Merge "Provide non-blocking SurfaceView draw notification path."
diff --git a/Android.mk b/Android.mk
index 7c9397f..ef97549 100644
--- a/Android.mk
+++ b/Android.mk
@@ -82,7 +82,6 @@
core/java/android/app/IBackupAgent.aidl \
core/java/android/app/IEphemeralResolver.aidl \
core/java/android/app/IInstrumentationWatcher.aidl \
- core/java/android/app/IOnNotificationChannelCreatedListener.aidl \
core/java/android/app/INotificationManager.aidl \
core/java/android/app/IProcessObserver.aidl \
core/java/android/app/ISearchManager.aidl \
@@ -108,6 +107,7 @@
core/java/android/app/backup/IFullBackupRestoreObserver.aidl \
core/java/android/app/backup/IRestoreObserver.aidl \
core/java/android/app/backup/IRestoreSession.aidl \
+ core/java/android/app/usage/IStorageStatsManager.aidl \
core/java/android/app/usage/IUsageStatsManager.aidl \
core/java/android/bluetooth/IBluetooth.aidl \
core/java/android/bluetooth/IBluetoothA2dp.aidl \
@@ -689,6 +689,8 @@
frameworks/base/core/java/android/service/notification/StatusBarNotification.aidl \
frameworks/base/core/java/android/service/chooser/ChooserTarget.aidl \
frameworks/base/core/java/android/speech/tts/Voice.aidl \
+ frameworks/base/core/java/android/app/usage/ExternalStorageStats.aidl \
+ frameworks/base/core/java/android/app/usage/StorageStats.aidl \
frameworks/base/core/java/android/app/usage/UsageEvents.aidl \
frameworks/base/core/java/android/app/Notification.aidl \
frameworks/base/core/java/android/app/NotificationManager.aidl \
diff --git a/api/current.txt b/api/current.txt
index 196b5f2..c38b5a8 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -5393,7 +5393,6 @@
method public android.net.Uri getSound();
method public long[] getVibrationPattern();
method public boolean isAllowed();
- method public void setAllowed(boolean);
method public void setBypassDnd(boolean);
method public void setImportance(int);
method public void setLights(boolean);
@@ -5414,7 +5413,8 @@
method public void cancel(int);
method public void cancel(java.lang.String, int);
method public void cancelAll();
- method public void createNotificationChannel(android.app.NotificationChannel, android.app.NotificationManager.OnNotificationChannelCreatedListener, android.os.Handler);
+ method public void createNotificationChannel(android.app.NotificationChannel);
+ method public void createNotificationChannels(java.util.List<android.app.NotificationChannel>);
method public void deleteNotificationChannel(java.lang.String);
method public android.service.notification.StatusBarNotification[] getActiveNotifications();
method public android.app.AutomaticZenRule getAutomaticZenRule(java.lang.String);
@@ -5448,10 +5448,6 @@
field public static final int INTERRUPTION_FILTER_UNKNOWN = 0; // 0x0
}
- public static abstract interface NotificationManager.OnNotificationChannelCreatedListener {
- method public abstract void onNotificationChannelCreated(android.app.NotificationChannel);
- }
-
public static class NotificationManager.Policy implements android.os.Parcelable {
ctor public NotificationManager.Policy(int, int, int);
ctor public NotificationManager.Policy(int, int, int, int);
@@ -6135,6 +6131,7 @@
method public boolean isSecurityLoggingEnabled(android.content.ComponentName);
method public boolean isUninstallBlocked(android.content.ComponentName, java.lang.String);
method public void lockNow();
+ method public void lockNow(int);
method public void reboot(android.content.ComponentName);
method public void removeActiveAdmin(android.content.ComponentName);
method public boolean removeCrossProfileWidgetProvider(android.content.ComponentName, java.lang.String);
@@ -6251,6 +6248,7 @@
field public static final java.lang.String EXTRA_PROVISIONING_WIFI_PROXY_PORT = "android.app.extra.PROVISIONING_WIFI_PROXY_PORT";
field public static final java.lang.String EXTRA_PROVISIONING_WIFI_SECURITY_TYPE = "android.app.extra.PROVISIONING_WIFI_SECURITY_TYPE";
field public static final java.lang.String EXTRA_PROVISIONING_WIFI_SSID = "android.app.extra.PROVISIONING_WIFI_SSID";
+ field public static final int FLAG_EVICT_CE_KEY = 1; // 0x1
field public static final int FLAG_MANAGED_CAN_ACCESS_PARENT = 2; // 0x2
field public static final int FLAG_PARENT_CAN_ACCESS_MANAGED = 1; // 0x1
field public static final int KEYGUARD_DISABLE_FEATURES_ALL = 2147483647; // 0x7fffffff
@@ -6628,6 +6626,16 @@
field public static final android.os.Parcelable.Creator<android.app.usage.ConfigurationStats> CREATOR;
}
+ public final class ExternalStorageStats implements android.os.Parcelable {
+ method public int describeContents();
+ method public long getAudioBytes();
+ method public long getImageBytes();
+ method public long getTotalBytes();
+ method public long getVideoBytes();
+ method public void writeToParcel(android.os.Parcel, int);
+ field public static final android.os.Parcelable.Creator<android.app.usage.ExternalStorageStats> CREATOR;
+ }
+
public final class NetworkStats implements java.lang.AutoCloseable {
method public void close();
method public boolean getNextBucket(android.app.usage.NetworkStats.Bucket);
@@ -6679,6 +6687,23 @@
method public abstract void onThresholdReached(int, java.lang.String);
}
+ public final class StorageStats implements android.os.Parcelable {
+ method public int describeContents();
+ method public long getCacheBytes();
+ method public long getCodeBytes();
+ method public long getDataBytes();
+ method public void writeToParcel(android.os.Parcel, int);
+ field public static final android.os.Parcelable.Creator<android.app.usage.StorageStats> CREATOR;
+ }
+
+ public class StorageStatsManager {
+ method public long getFreeBytes(java.lang.String);
+ method public long getTotalBytes(java.lang.String);
+ method public android.app.usage.ExternalStorageStats queryExternalStatsForUser(java.lang.String, android.os.UserHandle);
+ method public android.app.usage.StorageStats queryStatsForUid(java.lang.String, int);
+ method public android.app.usage.StorageStats queryStatsForUser(java.lang.String, android.os.UserHandle);
+ }
+
public final class UsageEvents implements android.os.Parcelable {
method public int describeContents();
method public boolean getNextEvent(android.app.usage.UsageEvents.Event);
@@ -6778,6 +6803,7 @@
method public void notifyAppWidgetViewDataChanged(int, int);
method public void partiallyUpdateAppWidget(int[], android.widget.RemoteViews);
method public void partiallyUpdateAppWidget(int, android.widget.RemoteViews);
+ method public boolean requestPinAppWidget(android.content.ComponentName, android.app.PendingIntent);
method public void updateAppWidget(int[], android.widget.RemoteViews);
method public void updateAppWidget(int, android.widget.RemoteViews);
method public void updateAppWidget(android.content.ComponentName, android.widget.RemoteViews);
@@ -8414,6 +8440,7 @@
field public static final java.lang.String SENSOR_SERVICE = "sensor";
field public static final java.lang.String SHORTCUT_SERVICE = "shortcut";
field public static final java.lang.String STORAGE_SERVICE = "storage";
+ field public static final java.lang.String STORAGE_STATS_SERVICE = "storagestats";
field public static final java.lang.String SYSTEM_HEALTH_SERVICE = "systemhealth";
field public static final java.lang.String TELECOM_SERVICE = "telecom";
field public static final java.lang.String TELEPHONY_SERVICE = "phone";
@@ -9761,11 +9788,13 @@
method public boolean accept(android.os.Bundle);
method public boolean accept();
method public int describeContents();
+ method public android.appwidget.AppWidgetProviderInfo getAppWidgetProviderInfo();
method public int getRequestType();
method public android.content.pm.ShortcutInfo getShortcutInfo();
method public boolean isValid();
method public void writeToParcel(android.os.Parcel, int);
field public static final android.os.Parcelable.Creator<android.content.pm.LauncherApps.PinItemRequest> CREATOR;
+ field public static final int REQUEST_TYPE_APPWIDGET = 2; // 0x2
field public static final int REQUEST_TYPE_SHORTCUT = 1; // 0x1
}
@@ -11946,8 +11975,6 @@
method public boolean clipRect(float, float, float, float, android.graphics.Region.Op);
method public boolean clipRect(float, float, float, float);
method public boolean clipRect(int, int, int, int);
- method public deprecated boolean clipRegion(android.graphics.Region, android.graphics.Region.Op);
- method public deprecated boolean clipRegion(android.graphics.Region);
method public void concat(android.graphics.Matrix);
method public void drawARGB(int, int, int, int);
method public void drawArc(android.graphics.RectF, float, float, boolean, android.graphics.Paint);
@@ -30906,6 +30933,7 @@
field public static final java.lang.String ACTION_SET_ALARM = "android.intent.action.SET_ALARM";
field public static final java.lang.String ACTION_SET_TIMER = "android.intent.action.SET_TIMER";
field public static final java.lang.String ACTION_SHOW_ALARMS = "android.intent.action.SHOW_ALARMS";
+ field public static final java.lang.String ACTION_SHOW_TIMERS = "android.intent.action.SHOW_TIMERS";
field public static final java.lang.String ACTION_SNOOZE_ALARM = "android.intent.action.SNOOZE_ALARM";
field public static final java.lang.String ALARM_SEARCH_MODE_ALL = "android.all";
field public static final java.lang.String ALARM_SEARCH_MODE_LABEL = "android.label";
@@ -36698,6 +36726,7 @@
method public void unhold();
method public void unregisterCallback(android.telecom.Call.Callback);
field public static final java.lang.String AVAILABLE_PHONE_ACCOUNTS = "selectPhoneAccountAccounts";
+ field public static final java.lang.String EXTRA_LAST_EMERGENCY_CALLBACK_TIME_MILLIS = "android.telecom.extra.LAST_EMERGENCY_CALLBACK_TIME_MILLIS";
field public static final int STATE_ACTIVE = 4; // 0x4
field public static final int STATE_CONNECTING = 9; // 0x9
field public static final int STATE_DIALING = 1; // 0x1
@@ -41816,7 +41845,7 @@
method public android.view.View findNearestTouchable(android.view.ViewGroup, int, int, int, int[]);
method public final android.view.View findNextFocus(android.view.ViewGroup, android.view.View, int);
method public android.view.View findNextFocusFromRect(android.view.ViewGroup, android.graphics.Rect, int);
- method public android.view.View findNextKeyboardNavigationCluster(android.view.ViewGroup, android.view.View, int);
+ method public android.view.View findNextKeyboardNavigationGroup(int, android.view.View, android.view.View, int);
method public static android.view.FocusFinder getInstance();
}
@@ -42590,6 +42619,7 @@
method public abstract android.view.ActionProvider getActionProvider();
method public abstract android.view.View getActionView();
method public abstract char getAlphabeticShortcut();
+ method public default java.lang.CharSequence getContentDescription();
method public abstract int getGroupId();
method public abstract android.graphics.drawable.Drawable getIcon();
method public abstract android.content.Intent getIntent();
@@ -42600,6 +42630,7 @@
method public abstract android.view.SubMenu getSubMenu();
method public abstract java.lang.CharSequence getTitle();
method public abstract java.lang.CharSequence getTitleCondensed();
+ method public default java.lang.CharSequence getTooltip();
method public abstract boolean hasSubMenu();
method public abstract boolean isActionViewExpanded();
method public abstract boolean isCheckable();
@@ -42612,6 +42643,7 @@
method public abstract android.view.MenuItem setAlphabeticShortcut(char);
method public abstract android.view.MenuItem setCheckable(boolean);
method public abstract android.view.MenuItem setChecked(boolean);
+ method public default android.view.MenuItem setContentDescription(java.lang.CharSequence);
method public abstract android.view.MenuItem setEnabled(boolean);
method public abstract android.view.MenuItem setIcon(android.graphics.drawable.Drawable);
method public abstract android.view.MenuItem setIcon(int);
@@ -42625,6 +42657,7 @@
method public abstract android.view.MenuItem setTitle(java.lang.CharSequence);
method public abstract android.view.MenuItem setTitle(int);
method public abstract android.view.MenuItem setTitleCondensed(java.lang.CharSequence);
+ method public default android.view.MenuItem setTooltip(java.lang.CharSequence);
method public abstract android.view.MenuItem setVisible(boolean);
field public static final int SHOW_AS_ACTION_ALWAYS = 2; // 0x2
field public static final int SHOW_AS_ACTION_COLLAPSE_ACTION_VIEW = 8; // 0x8
@@ -43110,7 +43143,7 @@
method public void addChildrenForAccessibility(java.util.ArrayList<android.view.View>);
method public void addFocusables(java.util.ArrayList<android.view.View>, int);
method public void addFocusables(java.util.ArrayList<android.view.View>, int, int);
- method public void addKeyboardNavigationClusters(java.util.Collection<android.view.View>, int);
+ method public void addKeyboardNavigationGroups(int, java.util.Collection<android.view.View>, int);
method public void addOnAttachStateChangeListener(android.view.View.OnAttachStateChangeListener);
method public void addOnLayoutChangeListener(android.view.View.OnLayoutChangeListener);
method public void addTouchables(java.util.ArrayList<android.view.View>);
@@ -43398,7 +43431,7 @@
method public boolean isVerticalFadingEdgeEnabled();
method public boolean isVerticalScrollBarEnabled();
method public void jumpDrawablesToCurrentState();
- method public android.view.View keyboardNavigationClusterSearch(int);
+ method public android.view.View keyboardNavigationGroupSearch(int, android.view.View, int);
method public void layout(int, int, int, int);
method public final void measure(int, int);
method protected static int[] mergeDrawableStates(int[], int[]);
@@ -43691,6 +43724,8 @@
field public static final int IMPORTANT_FOR_ACCESSIBILITY_YES = 1; // 0x1
field public static final int INVISIBLE = 4; // 0x4
field public static final int KEEP_SCREEN_ON = 67108864; // 0x4000000
+ field public static final int KEYBOARD_NAVIGATION_GROUP_CLUSTER = 1; // 0x1
+ field public static final int KEYBOARD_NAVIGATION_GROUP_SECTION = 2; // 0x2
field public static final int LAYER_TYPE_HARDWARE = 2; // 0x2
field public static final int LAYER_TYPE_NONE = 0; // 0x0
field public static final int LAYER_TYPE_SOFTWARE = 1; // 0x1
@@ -44047,7 +44082,6 @@
method protected deprecated boolean isChildrenDrawnWithCacheEnabled();
method public boolean isMotionEventSplittingEnabled();
method public boolean isTransitionGroup();
- method public android.view.View keyboardNavigationClusterSearch(android.view.View, int);
method public final void layout(int, int, int, int);
method protected void measureChild(android.view.View, int, int);
method protected void measureChildWithMargins(android.view.View, int, int, int, int);
@@ -44210,7 +44244,7 @@
method public abstract boolean isLayoutRequested();
method public abstract boolean isTextAlignmentResolved();
method public abstract boolean isTextDirectionResolved();
- method public abstract android.view.View keyboardNavigationClusterSearch(android.view.View, int);
+ method public abstract android.view.View keyboardNavigationGroupSearch(int, android.view.View, int);
method public abstract void notifySubtreeAccessibilityStateChanged(android.view.View, android.view.View, int);
method public abstract boolean onNestedFling(android.view.View, float, float, boolean);
method public abstract boolean onNestedPreFling(android.view.View, float, float);
@@ -46137,6 +46171,11 @@
method public abstract android.view.View getFullScreenView(int, android.content.Context);
}
+ public abstract class RenderProcessGoneDetail {
+ ctor public RenderProcessGoneDetail();
+ method public abstract boolean didCrash();
+ }
+
public class ServiceWorkerClient {
ctor public ServiceWorkerClient();
method public android.webkit.WebResourceResponse shouldInterceptRequest(android.webkit.WebResourceRequest);
@@ -46661,6 +46700,7 @@
method public void onReceivedHttpError(android.webkit.WebView, android.webkit.WebResourceRequest, android.webkit.WebResourceResponse);
method public void onReceivedLoginRequest(android.webkit.WebView, java.lang.String, java.lang.String, java.lang.String);
method public void onReceivedSslError(android.webkit.WebView, android.webkit.SslErrorHandler, android.net.http.SslError);
+ method public boolean onRenderProcessGone(android.webkit.WebView, android.webkit.RenderProcessGoneDetail);
method public void onScaleChanged(android.webkit.WebView, float, float);
method public deprecated void onTooManyRedirects(android.webkit.WebView, android.os.Message, android.os.Message);
method public void onUnhandledKeyEvent(android.webkit.WebView, android.view.KeyEvent);
diff --git a/api/removed.txt b/api/removed.txt
index 10e6eb5..d7a8bce 100644
--- a/api/removed.txt
+++ b/api/removed.txt
@@ -78,6 +78,11 @@
enum_constant public static final android.graphics.AvoidXfermode.Mode TARGET;
}
+ public class Canvas {
+ method public deprecated boolean clipRegion(android.graphics.Region, android.graphics.Region.Op);
+ method public deprecated boolean clipRegion(android.graphics.Region);
+ }
+
public deprecated class LayerRasterizer extends android.graphics.Rasterizer {
ctor public LayerRasterizer();
method public void addLayer(android.graphics.Paint, float, float);
@@ -99,67 +104,6 @@
}
-package android.location {
-
- public final class GnssMeasurement implements android.os.Parcelable {
- field public static final int MULTIPATH_INDICATOR_NOT_USED = 2; // 0x2
- }
-
- public final class GnssMeasurementsEvent implements android.os.Parcelable {
- field public static final int STATUS_GNSS_LOCATION_DISABLED = 2; // 0x2
- field public static final int STATUS_NOT_SUPPORTED = 0; // 0x0
- field public static final int STATUS_READY = 1; // 0x1
- }
-
- public final class GnssNavigationMessageEvent implements android.os.Parcelable {
- ctor public GnssNavigationMessageEvent(android.location.GnssNavigationMessage);
- method public int describeContents();
- method public android.location.GnssNavigationMessage getNavigationMessage();
- method public void writeToParcel(android.os.Parcel, int);
- field public static final android.os.Parcelable.Creator<android.location.GnssNavigationMessageEvent> CREATOR;
- field public static final int STATUS_GNSS_LOCATION_DISABLED = 2; // 0x2
- field public static final int STATUS_NOT_SUPPORTED = 0; // 0x0
- field public static final int STATUS_READY = 1; // 0x1
- }
-
- public static abstract class GnssNavigationMessageEvent.Callback {
- ctor public GnssNavigationMessageEvent.Callback();
- method public void onGnssNavigationMessageReceived(android.location.GnssNavigationMessageEvent);
- method public void onStatusChanged(int);
- }
-
- public abstract interface GnssNmeaListener {
- method public abstract void onNmeaReceived(long, java.lang.String);
- }
-
- public final class GnssStatus {
- method public int getNumSatellites();
- method public boolean hasAlmanac(int);
- method public boolean hasEphemeris(int);
- }
-
- public abstract class GnssStatusCallback {
- ctor public GnssStatusCallback();
- method public void onFirstFix(int);
- method public void onSatelliteStatusChanged(android.location.GnssStatus);
- method public void onStarted();
- method public void onStopped();
- }
-
- public class LocationManager {
- method public boolean addNmeaListener(android.location.GnssNmeaListener);
- method public boolean addNmeaListener(android.location.GnssNmeaListener, android.os.Handler);
- method public boolean registerGnssNavigationMessageCallback(android.location.GnssNavigationMessageEvent.Callback);
- method public boolean registerGnssNavigationMessageCallback(android.location.GnssNavigationMessageEvent.Callback, android.os.Handler);
- method public boolean registerGnssStatusCallback(android.location.GnssStatusCallback);
- method public boolean registerGnssStatusCallback(android.location.GnssStatusCallback, android.os.Handler);
- method public void removeNmeaListener(android.location.GnssNmeaListener);
- method public void unregisterGnssNavigationMessageCallback(android.location.GnssNavigationMessageEvent.Callback);
- method public void unregisterGnssStatusCallback(android.location.GnssStatusCallback);
- }
-
-}
-
package android.media {
public final class AudioFormat implements android.os.Parcelable {
diff --git a/api/system-current.txt b/api/system-current.txt
index 5a1f880..0d116f6 100644
--- a/api/system-current.txt
+++ b/api/system-current.txt
@@ -66,7 +66,7 @@
field public static final java.lang.String BLUETOOTH_PRIVILEGED = "android.permission.BLUETOOTH_PRIVILEGED";
field public static final java.lang.String BODY_SENSORS = "android.permission.BODY_SENSORS";
field public static final java.lang.String BRICK = "android.permission.BRICK";
- field public static final java.lang.String BROADCAST_NETWORK_PRIVILEGED = "android.permission.BROADCAST_NETWORK_PRIVILEGED";
+ field public static final deprecated java.lang.String BROADCAST_NETWORK_PRIVILEGED = "android.permission.BROADCAST_NETWORK_PRIVILEGED";
field public static final java.lang.String BROADCAST_PACKAGE_REMOVED = "android.permission.BROADCAST_PACKAGE_REMOVED";
field public static final java.lang.String BROADCAST_SMS = "android.permission.BROADCAST_SMS";
field public static final java.lang.String BROADCAST_STICKY = "android.permission.BROADCAST_STICKY";
@@ -201,6 +201,7 @@
field public static final java.lang.String REORDER_TASKS = "android.permission.REORDER_TASKS";
field public static final java.lang.String REQUEST_IGNORE_BATTERY_OPTIMIZATIONS = "android.permission.REQUEST_IGNORE_BATTERY_OPTIMIZATIONS";
field public static final java.lang.String REQUEST_INSTALL_PACKAGES = "android.permission.REQUEST_INSTALL_PACKAGES";
+ field public static final java.lang.String REQUEST_NETWORK_SCORES = "android.permission.REQUEST_NETWORK_SCORES";
field public static final deprecated java.lang.String RESTART_PACKAGES = "android.permission.RESTART_PACKAGES";
field public static final java.lang.String RETRIEVE_WINDOW_CONTENT = "android.permission.RETRIEVE_WINDOW_CONTENT";
field public static final java.lang.String REVOKE_RUNTIME_PERMISSIONS = "android.permission.REVOKE_RUNTIME_PERMISSIONS";
@@ -5554,7 +5555,6 @@
method public boolean isAllowed();
method public void lockFields(int);
method public void populateFromXml(org.xmlpull.v1.XmlPullParser);
- method public void setAllowed(boolean);
method public void setBypassDnd(boolean);
method public void setImportance(int);
method public void setLights(boolean);
@@ -5586,7 +5586,8 @@
method public void cancel(int);
method public void cancel(java.lang.String, int);
method public void cancelAll();
- method public void createNotificationChannel(android.app.NotificationChannel, android.app.NotificationManager.OnNotificationChannelCreatedListener, android.os.Handler);
+ method public void createNotificationChannel(android.app.NotificationChannel);
+ method public void createNotificationChannels(java.util.List<android.app.NotificationChannel>);
method public void deleteNotificationChannel(java.lang.String);
method public android.service.notification.StatusBarNotification[] getActiveNotifications();
method public android.app.AutomaticZenRule getAutomaticZenRule(java.lang.String);
@@ -5620,10 +5621,6 @@
field public static final int INTERRUPTION_FILTER_UNKNOWN = 0; // 0x0
}
- public static abstract interface NotificationManager.OnNotificationChannelCreatedListener {
- method public abstract void onNotificationChannelCreated(android.app.NotificationChannel);
- }
-
public static class NotificationManager.Policy implements android.os.Parcelable {
ctor public NotificationManager.Policy(int, int, int);
ctor public NotificationManager.Policy(int, int, int, int);
@@ -6325,6 +6322,7 @@
method public boolean isSecurityLoggingEnabled(android.content.ComponentName);
method public boolean isUninstallBlocked(android.content.ComponentName, java.lang.String);
method public void lockNow();
+ method public void lockNow(int);
method public void notifyPendingSystemUpdate(long);
method public void reboot(android.content.ComponentName);
method public void removeActiveAdmin(android.content.ComponentName);
@@ -6448,6 +6446,7 @@
field public static final java.lang.String EXTRA_PROVISIONING_WIFI_PROXY_PORT = "android.app.extra.PROVISIONING_WIFI_PROXY_PORT";
field public static final java.lang.String EXTRA_PROVISIONING_WIFI_SECURITY_TYPE = "android.app.extra.PROVISIONING_WIFI_SECURITY_TYPE";
field public static final java.lang.String EXTRA_PROVISIONING_WIFI_SSID = "android.app.extra.PROVISIONING_WIFI_SSID";
+ field public static final int FLAG_EVICT_CE_KEY = 1; // 0x1
field public static final int FLAG_MANAGED_CAN_ACCESS_PARENT = 2; // 0x2
field public static final int FLAG_PARENT_CAN_ACCESS_MANAGED = 1; // 0x1
field public static final int KEYGUARD_DISABLE_FEATURES_ALL = 2147483647; // 0x7fffffff
@@ -6940,6 +6939,16 @@
field public static final android.os.Parcelable.Creator<android.app.usage.ConfigurationStats> CREATOR;
}
+ public final class ExternalStorageStats implements android.os.Parcelable {
+ method public int describeContents();
+ method public long getAudioBytes();
+ method public long getImageBytes();
+ method public long getTotalBytes();
+ method public long getVideoBytes();
+ method public void writeToParcel(android.os.Parcel, int);
+ field public static final android.os.Parcelable.Creator<android.app.usage.ExternalStorageStats> CREATOR;
+ }
+
public final class NetworkStats implements java.lang.AutoCloseable {
method public void close();
method public boolean getNextBucket(android.app.usage.NetworkStats.Bucket);
@@ -6991,6 +7000,23 @@
method public abstract void onThresholdReached(int, java.lang.String);
}
+ public final class StorageStats implements android.os.Parcelable {
+ method public int describeContents();
+ method public long getCacheBytes();
+ method public long getCodeBytes();
+ method public long getDataBytes();
+ method public void writeToParcel(android.os.Parcel, int);
+ field public static final android.os.Parcelable.Creator<android.app.usage.StorageStats> CREATOR;
+ }
+
+ public class StorageStatsManager {
+ method public long getFreeBytes(java.lang.String);
+ method public long getTotalBytes(java.lang.String);
+ method public android.app.usage.ExternalStorageStats queryExternalStatsForUser(java.lang.String, android.os.UserHandle);
+ method public android.app.usage.StorageStats queryStatsForUid(java.lang.String, int);
+ method public android.app.usage.StorageStats queryStatsForUser(java.lang.String, android.os.UserHandle);
+ }
+
public final class UsageEvents implements android.os.Parcelable {
method public int describeContents();
method public boolean getNextEvent(android.app.usage.UsageEvents.Event);
@@ -7091,6 +7117,7 @@
method public void notifyAppWidgetViewDataChanged(int, int);
method public void partiallyUpdateAppWidget(int[], android.widget.RemoteViews);
method public void partiallyUpdateAppWidget(int, android.widget.RemoteViews);
+ method public boolean requestPinAppWidget(android.content.ComponentName, android.app.PendingIntent);
method public void updateAppWidget(int[], android.widget.RemoteViews);
method public void updateAppWidget(int, android.widget.RemoteViews);
method public void updateAppWidget(android.content.ComponentName, android.widget.RemoteViews);
@@ -8768,6 +8795,7 @@
field public static final java.lang.String SENSOR_SERVICE = "sensor";
field public static final java.lang.String SHORTCUT_SERVICE = "shortcut";
field public static final java.lang.String STORAGE_SERVICE = "storage";
+ field public static final java.lang.String STORAGE_STATS_SERVICE = "storagestats";
field public static final java.lang.String SYSTEM_HEALTH_SERVICE = "systemhealth";
field public static final java.lang.String TELECOM_SERVICE = "telecom";
field public static final java.lang.String TELEPHONY_SERVICE = "phone";
@@ -10171,11 +10199,13 @@
method public boolean accept(android.os.Bundle);
method public boolean accept();
method public int describeContents();
+ method public android.appwidget.AppWidgetProviderInfo getAppWidgetProviderInfo();
method public int getRequestType();
method public android.content.pm.ShortcutInfo getShortcutInfo();
method public boolean isValid();
method public void writeToParcel(android.os.Parcel, int);
field public static final android.os.Parcelable.Creator<android.content.pm.LauncherApps.PinItemRequest> CREATOR;
+ field public static final int REQUEST_TYPE_APPWIDGET = 2; // 0x2
field public static final int REQUEST_TYPE_SHORTCUT = 1; // 0x1
}
@@ -12443,8 +12473,6 @@
method public boolean clipRect(float, float, float, float, android.graphics.Region.Op);
method public boolean clipRect(float, float, float, float);
method public boolean clipRect(int, int, int, int);
- method public deprecated boolean clipRegion(android.graphics.Region, android.graphics.Region.Op);
- method public deprecated boolean clipRegion(android.graphics.Region);
method public void concat(android.graphics.Matrix);
method public void drawARGB(int, int, int, int);
method public void drawArc(android.graphics.RectF, float, float, boolean, android.graphics.Paint);
@@ -26175,6 +26203,14 @@
field public static final android.os.Parcelable.Creator<android.net.RecommendationRequest> CREATOR;
}
+ public static final class RecommendationRequest.Builder {
+ ctor public RecommendationRequest.Builder();
+ method public android.net.RecommendationRequest build();
+ method public android.net.RecommendationRequest.Builder setCurrentRecommendedWifiConfig(android.net.wifi.WifiConfiguration);
+ method public android.net.RecommendationRequest.Builder setNetworkCapabilities(android.net.NetworkCapabilities);
+ method public android.net.RecommendationRequest.Builder setScanResults(android.net.wifi.ScanResult[]);
+ }
+
public final class RecommendationResult implements android.os.Parcelable {
method public static android.net.RecommendationResult createConnectRecommendation(android.net.wifi.WifiConfiguration);
method public static android.net.RecommendationResult createDoNotConnectRecommendation();
@@ -26239,10 +26275,16 @@
ctor public ScoredNetwork(android.net.NetworkKey, android.net.RssiCurve);
ctor public ScoredNetwork(android.net.NetworkKey, android.net.RssiCurve, boolean);
ctor public ScoredNetwork(android.net.NetworkKey, android.net.RssiCurve, boolean, android.os.Bundle);
+ method public int calculateBadge(int);
method public int describeContents();
method public void writeToParcel(android.os.Parcel, int);
+ field public static final java.lang.String ATTRIBUTES_KEY_BADGING_CURVE = "android.net.attributes.key.BADGING_CURVE";
field public static final java.lang.String ATTRIBUTES_KEY_HAS_CAPTIVE_PORTAL = "android.net.attributes.key.HAS_CAPTIVE_PORTAL";
field public static final java.lang.String ATTRIBUTES_KEY_RANKING_SCORE_OFFSET = "android.net.attributes.key.RANKING_SCORE_OFFSET";
+ field public static final int BADGING_4K = 30; // 0x1e
+ field public static final int BADGING_HD = 20; // 0x14
+ field public static final int BADGING_NONE = 0; // 0x0
+ field public static final int BADGING_SD = 10; // 0xa
field public static final android.os.Parcelable.Creator<android.net.ScoredNetwork> CREATOR;
field public final android.os.Bundle attributes;
field public final boolean meteredHint;
@@ -26250,6 +26292,9 @@
field public final android.net.RssiCurve rssiCurve;
}
+ public static abstract class ScoredNetwork.Badging implements java.lang.annotation.Annotation {
+ }
+
public class TrafficStats {
ctor public TrafficStats();
method public static void clearThreadStatsTag();
@@ -27258,6 +27303,8 @@
public class WifiConfiguration implements android.os.Parcelable {
ctor public WifiConfiguration();
method public int describeContents();
+ method public boolean hasNoInternetAccess();
+ method public boolean isNoInternetAccessExpected();
method public boolean isPasspoint();
method public void writeToParcel(android.os.Parcel, int);
field public java.lang.String BSSID;
@@ -27430,6 +27477,7 @@
method public static int calculateSignalLevel(int, int);
method public void cancelWps(android.net.wifi.WifiManager.WpsCallback);
method public static int compareSignalLevel(int, int);
+ method public void connect(android.net.wifi.WifiConfiguration, android.net.wifi.WifiManager.ActionListener);
method public android.net.wifi.WifiManager.MulticastLock createMulticastLock(java.lang.String);
method public android.net.wifi.WifiManager.WifiLock createWifiLock(int, java.lang.String);
method public android.net.wifi.WifiManager.WifiLock createWifiLock(java.lang.String);
@@ -27529,6 +27577,11 @@
field public static final int WPS_WEP_PROHIBITED = 4; // 0x4
}
+ public static abstract interface WifiManager.ActionListener {
+ method public abstract void onFailure(int);
+ method public abstract void onSuccess();
+ }
+
public class WifiManager.MulticastLock {
method public void acquire();
method public boolean isHeld();
@@ -33600,6 +33653,7 @@
field public static final java.lang.String ACTION_SET_ALARM = "android.intent.action.SET_ALARM";
field public static final java.lang.String ACTION_SET_TIMER = "android.intent.action.SET_TIMER";
field public static final java.lang.String ACTION_SHOW_ALARMS = "android.intent.action.SHOW_ALARMS";
+ field public static final java.lang.String ACTION_SHOW_TIMERS = "android.intent.action.SHOW_TIMERS";
field public static final java.lang.String ACTION_SNOOZE_ALARM = "android.intent.action.SNOOZE_ALARM";
field public static final java.lang.String ALARM_SEARCH_MODE_ALL = "android.all";
field public static final java.lang.String ALARM_SEARCH_MODE_LABEL = "android.label";
@@ -39606,6 +39660,7 @@
method public void unhold();
method public void unregisterCallback(android.telecom.Call.Callback);
field public static final java.lang.String AVAILABLE_PHONE_ACCOUNTS = "selectPhoneAccountAccounts";
+ field public static final java.lang.String EXTRA_LAST_EMERGENCY_CALLBACK_TIME_MILLIS = "android.telecom.extra.LAST_EMERGENCY_CALLBACK_TIME_MILLIS";
field public static final int STATE_ACTIVE = 4; // 0x4
field public static final int STATE_CONNECTING = 9; // 0x9
field public static final int STATE_DIALING = 1; // 0x1
@@ -45008,7 +45063,7 @@
method public android.view.View findNearestTouchable(android.view.ViewGroup, int, int, int, int[]);
method public final android.view.View findNextFocus(android.view.ViewGroup, android.view.View, int);
method public android.view.View findNextFocusFromRect(android.view.ViewGroup, android.graphics.Rect, int);
- method public android.view.View findNextKeyboardNavigationCluster(android.view.ViewGroup, android.view.View, int);
+ method public android.view.View findNextKeyboardNavigationGroup(int, android.view.View, android.view.View, int);
method public static android.view.FocusFinder getInstance();
}
@@ -45782,6 +45837,7 @@
method public abstract android.view.ActionProvider getActionProvider();
method public abstract android.view.View getActionView();
method public abstract char getAlphabeticShortcut();
+ method public default java.lang.CharSequence getContentDescription();
method public abstract int getGroupId();
method public abstract android.graphics.drawable.Drawable getIcon();
method public abstract android.content.Intent getIntent();
@@ -45792,6 +45848,7 @@
method public abstract android.view.SubMenu getSubMenu();
method public abstract java.lang.CharSequence getTitle();
method public abstract java.lang.CharSequence getTitleCondensed();
+ method public default java.lang.CharSequence getTooltip();
method public abstract boolean hasSubMenu();
method public abstract boolean isActionViewExpanded();
method public abstract boolean isCheckable();
@@ -45804,6 +45861,7 @@
method public abstract android.view.MenuItem setAlphabeticShortcut(char);
method public abstract android.view.MenuItem setCheckable(boolean);
method public abstract android.view.MenuItem setChecked(boolean);
+ method public default android.view.MenuItem setContentDescription(java.lang.CharSequence);
method public abstract android.view.MenuItem setEnabled(boolean);
method public abstract android.view.MenuItem setIcon(android.graphics.drawable.Drawable);
method public abstract android.view.MenuItem setIcon(int);
@@ -45817,6 +45875,7 @@
method public abstract android.view.MenuItem setTitle(java.lang.CharSequence);
method public abstract android.view.MenuItem setTitle(int);
method public abstract android.view.MenuItem setTitleCondensed(java.lang.CharSequence);
+ method public default android.view.MenuItem setTooltip(java.lang.CharSequence);
method public abstract android.view.MenuItem setVisible(boolean);
field public static final int SHOW_AS_ACTION_ALWAYS = 2; // 0x2
field public static final int SHOW_AS_ACTION_COLLAPSE_ACTION_VIEW = 8; // 0x8
@@ -46302,7 +46361,7 @@
method public void addChildrenForAccessibility(java.util.ArrayList<android.view.View>);
method public void addFocusables(java.util.ArrayList<android.view.View>, int);
method public void addFocusables(java.util.ArrayList<android.view.View>, int, int);
- method public void addKeyboardNavigationClusters(java.util.Collection<android.view.View>, int);
+ method public void addKeyboardNavigationGroups(int, java.util.Collection<android.view.View>, int);
method public void addOnAttachStateChangeListener(android.view.View.OnAttachStateChangeListener);
method public void addOnLayoutChangeListener(android.view.View.OnLayoutChangeListener);
method public void addTouchables(java.util.ArrayList<android.view.View>);
@@ -46590,7 +46649,7 @@
method public boolean isVerticalFadingEdgeEnabled();
method public boolean isVerticalScrollBarEnabled();
method public void jumpDrawablesToCurrentState();
- method public android.view.View keyboardNavigationClusterSearch(int);
+ method public android.view.View keyboardNavigationGroupSearch(int, android.view.View, int);
method public void layout(int, int, int, int);
method public final void measure(int, int);
method protected static int[] mergeDrawableStates(int[], int[]);
@@ -46883,6 +46942,8 @@
field public static final int IMPORTANT_FOR_ACCESSIBILITY_YES = 1; // 0x1
field public static final int INVISIBLE = 4; // 0x4
field public static final int KEEP_SCREEN_ON = 67108864; // 0x4000000
+ field public static final int KEYBOARD_NAVIGATION_GROUP_CLUSTER = 1; // 0x1
+ field public static final int KEYBOARD_NAVIGATION_GROUP_SECTION = 2; // 0x2
field public static final int LAYER_TYPE_HARDWARE = 2; // 0x2
field public static final int LAYER_TYPE_NONE = 0; // 0x0
field public static final int LAYER_TYPE_SOFTWARE = 1; // 0x1
@@ -47239,7 +47300,6 @@
method protected deprecated boolean isChildrenDrawnWithCacheEnabled();
method public boolean isMotionEventSplittingEnabled();
method public boolean isTransitionGroup();
- method public android.view.View keyboardNavigationClusterSearch(android.view.View, int);
method public final void layout(int, int, int, int);
method protected void measureChild(android.view.View, int, int);
method protected void measureChildWithMargins(android.view.View, int, int, int, int);
@@ -47402,7 +47462,7 @@
method public abstract boolean isLayoutRequested();
method public abstract boolean isTextAlignmentResolved();
method public abstract boolean isTextDirectionResolved();
- method public abstract android.view.View keyboardNavigationClusterSearch(android.view.View, int);
+ method public abstract android.view.View keyboardNavigationGroupSearch(int, android.view.View, int);
method public abstract void notifySubtreeAccessibilityStateChanged(android.view.View, android.view.View, int);
method public abstract boolean onNestedFling(android.view.View, float, float, boolean);
method public abstract boolean onNestedPreFling(android.view.View, float, float);
@@ -49386,6 +49446,11 @@
method public abstract android.view.View getFullScreenView(int, android.content.Context);
}
+ public abstract class RenderProcessGoneDetail {
+ ctor public RenderProcessGoneDetail();
+ method public abstract boolean didCrash();
+ }
+
public class ServiceWorkerClient {
ctor public ServiceWorkerClient();
method public android.webkit.WebResourceResponse shouldInterceptRequest(android.webkit.WebResourceRequest);
@@ -49981,6 +50046,7 @@
method public void onReceivedHttpError(android.webkit.WebView, android.webkit.WebResourceRequest, android.webkit.WebResourceResponse);
method public void onReceivedLoginRequest(android.webkit.WebView, java.lang.String, java.lang.String, java.lang.String);
method public void onReceivedSslError(android.webkit.WebView, android.webkit.SslErrorHandler, android.net.http.SslError);
+ method public boolean onRenderProcessGone(android.webkit.WebView, android.webkit.RenderProcessGoneDetail);
method public void onScaleChanged(android.webkit.WebView, float, float);
method public deprecated void onTooManyRedirects(android.webkit.WebView, android.os.Message, android.os.Message);
method public void onUnhandledKeyEvent(android.webkit.WebView, android.view.KeyEvent);
diff --git a/api/system-removed.txt b/api/system-removed.txt
index 0919b8f..7ba88bd 100644
--- a/api/system-removed.txt
+++ b/api/system-removed.txt
@@ -76,6 +76,11 @@
enum_constant public static final android.graphics.AvoidXfermode.Mode TARGET;
}
+ public class Canvas {
+ method public deprecated boolean clipRegion(android.graphics.Region, android.graphics.Region.Op);
+ method public deprecated boolean clipRegion(android.graphics.Region);
+ }
+
public deprecated class LayerRasterizer extends android.graphics.Rasterizer {
ctor public LayerRasterizer();
method public void addLayer(android.graphics.Paint, float, float);
@@ -97,67 +102,6 @@
}
-package android.location {
-
- public final class GnssMeasurement implements android.os.Parcelable {
- field public static final int MULTIPATH_INDICATOR_NOT_USED = 2; // 0x2
- }
-
- public final class GnssMeasurementsEvent implements android.os.Parcelable {
- field public static final int STATUS_GNSS_LOCATION_DISABLED = 2; // 0x2
- field public static final int STATUS_NOT_SUPPORTED = 0; // 0x0
- field public static final int STATUS_READY = 1; // 0x1
- }
-
- public final class GnssNavigationMessageEvent implements android.os.Parcelable {
- ctor public GnssNavigationMessageEvent(android.location.GnssNavigationMessage);
- method public int describeContents();
- method public android.location.GnssNavigationMessage getNavigationMessage();
- method public void writeToParcel(android.os.Parcel, int);
- field public static final android.os.Parcelable.Creator<android.location.GnssNavigationMessageEvent> CREATOR;
- field public static final int STATUS_GNSS_LOCATION_DISABLED = 2; // 0x2
- field public static final int STATUS_NOT_SUPPORTED = 0; // 0x0
- field public static final int STATUS_READY = 1; // 0x1
- }
-
- public static abstract class GnssNavigationMessageEvent.Callback {
- ctor public GnssNavigationMessageEvent.Callback();
- method public void onGnssNavigationMessageReceived(android.location.GnssNavigationMessageEvent);
- method public void onStatusChanged(int);
- }
-
- public abstract interface GnssNmeaListener {
- method public abstract void onNmeaReceived(long, java.lang.String);
- }
-
- public final class GnssStatus {
- method public int getNumSatellites();
- method public boolean hasAlmanac(int);
- method public boolean hasEphemeris(int);
- }
-
- public abstract class GnssStatusCallback {
- ctor public GnssStatusCallback();
- method public void onFirstFix(int);
- method public void onSatelliteStatusChanged(android.location.GnssStatus);
- method public void onStarted();
- method public void onStopped();
- }
-
- public class LocationManager {
- method public boolean addNmeaListener(android.location.GnssNmeaListener);
- method public boolean addNmeaListener(android.location.GnssNmeaListener, android.os.Handler);
- method public boolean registerGnssNavigationMessageCallback(android.location.GnssNavigationMessageEvent.Callback);
- method public boolean registerGnssNavigationMessageCallback(android.location.GnssNavigationMessageEvent.Callback, android.os.Handler);
- method public boolean registerGnssStatusCallback(android.location.GnssStatusCallback);
- method public boolean registerGnssStatusCallback(android.location.GnssStatusCallback, android.os.Handler);
- method public void removeNmeaListener(android.location.GnssNmeaListener);
- method public void unregisterGnssNavigationMessageCallback(android.location.GnssNavigationMessageEvent.Callback);
- method public void unregisterGnssStatusCallback(android.location.GnssStatusCallback);
- }
-
-}
-
package android.media {
public final class AudioFormat implements android.os.Parcelable {
diff --git a/api/test-current.txt b/api/test-current.txt
index e67f2ce..bdda72e 100644
--- a/api/test-current.txt
+++ b/api/test-current.txt
@@ -5403,7 +5403,6 @@
method public android.net.Uri getSound();
method public long[] getVibrationPattern();
method public boolean isAllowed();
- method public void setAllowed(boolean);
method public void setBypassDnd(boolean);
method public void setImportance(int);
method public void setLights(boolean);
@@ -5424,7 +5423,8 @@
method public void cancel(int);
method public void cancel(java.lang.String, int);
method public void cancelAll();
- method public void createNotificationChannel(android.app.NotificationChannel, android.app.NotificationManager.OnNotificationChannelCreatedListener, android.os.Handler);
+ method public void createNotificationChannel(android.app.NotificationChannel);
+ method public void createNotificationChannels(java.util.List<android.app.NotificationChannel>);
method public void deleteNotificationChannel(java.lang.String);
method public android.service.notification.StatusBarNotification[] getActiveNotifications();
method public android.app.AutomaticZenRule getAutomaticZenRule(java.lang.String);
@@ -5459,10 +5459,6 @@
field public static final int INTERRUPTION_FILTER_UNKNOWN = 0; // 0x0
}
- public static abstract interface NotificationManager.OnNotificationChannelCreatedListener {
- method public abstract void onNotificationChannelCreated(android.app.NotificationChannel);
- }
-
public static class NotificationManager.Policy implements android.os.Parcelable {
ctor public NotificationManager.Policy(int, int, int);
ctor public NotificationManager.Policy(int, int, int, int);
@@ -6157,6 +6153,7 @@
method public boolean isSecurityLoggingEnabled(android.content.ComponentName);
method public boolean isUninstallBlocked(android.content.ComponentName, java.lang.String);
method public void lockNow();
+ method public void lockNow(int);
method public void reboot(android.content.ComponentName);
method public void removeActiveAdmin(android.content.ComponentName);
method public boolean removeCrossProfileWidgetProvider(android.content.ComponentName, java.lang.String);
@@ -6273,6 +6270,7 @@
field public static final java.lang.String EXTRA_PROVISIONING_WIFI_PROXY_PORT = "android.app.extra.PROVISIONING_WIFI_PROXY_PORT";
field public static final java.lang.String EXTRA_PROVISIONING_WIFI_SECURITY_TYPE = "android.app.extra.PROVISIONING_WIFI_SECURITY_TYPE";
field public static final java.lang.String EXTRA_PROVISIONING_WIFI_SSID = "android.app.extra.PROVISIONING_WIFI_SSID";
+ field public static final int FLAG_EVICT_CE_KEY = 1; // 0x1
field public static final int FLAG_MANAGED_CAN_ACCESS_PARENT = 2; // 0x2
field public static final int FLAG_PARENT_CAN_ACCESS_MANAGED = 1; // 0x1
field public static final int KEYGUARD_DISABLE_FEATURES_ALL = 2147483647; // 0x7fffffff
@@ -6650,6 +6648,16 @@
field public static final android.os.Parcelable.Creator<android.app.usage.ConfigurationStats> CREATOR;
}
+ public final class ExternalStorageStats implements android.os.Parcelable {
+ method public int describeContents();
+ method public long getAudioBytes();
+ method public long getImageBytes();
+ method public long getTotalBytes();
+ method public long getVideoBytes();
+ method public void writeToParcel(android.os.Parcel, int);
+ field public static final android.os.Parcelable.Creator<android.app.usage.ExternalStorageStats> CREATOR;
+ }
+
public final class NetworkStats implements java.lang.AutoCloseable {
method public void close();
method public boolean getNextBucket(android.app.usage.NetworkStats.Bucket);
@@ -6701,6 +6709,23 @@
method public abstract void onThresholdReached(int, java.lang.String);
}
+ public final class StorageStats implements android.os.Parcelable {
+ method public int describeContents();
+ method public long getCacheBytes();
+ method public long getCodeBytes();
+ method public long getDataBytes();
+ method public void writeToParcel(android.os.Parcel, int);
+ field public static final android.os.Parcelable.Creator<android.app.usage.StorageStats> CREATOR;
+ }
+
+ public class StorageStatsManager {
+ method public long getFreeBytes(java.lang.String);
+ method public long getTotalBytes(java.lang.String);
+ method public android.app.usage.ExternalStorageStats queryExternalStatsForUser(java.lang.String, android.os.UserHandle);
+ method public android.app.usage.StorageStats queryStatsForUid(java.lang.String, int);
+ method public android.app.usage.StorageStats queryStatsForUser(java.lang.String, android.os.UserHandle);
+ }
+
public final class UsageEvents implements android.os.Parcelable {
method public int describeContents();
method public boolean getNextEvent(android.app.usage.UsageEvents.Event);
@@ -6800,6 +6825,7 @@
method public void notifyAppWidgetViewDataChanged(int, int);
method public void partiallyUpdateAppWidget(int[], android.widget.RemoteViews);
method public void partiallyUpdateAppWidget(int, android.widget.RemoteViews);
+ method public boolean requestPinAppWidget(android.content.ComponentName, android.app.PendingIntent);
method public void updateAppWidget(int[], android.widget.RemoteViews);
method public void updateAppWidget(int, android.widget.RemoteViews);
method public void updateAppWidget(android.content.ComponentName, android.widget.RemoteViews);
@@ -8438,6 +8464,7 @@
field public static final java.lang.String SENSOR_SERVICE = "sensor";
field public static final java.lang.String SHORTCUT_SERVICE = "shortcut";
field public static final java.lang.String STORAGE_SERVICE = "storage";
+ field public static final java.lang.String STORAGE_STATS_SERVICE = "storagestats";
field public static final java.lang.String SYSTEM_HEALTH_SERVICE = "systemhealth";
field public static final java.lang.String TELECOM_SERVICE = "telecom";
field public static final java.lang.String TELEPHONY_SERVICE = "phone";
@@ -9789,11 +9816,13 @@
method public boolean accept(android.os.Bundle);
method public boolean accept();
method public int describeContents();
+ method public android.appwidget.AppWidgetProviderInfo getAppWidgetProviderInfo();
method public int getRequestType();
method public android.content.pm.ShortcutInfo getShortcutInfo();
method public boolean isValid();
method public void writeToParcel(android.os.Parcel, int);
field public static final android.os.Parcelable.Creator<android.content.pm.LauncherApps.PinItemRequest> CREATOR;
+ field public static final int REQUEST_TYPE_APPWIDGET = 2; // 0x2
field public static final int REQUEST_TYPE_SHORTCUT = 1; // 0x1
}
@@ -11977,8 +12006,6 @@
method public boolean clipRect(float, float, float, float, android.graphics.Region.Op);
method public boolean clipRect(float, float, float, float);
method public boolean clipRect(int, int, int, int);
- method public deprecated boolean clipRegion(android.graphics.Region, android.graphics.Region.Op);
- method public deprecated boolean clipRegion(android.graphics.Region);
method public void concat(android.graphics.Matrix);
method public void drawARGB(int, int, int, int);
method public void drawArc(android.graphics.RectF, float, float, boolean, android.graphics.Paint);
@@ -31019,6 +31046,7 @@
field public static final java.lang.String ACTION_SET_ALARM = "android.intent.action.SET_ALARM";
field public static final java.lang.String ACTION_SET_TIMER = "android.intent.action.SET_TIMER";
field public static final java.lang.String ACTION_SHOW_ALARMS = "android.intent.action.SHOW_ALARMS";
+ field public static final java.lang.String ACTION_SHOW_TIMERS = "android.intent.action.SHOW_TIMERS";
field public static final java.lang.String ACTION_SNOOZE_ALARM = "android.intent.action.SNOOZE_ALARM";
field public static final java.lang.String ALARM_SEARCH_MODE_ALL = "android.all";
field public static final java.lang.String ALARM_SEARCH_MODE_LABEL = "android.label";
@@ -36816,6 +36844,7 @@
method public void unhold();
method public void unregisterCallback(android.telecom.Call.Callback);
field public static final java.lang.String AVAILABLE_PHONE_ACCOUNTS = "selectPhoneAccountAccounts";
+ field public static final java.lang.String EXTRA_LAST_EMERGENCY_CALLBACK_TIME_MILLIS = "android.telecom.extra.LAST_EMERGENCY_CALLBACK_TIME_MILLIS";
field public static final int STATE_ACTIVE = 4; // 0x4
field public static final int STATE_CONNECTING = 9; // 0x9
field public static final int STATE_DIALING = 1; // 0x1
@@ -42103,7 +42132,7 @@
method public android.view.View findNearestTouchable(android.view.ViewGroup, int, int, int, int[]);
method public final android.view.View findNextFocus(android.view.ViewGroup, android.view.View, int);
method public android.view.View findNextFocusFromRect(android.view.ViewGroup, android.graphics.Rect, int);
- method public android.view.View findNextKeyboardNavigationCluster(android.view.ViewGroup, android.view.View, int);
+ method public android.view.View findNextKeyboardNavigationGroup(int, android.view.View, android.view.View, int);
method public static android.view.FocusFinder getInstance();
}
@@ -42877,6 +42906,7 @@
method public abstract android.view.ActionProvider getActionProvider();
method public abstract android.view.View getActionView();
method public abstract char getAlphabeticShortcut();
+ method public default java.lang.CharSequence getContentDescription();
method public abstract int getGroupId();
method public abstract android.graphics.drawable.Drawable getIcon();
method public abstract android.content.Intent getIntent();
@@ -42887,6 +42917,7 @@
method public abstract android.view.SubMenu getSubMenu();
method public abstract java.lang.CharSequence getTitle();
method public abstract java.lang.CharSequence getTitleCondensed();
+ method public default java.lang.CharSequence getTooltip();
method public abstract boolean hasSubMenu();
method public abstract boolean isActionViewExpanded();
method public abstract boolean isCheckable();
@@ -42899,6 +42930,7 @@
method public abstract android.view.MenuItem setAlphabeticShortcut(char);
method public abstract android.view.MenuItem setCheckable(boolean);
method public abstract android.view.MenuItem setChecked(boolean);
+ method public default android.view.MenuItem setContentDescription(java.lang.CharSequence);
method public abstract android.view.MenuItem setEnabled(boolean);
method public abstract android.view.MenuItem setIcon(android.graphics.drawable.Drawable);
method public abstract android.view.MenuItem setIcon(int);
@@ -42912,6 +42944,7 @@
method public abstract android.view.MenuItem setTitle(java.lang.CharSequence);
method public abstract android.view.MenuItem setTitle(int);
method public abstract android.view.MenuItem setTitleCondensed(java.lang.CharSequence);
+ method public default android.view.MenuItem setTooltip(java.lang.CharSequence);
method public abstract android.view.MenuItem setVisible(boolean);
field public static final int SHOW_AS_ACTION_ALWAYS = 2; // 0x2
field public static final int SHOW_AS_ACTION_COLLAPSE_ACTION_VIEW = 8; // 0x8
@@ -43399,7 +43432,7 @@
method public void addChildrenForAccessibility(java.util.ArrayList<android.view.View>);
method public void addFocusables(java.util.ArrayList<android.view.View>, int);
method public void addFocusables(java.util.ArrayList<android.view.View>, int, int);
- method public void addKeyboardNavigationClusters(java.util.Collection<android.view.View>, int);
+ method public void addKeyboardNavigationGroups(int, java.util.Collection<android.view.View>, int);
method public void addOnAttachStateChangeListener(android.view.View.OnAttachStateChangeListener);
method public void addOnLayoutChangeListener(android.view.View.OnLayoutChangeListener);
method public void addTouchables(java.util.ArrayList<android.view.View>);
@@ -43688,7 +43721,7 @@
method public boolean isVerticalFadingEdgeEnabled();
method public boolean isVerticalScrollBarEnabled();
method public void jumpDrawablesToCurrentState();
- method public android.view.View keyboardNavigationClusterSearch(int);
+ method public android.view.View keyboardNavigationGroupSearch(int, android.view.View, int);
method public void layout(int, int, int, int);
method public final void measure(int, int);
method protected static int[] mergeDrawableStates(int[], int[]);
@@ -43981,6 +44014,8 @@
field public static final int IMPORTANT_FOR_ACCESSIBILITY_YES = 1; // 0x1
field public static final int INVISIBLE = 4; // 0x4
field public static final int KEEP_SCREEN_ON = 67108864; // 0x4000000
+ field public static final int KEYBOARD_NAVIGATION_GROUP_CLUSTER = 1; // 0x1
+ field public static final int KEYBOARD_NAVIGATION_GROUP_SECTION = 2; // 0x2
field public static final int LAYER_TYPE_HARDWARE = 2; // 0x2
field public static final int LAYER_TYPE_NONE = 0; // 0x0
field public static final int LAYER_TYPE_SOFTWARE = 1; // 0x1
@@ -44341,7 +44376,6 @@
method protected deprecated boolean isChildrenDrawnWithCacheEnabled();
method public boolean isMotionEventSplittingEnabled();
method public boolean isTransitionGroup();
- method public android.view.View keyboardNavigationClusterSearch(android.view.View, int);
method public final void layout(int, int, int, int);
method protected void measureChild(android.view.View, int, int);
method protected void measureChildWithMargins(android.view.View, int, int, int, int);
@@ -44504,7 +44538,7 @@
method public abstract boolean isLayoutRequested();
method public abstract boolean isTextAlignmentResolved();
method public abstract boolean isTextDirectionResolved();
- method public abstract android.view.View keyboardNavigationClusterSearch(android.view.View, int);
+ method public abstract android.view.View keyboardNavigationGroupSearch(int, android.view.View, int);
method public abstract void notifySubtreeAccessibilityStateChanged(android.view.View, android.view.View, int);
method public abstract boolean onNestedFling(android.view.View, float, float, boolean);
method public abstract boolean onNestedPreFling(android.view.View, float, float);
@@ -46433,6 +46467,11 @@
method public abstract android.view.View getFullScreenView(int, android.content.Context);
}
+ public abstract class RenderProcessGoneDetail {
+ ctor public RenderProcessGoneDetail();
+ method public abstract boolean didCrash();
+ }
+
public class ServiceWorkerClient {
ctor public ServiceWorkerClient();
method public android.webkit.WebResourceResponse shouldInterceptRequest(android.webkit.WebResourceRequest);
@@ -46957,6 +46996,7 @@
method public void onReceivedHttpError(android.webkit.WebView, android.webkit.WebResourceRequest, android.webkit.WebResourceResponse);
method public void onReceivedLoginRequest(android.webkit.WebView, java.lang.String, java.lang.String, java.lang.String);
method public void onReceivedSslError(android.webkit.WebView, android.webkit.SslErrorHandler, android.net.http.SslError);
+ method public boolean onRenderProcessGone(android.webkit.WebView, android.webkit.RenderProcessGoneDetail);
method public void onScaleChanged(android.webkit.WebView, float, float);
method public deprecated void onTooManyRedirects(android.webkit.WebView, android.os.Message, android.os.Message);
method public void onUnhandledKeyEvent(android.webkit.WebView, android.view.KeyEvent);
diff --git a/api/test-removed.txt b/api/test-removed.txt
index 10e6eb5..d7a8bce 100644
--- a/api/test-removed.txt
+++ b/api/test-removed.txt
@@ -78,6 +78,11 @@
enum_constant public static final android.graphics.AvoidXfermode.Mode TARGET;
}
+ public class Canvas {
+ method public deprecated boolean clipRegion(android.graphics.Region, android.graphics.Region.Op);
+ method public deprecated boolean clipRegion(android.graphics.Region);
+ }
+
public deprecated class LayerRasterizer extends android.graphics.Rasterizer {
ctor public LayerRasterizer();
method public void addLayer(android.graphics.Paint, float, float);
@@ -99,67 +104,6 @@
}
-package android.location {
-
- public final class GnssMeasurement implements android.os.Parcelable {
- field public static final int MULTIPATH_INDICATOR_NOT_USED = 2; // 0x2
- }
-
- public final class GnssMeasurementsEvent implements android.os.Parcelable {
- field public static final int STATUS_GNSS_LOCATION_DISABLED = 2; // 0x2
- field public static final int STATUS_NOT_SUPPORTED = 0; // 0x0
- field public static final int STATUS_READY = 1; // 0x1
- }
-
- public final class GnssNavigationMessageEvent implements android.os.Parcelable {
- ctor public GnssNavigationMessageEvent(android.location.GnssNavigationMessage);
- method public int describeContents();
- method public android.location.GnssNavigationMessage getNavigationMessage();
- method public void writeToParcel(android.os.Parcel, int);
- field public static final android.os.Parcelable.Creator<android.location.GnssNavigationMessageEvent> CREATOR;
- field public static final int STATUS_GNSS_LOCATION_DISABLED = 2; // 0x2
- field public static final int STATUS_NOT_SUPPORTED = 0; // 0x0
- field public static final int STATUS_READY = 1; // 0x1
- }
-
- public static abstract class GnssNavigationMessageEvent.Callback {
- ctor public GnssNavigationMessageEvent.Callback();
- method public void onGnssNavigationMessageReceived(android.location.GnssNavigationMessageEvent);
- method public void onStatusChanged(int);
- }
-
- public abstract interface GnssNmeaListener {
- method public abstract void onNmeaReceived(long, java.lang.String);
- }
-
- public final class GnssStatus {
- method public int getNumSatellites();
- method public boolean hasAlmanac(int);
- method public boolean hasEphemeris(int);
- }
-
- public abstract class GnssStatusCallback {
- ctor public GnssStatusCallback();
- method public void onFirstFix(int);
- method public void onSatelliteStatusChanged(android.location.GnssStatus);
- method public void onStarted();
- method public void onStopped();
- }
-
- public class LocationManager {
- method public boolean addNmeaListener(android.location.GnssNmeaListener);
- method public boolean addNmeaListener(android.location.GnssNmeaListener, android.os.Handler);
- method public boolean registerGnssNavigationMessageCallback(android.location.GnssNavigationMessageEvent.Callback);
- method public boolean registerGnssNavigationMessageCallback(android.location.GnssNavigationMessageEvent.Callback, android.os.Handler);
- method public boolean registerGnssStatusCallback(android.location.GnssStatusCallback);
- method public boolean registerGnssStatusCallback(android.location.GnssStatusCallback, android.os.Handler);
- method public void removeNmeaListener(android.location.GnssNmeaListener);
- method public void unregisterGnssNavigationMessageCallback(android.location.GnssNavigationMessageEvent.Callback);
- method public void unregisterGnssStatusCallback(android.location.GnssStatusCallback);
- }
-
-}
-
package android.media {
public final class AudioFormat implements android.os.Parcelable {
diff --git a/compiled-classes-phone b/compiled-classes-phone
index f09bad9..7239a7f 100644
--- a/compiled-classes-phone
+++ b/compiled-classes-phone
@@ -632,6 +632,7 @@
android.bluetooth.BluetoothAudioConfig
android.bluetooth.BluetoothClass
android.bluetooth.BluetoothClass$1
+android.bluetooth.BluetoothCodecConfig
android.bluetooth.BluetoothDevice
android.bluetooth.BluetoothDevice$1
android.bluetooth.BluetoothDevice$2
diff --git a/core/java/android/app/Activity.java b/core/java/android/app/Activity.java
index 2ccfe0e..0d9e8a0 100644
--- a/core/java/android/app/Activity.java
+++ b/core/java/android/app/Activity.java
@@ -4341,8 +4341,8 @@
* that are defined to return a result. In other protocols (such as
* {@link Intent#ACTION_MAIN} or {@link Intent#ACTION_VIEW}), you may
* not get the result when you expect. For example, if the activity you
- * are launching uses the singleTask launch mode, it will not run in your
- * task and thus you will immediately receive a cancel result.
+ * are launching uses {@link Intent#FLAG_ACTIVITY_NEW_TASK}, it will not
+ * run in your task and thus you will immediately receive a cancel result.
*
* <p>As a special case, if you call startActivityForResult() with a requestCode
* >= 0 during the initial onCreate(Bundle savedInstanceState)/onResume() of your
diff --git a/core/java/android/app/ActivityManager.java b/core/java/android/app/ActivityManager.java
index 761da35..cd50c4d 100644
--- a/core/java/android/app/ActivityManager.java
+++ b/core/java/android/app/ActivityManager.java
@@ -80,7 +80,39 @@
import java.util.List;
/**
- * Interact with the overall activities running in the system.
+ * <p>
+ * This class gives information about, and interacts
+ * with, activities, services, and the containing
+ * process.
+ * </p>
+ *
+ * <p>
+ * A number of the methods in this class are for
+ * debugging or informational purposes and they should
+ * not be used to affect any runtime behavior of
+ * your app. These methods are called out as such in
+ * the method level documentation.
+ * </p>
+ *
+ *<p>
+ * Most application developers should not have the need to
+ * use this class, most of whose methods are for specialized
+ * use cases. However, a few methods are more broadly applicable.
+ * For instance, {@link android.app.ActivityManager#isLowRamDevice() isLowRamDevice()}
+ * enables your app to detect whether it is running on a low-memory device,
+ * and behave accordingly.
+ * {@link android.app.ActivityManager#clearApplicationUserData() clearApplicationUserData()}
+ * is for apps with reset-data functionality.
+ * </p>
+ *
+ * <p>
+ * In some special use cases, where an app interacts with
+ * its Task stack, the app may use the
+ * {@link android.app.ActivityManager.AppTask} and
+ * {@link android.app.ActivityManager.RecentTaskInfo} inner
+ * classes. However, in general, the methods in this class should
+ * be used for testing and debugging purposes only.
+ * </p>
*/
public class ActivityManager {
private static String TAG = "ActivityManager";
diff --git a/core/java/android/app/ContextImpl.java b/core/java/android/app/ContextImpl.java
index 547c710..d08bee5 100644
--- a/core/java/android/app/ContextImpl.java
+++ b/core/java/android/app/ContextImpl.java
@@ -509,10 +509,23 @@
* Common-path handling of app data dir creation
*/
private static File ensurePrivateDirExists(File file) {
+ return ensurePrivateDirExists(file, 0771, -1);
+ }
+
+ private static File ensurePrivateCacheDirExists(File file) {
+ final int gid = UserHandle.getCacheAppGid(Process.myUid());
+ return ensurePrivateDirExists(file, 02771, gid);
+ }
+
+ private static File ensurePrivateDirExists(File file, int mode, int gid) {
if (!file.exists()) {
+ final String path = file.getAbsolutePath();
try {
- Os.mkdir(file.getAbsolutePath(), 0771);
- Os.chmod(file.getAbsolutePath(), 0771);
+ Os.mkdir(path, mode);
+ Os.chmod(path, mode);
+ if (gid != -1) {
+ Os.chown(path, -1, gid);
+ }
} catch (ErrnoException e) {
if (e.errno == OsConstants.EEXIST) {
// We must have raced with someone; that's okay
@@ -581,7 +594,7 @@
if (mCacheDir == null) {
mCacheDir = new File(getDataDir(), "cache");
}
- return ensurePrivateDirExists(mCacheDir);
+ return ensurePrivateCacheDirExists(mCacheDir);
}
}
@@ -591,7 +604,7 @@
if (mCodeCacheDir == null) {
mCodeCacheDir = new File(getDataDir(), "code_cache");
}
- return ensurePrivateDirExists(mCodeCacheDir);
+ return ensurePrivateCacheDirExists(mCodeCacheDir);
}
}
diff --git a/core/java/android/app/IActivityManager.aidl b/core/java/android/app/IActivityManager.aidl
index 28ad01e..21854d3 100644
--- a/core/java/android/app/IActivityManager.aidl
+++ b/core/java/android/app/IActivityManager.aidl
@@ -319,7 +319,12 @@
void registerUserSwitchObserver(in IUserSwitchObserver observer, in String name);
void unregisterUserSwitchObserver(in IUserSwitchObserver observer);
int[] getRunningUserIds();
+
+ // Deprecated - This method is only used by a few internal components and it will soon be
+ // replaced by a proper bug report API (which will be restricted to a few, pre-defined apps).
+ // No new code should be calling it.
void requestBugReport(int bugreportType);
+
long inputDispatchingTimedOut(int pid, boolean aboveSystem, in String reason);
void clearPendingBackup();
Intent getIntentForIntentSender(in IIntentSender sender);
@@ -583,6 +588,7 @@
boolean requestAutoFillData(in IResultReceiver receiver, in Bundle receiverExtras,
in IBinder activityToken, int flags);
void dismissKeyguard(in IBinder token, in IKeyguardDismissCallback callback);
+ int restartUserInBackground(int userId);
// WARNING: when these transactions are updated, check if they are any callers on the native
// side. If so, make sure they are using the correct transaction ids and arguments.
diff --git a/core/java/android/app/INotificationManager.aidl b/core/java/android/app/INotificationManager.aidl
index 211aa07..81aeaef 100644
--- a/core/java/android/app/INotificationManager.aidl
+++ b/core/java/android/app/INotificationManager.aidl
@@ -17,7 +17,6 @@
package android.app;
-import android.app.IOnNotificationChannelCreatedListener;
import android.app.ITransientNotification;
import android.app.Notification;
import android.app.NotificationChannel;
@@ -52,8 +51,7 @@
boolean areNotificationsEnabled(String pkg);
int getPackageImportance(String pkg);
- void createNotificationChannel(String pkg, in NotificationChannel channel,
- in IOnNotificationChannelCreatedListener listener);
+ void createNotificationChannels(String pkg, in ParceledListSlice channelsList);
void updateNotificationChannelForPackage(String pkg, int uid, in NotificationChannel channel);
NotificationChannel getNotificationChannel(String pkg, String channelId);
NotificationChannel getNotificationChannelForPackage(String pkg, int uid, String channelId);
@@ -92,6 +90,7 @@
void setOnNotificationPostedTrimFromListener(in INotificationListener token, int trim);
void setInterruptionFilter(String pkg, int interruptionFilter);
+ void applyEnqueuedAdjustmentFromAssistant(in INotificationListener token, in Adjustment adjustment);
void applyAdjustmentFromAssistant(in INotificationListener token, in Adjustment adjustment);
void applyAdjustmentsFromAssistant(in INotificationListener token, in List<Adjustment> adjustments);
void createNotificationChannelFromAssistant(in INotificationListener token, String pkg, in NotificationChannel channel);
diff --git a/core/java/android/app/IOnNotificationChannelCreatedListener.aidl b/core/java/android/app/IOnNotificationChannelCreatedListener.aidl
deleted file mode 100644
index 8e66542..0000000
--- a/core/java/android/app/IOnNotificationChannelCreatedListener.aidl
+++ /dev/null
@@ -1,25 +0,0 @@
-/*
-**
-** Copyright 2016, 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 android.app;
-
-import android.app.NotificationChannel;
-
-/** {@hide} */
-oneway interface IOnNotificationChannelCreatedListener {
- void onNotificationChannelCreated(in NotificationChannel channel);
-}
diff --git a/core/java/android/app/NotificationChannel.java b/core/java/android/app/NotificationChannel.java
index 52d9b67..bdccb8a 100644
--- a/core/java/android/app/NotificationChannel.java
+++ b/core/java/android/app/NotificationChannel.java
@@ -55,7 +55,6 @@
private static final String ATT_AUDIO_ATTRIBUTES = "audio_attributes";
private static final String ATT_SHOW_BADGE = "show_badge";
private static final String ATT_USER_LOCKED = "locked";
- private static final String ATT_ALLOWED = "allowed";
private static final String DELIMITER = ",";
/**
@@ -243,12 +242,12 @@
this.mImportance = importance;
}
+ // Modifiable by apps on channel creation.
+
/**
* Sets whether notifications posted to this channel can appear as application icon badges
* in a Launcher.
*
- * Only modifiable by the system and notification ranker.
- *
* @param showBadge true if badges should be allowed to be shown.
*/
public void setShowBadge(boolean showBadge) {
@@ -256,20 +255,6 @@
}
/**
- * Sets whether notifications are allowed to be posted to this channel.
- *
- * Only modifiable by the system and notification ranker.
- *
- * @param allowed true if notifications are not allowed from this channel.
- */
- public void setAllowed(boolean allowed) {
- this.mAllowed = allowed;
- }
-
-
- // Modifiable by apps on channel creation.
-
- /**
* Sets the sound that should be played for notifications posted to this channel if
* the notifications don't supply a sound. Only modifiable before the channel is submitted
* to the NotificationManager.
@@ -408,7 +393,6 @@
enableVibration(safeBool(parser, ATT_VIBRATION_ENABLED, false));
setVibrationPattern(safeLongArray(parser, ATT_VIBRATION, null));
setShowBadge(safeBool(parser, ATT_SHOW_BADGE, false));
- setAllowed(safeBool(parser, ATT_ALLOWED, true));
lockFields(safeInt(parser, ATT_USER_LOCKED, 0));
}
@@ -450,9 +434,6 @@
if (canShowBadge()) {
out.attribute(null, ATT_SHOW_BADGE, Boolean.toString(canShowBadge()));
}
- if (!isAllowed()) {
- out.attribute(null, ATT_ALLOWED, Boolean.toString(isAllowed()));
- }
out.endTag(null, TAG_CHANNEL);
}
@@ -483,8 +464,6 @@
record.put(ATT_USER_LOCKED, Integer.toString(getUserLockedFields()));
record.put(ATT_VIBRATION, longArrayToString(getVibrationPattern()));
record.put(ATT_SHOW_BADGE, Boolean.toString(canShowBadge()));
- record.put(ATT_ALLOWED, Boolean.toString(isAllowed()));
-
return record;
}
diff --git a/core/java/android/app/NotificationManager.java b/core/java/android/app/NotificationManager.java
index a9ff482..3551691 100644
--- a/core/java/android/app/NotificationManager.java
+++ b/core/java/android/app/NotificationManager.java
@@ -47,6 +47,7 @@
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
+import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
@@ -381,42 +382,26 @@
}
/**
- * Listener passed to {@link NotificationManager#createNotificationChannel} to notify
- * caller of result.
+ * Creates a notification channel that notifications can be posted to.
+ *
+ * @param channel the channel to create. Note that the created channel may differ from this
+ * value. If the channel already exists, it will not be modified.
*/
- public interface OnNotificationChannelCreatedListener {
- /**
- * @param createdChannel NotificationChannel created by the system. Value is null iff an
- * exception was thrown during channel creation.
- */
- public void onNotificationChannelCreated(NotificationChannel createdChannel);
+ public void createNotificationChannel(@NonNull NotificationChannel channel) {
+ createNotificationChannels(Arrays.asList(channel));
}
/**
- * Creates a notification channel that notifications can be posted to.
+ * Creates multiple notification channels that different notifications can be posted to.
*
- * @param channel the channel to attempt to create. Note that the created channel may differ
- * from this value.
- * @param listener Called when operation is finished.
- * @param handler The handler to invoke the listener on, or {@code null} to use the main
- * handler.
+ * @param channels the list of channels to attempt to create. If any of these channels already
+ * exist, they will not be modified.
*/
- public void createNotificationChannel(
- @NonNull NotificationChannel channel,
- @NonNull OnNotificationChannelCreatedListener listener,
- @Nullable Handler handler) {
+ public void createNotificationChannels(@NonNull List<NotificationChannel> channels) {
INotificationManager service = getService();
try {
- final Handler actualHandler =
- handler != null ? handler : new Handler(Looper.getMainLooper());
- service.createNotificationChannel(mContext.getPackageName(), channel,
- new IOnNotificationChannelCreatedListener.Stub() {
- @Override public void onNotificationChannelCreated(
- NotificationChannel channel) {
- actualHandler.post(
- () -> { listener.onNotificationChannelCreated(channel); });
- }
- });
+ service.createNotificationChannels(mContext.getPackageName(),
+ new ParceledListSlice(channels));
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
diff --git a/core/java/android/app/SystemServiceRegistry.java b/core/java/android/app/SystemServiceRegistry.java
index 6bddfba..9387019 100644
--- a/core/java/android/app/SystemServiceRegistry.java
+++ b/core/java/android/app/SystemServiceRegistry.java
@@ -23,8 +23,10 @@
import android.app.job.IJobScheduler;
import android.app.job.JobScheduler;
import android.app.trust.TrustManager;
+import android.app.usage.IStorageStatsManager;
import android.app.usage.IUsageStatsManager;
import android.app.usage.NetworkStatsManager;
+import android.app.usage.StorageStatsManager;
import android.app.usage.UsageStatsManager;
import android.appwidget.AppWidgetManager;
import android.bluetooth.BluetoothManager;
@@ -434,6 +436,15 @@
return new StorageManager(ctx, ctx.mMainThread.getHandler().getLooper());
}});
+ registerService(Context.STORAGE_STATS_SERVICE, StorageStatsManager.class,
+ new CachedServiceFetcher<StorageStatsManager>() {
+ @Override
+ public StorageStatsManager createService(ContextImpl ctx) throws ServiceNotFoundException {
+ IStorageStatsManager service = IStorageStatsManager.Stub.asInterface(
+ ServiceManager.getServiceOrThrow(Context.STORAGE_STATS_SERVICE));
+ return new StorageStatsManager(ctx, service);
+ }});
+
registerService(Context.TELEPHONY_SERVICE, TelephonyManager.class,
new CachedServiceFetcher<TelephonyManager>() {
@Override
diff --git a/core/java/android/app/admin/DevicePolicyManager.java b/core/java/android/app/admin/DevicePolicyManager.java
index 6f73388..a56ff5e 100644
--- a/core/java/android/app/admin/DevicePolicyManager.java
+++ b/core/java/android/app/admin/DevicePolicyManager.java
@@ -2715,6 +2715,43 @@
}
/**
+ * Flag for {@link #lockNow(int)}: also evict the user's credential encryption key from the
+ * keyring. The user's credential will need to be entered again in order to derive the
+ * credential encryption key that will be stored back in the keyring for future use.
+ * <p>
+ * This flag can only be used by a profile owner when locking a managed profile on an FBE
+ * device.
+ * <p>
+ * In order to secure user data, the user will be stopped and restarted so apps should wait
+ * until they are next run to perform further actions.
+ */
+ public static final int FLAG_EVICT_CE_KEY = 1;
+
+ /** @hide */
+ @Retention(RetentionPolicy.SOURCE)
+ @IntDef(flag=true, value={FLAG_EVICT_CE_KEY})
+ public @interface LockNowFlag {}
+
+ /**
+ * Make the device lock immediately, as if the lock screen timeout has expired at the point of
+ * this call.
+ * <p>
+ * The calling device admin must have requested {@link DeviceAdminInfo#USES_POLICY_FORCE_LOCK}
+ * to be able to call this method; if it has not, a security exception will be thrown.
+ * <p>
+ * This method can be called on the {@link DevicePolicyManager} instance returned by
+ * {@link #getParentProfileInstance(ComponentName)} in order to lock the parent profile.
+ * <p>
+ * Equivalent to calling {@link #lockNow(int)} with no flags.
+ *
+ * @throws SecurityException if the calling application does not own an active administrator
+ * that uses {@link DeviceAdminInfo#USES_POLICY_FORCE_LOCK}
+ */
+ public void lockNow() {
+ lockNow(0);
+ }
+
+ /**
* Make the device lock immediately, as if the lock screen timeout has expired at the point of
* this call.
* <p>
@@ -2724,13 +2761,20 @@
* This method can be called on the {@link DevicePolicyManager} instance returned by
* {@link #getParentProfileInstance(ComponentName)} in order to lock the parent profile.
*
+ * @param flags May be 0 or {@link #FLAG_EVICT_CE_KEY}.
* @throws SecurityException if the calling application does not own an active administrator
- * that uses {@link DeviceAdminInfo#USES_POLICY_FORCE_LOCK}
+ * that uses {@link DeviceAdminInfo#USES_POLICY_FORCE_LOCK} or the
+ * {@link #FLAG_EVICT_CE_KEY} flag is passed by an application that is not a profile
+ * owner of a managed profile.
+ * @throws IllegalArgumentException if the {@link #FLAG_EVICT_CE_KEY} flag is passed when
+ * locking the parent profile.
+ * @throws UnsupportedOperationException if the {@link #FLAG_EVICT_CE_KEY} flag is passed on a
+ * non-FBE device.
*/
- public void lockNow() {
+ public void lockNow(@LockNowFlag int flags) {
if (mService != null) {
try {
- mService.lockNow(mParentInstance);
+ mService.lockNow(flags, mParentInstance);
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
diff --git a/core/java/android/app/admin/IDevicePolicyManager.aidl b/core/java/android/app/admin/IDevicePolicyManager.aidl
index 9be694e..66185d5 100644
--- a/core/java/android/app/admin/IDevicePolicyManager.aidl
+++ b/core/java/android/app/admin/IDevicePolicyManager.aidl
@@ -90,7 +90,7 @@
void setRequiredStrongAuthTimeout(in ComponentName who, long timeMs, boolean parent);
long getRequiredStrongAuthTimeout(in ComponentName who, int userId, boolean parent);
- void lockNow(boolean parent);
+ void lockNow(int flags, boolean parent);
void wipeData(int flags);
diff --git a/core/java/android/app/admin/SystemUpdatePolicy.java b/core/java/android/app/admin/SystemUpdatePolicy.java
index 20ddb77..28704e6 100644
--- a/core/java/android/app/admin/SystemUpdatePolicy.java
+++ b/core/java/android/app/admin/SystemUpdatePolicy.java
@@ -19,10 +19,8 @@
import android.annotation.IntDef;
import android.os.Parcel;
import android.os.Parcelable;
-import android.os.PersistableBundle;
import org.xmlpull.v1.XmlPullParser;
-import org.xmlpull.v1.XmlPullParserException;
import org.xmlpull.v1.XmlSerializer;
import java.io.IOException;
@@ -49,25 +47,45 @@
* Unknown policy type, used only internally.
*/
private static final int TYPE_UNKNOWN = -1;
+
/**
* Install system update automatically as soon as one is available.
*/
public static final int TYPE_INSTALL_AUTOMATIC = 1;
/**
- * Install system update automatically within a daily maintenance window, for a maximum of 30
- * days. After the expiration the policy will no longer be effective and the system should
- * revert back to its normal behavior as if no policy were set. The only exception is
- * {@link #TYPE_INSTALL_AUTOMATIC} which should still take effect to install system update
- * immediately.
+ * Install system update automatically within a daily maintenance window. An update can be
+ * delayed for a maximum of 30 days, after which the policy will no longer be effective and the
+ * system will revert back to its normal behavior as if no policy were set.
+ *
+ * <p>After this policy expires, resetting it to any policy other than
+ * {@link #TYPE_INSTALL_AUTOMATIC} will produce no effect, as the 30-day maximum delay has
+ * already been used up.
+ * The {@link #TYPE_INSTALL_AUTOMATIC} policy will still take effect to install the delayed
+ * system update immediately.
+ *
+ * <p>Re-applying this policy or changing it to {@link #TYPE_POSTPONE} within the 30-day period
+ * will <i>not</i> extend policy expiration.
+ * However, the expiration will be recalculated when a new system update is made available.
*/
public static final int TYPE_INSTALL_WINDOWED = 2;
/**
- * Incoming system update will be blocked for a maximum of 30 days, after which the system
- * should revert back to its normal behavior as if no policy were set. The only exception is
- * {@link #TYPE_INSTALL_AUTOMATIC} which should still take effect to install system update
- * immediately.
+ * Incoming system updates (except for security updates) will be blocked for 30 days, after
+ * which the policy will no longer be effective and the system will revert back to its normal
+ * behavior as if no policy were set.
+ * <b>Note:</b> security updates (e.g. monthly security patches) will <i>not</i> be affected by
+ * this policy.
+ *
+ * <p>After this policy expires, resetting it to any policy other than
+ * {@link #TYPE_INSTALL_AUTOMATIC} will produce no effect, as the 30-day maximum delay has
+ * already been used up.
+ * The {@link #TYPE_INSTALL_AUTOMATIC} policy will still take effect to install the delayed
+ * system update immediately.
+ *
+ * <p>Re-applying this policy or changing it to {@link #TYPE_INSTALL_WINDOWED} within the 30-day
+ * period will <i>not</i> extend policy expiration.
+ * However, the expiration will be recalculated when a new system update is made available.
*/
public static final int TYPE_POSTPONE = 3;
@@ -105,11 +123,12 @@
/**
* Create a policy object and set it to: new system update will only be installed automatically
* when the system clock is inside a daily maintenance window. If the start and end times are
- * the same, the window is considered to include the WHOLE 24 hours, that is, updates can
- * install at any time. If the given window in invalid, a {@link IllegalArgumentException} will
- * be thrown. If start time is later than end time, the window is considered spanning midnight,
- * i.e. end time donates a time on the next day. The maintenance window will last for 30 days,
- * after which the system should revert back to its normal behavior as if no policy were set.
+ * the same, the window is considered to include the <i>whole 24 hours</i>. That is, updates can
+ * install at any time. If the given window in invalid, an {@link IllegalArgumentException}
+ * will be thrown. If start time is later than end time, the window is considered spanning
+ * midnight (i.e. the end time denotes a time on the next day). The maintenance window will last
+ * for 30 days, after which the system will revert back to its normal behavior as if no policy
+ * were set.
*
* @param startTime the start of the maintenance window, measured as the number of minutes from
* midnight in the device's local time. Must be in the range of [0, 1440).
@@ -131,9 +150,12 @@
/**
* Create a policy object and set it to block installation for a maximum period of 30 days.
- * After expiration the system should revert back to its normal behavior as if no policy were
+ * After expiration the system will revert back to its normal behavior as if no policy were
* set.
*
+ * <p><b>Note: </b> security updates (e.g. monthly security patches) will <i>not</i> be affected
+ * by this policy.
+ *
* @see #TYPE_POSTPONE
*/
public static SystemUpdatePolicy createPostponeInstallPolicy() {
diff --git a/core/java/android/view/GraphicBuffer.aidl b/core/java/android/app/usage/ExternalStorageStats.aidl
similarity index 82%
copy from core/java/android/view/GraphicBuffer.aidl
copy to core/java/android/app/usage/ExternalStorageStats.aidl
index 6dc6bed..2d9375c 100644
--- a/core/java/android/view/GraphicBuffer.aidl
+++ b/core/java/android/app/usage/ExternalStorageStats.aidl
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2013 The Android Open Source Project
+ * 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.
@@ -14,6 +14,6 @@
* limitations under the License.
*/
-package android.view;
+package android.app.usage;
-parcelable GraphicBuffer;
+parcelable ExternalStorageStats;
diff --git a/core/java/android/app/usage/ExternalStorageStats.java b/core/java/android/app/usage/ExternalStorageStats.java
new file mode 100644
index 0000000..1166df0
--- /dev/null
+++ b/core/java/android/app/usage/ExternalStorageStats.java
@@ -0,0 +1,103 @@
+/*
+ * 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 android.app.usage;
+
+import android.os.Parcel;
+import android.os.Parcelable;
+import android.os.UserHandle;
+
+/**
+ * Shared/external storage statistics for a {@link UserHandle} on a single
+ * storage volume.
+ *
+ * @see StorageStatsManager
+ */
+public final class ExternalStorageStats implements Parcelable {
+ /** {@hide} */ public long totalBytes;
+ /** {@hide} */ public long audioBytes;
+ /** {@hide} */ public long videoBytes;
+ /** {@hide} */ public long imageBytes;
+
+ /**
+ * Return the total bytes used by all files in the shared/external storage
+ * hosted on this volume.
+ */
+ public long getTotalBytes() {
+ return totalBytes;
+ }
+
+ /**
+ * Return the total bytes used by audio files in the shared/external storage
+ * hosted on this volume.
+ */
+ public long getAudioBytes() {
+ return audioBytes;
+ }
+
+ /**
+ * Return the total bytes used by video files in the shared/external storage
+ * hosted on this volume.
+ */
+ public long getVideoBytes() {
+ return videoBytes;
+ }
+
+ /**
+ * Return the total bytes used by image files in the shared/external storage
+ * hosted on this volume.
+ */
+ public long getImageBytes() {
+ return imageBytes;
+ }
+
+ /** {@hide} */
+ public ExternalStorageStats() {
+ }
+
+ /** {@hide} */
+ public ExternalStorageStats(Parcel in) {
+ this.totalBytes = in.readLong();
+ this.audioBytes = in.readLong();
+ this.videoBytes = in.readLong();
+ this.imageBytes = in.readLong();
+ }
+
+ @Override
+ public int describeContents() {
+ return 0;
+ }
+
+ @Override
+ public void writeToParcel(Parcel dest, int flags) {
+ dest.writeLong(totalBytes);
+ dest.writeLong(audioBytes);
+ dest.writeLong(videoBytes);
+ dest.writeLong(imageBytes);
+ }
+
+ public static final Creator<ExternalStorageStats> CREATOR = new Creator<ExternalStorageStats>() {
+ @Override
+ public ExternalStorageStats createFromParcel(Parcel in) {
+ return new ExternalStorageStats(in);
+ }
+
+ @Override
+ public ExternalStorageStats[] newArray(int size) {
+ return new ExternalStorageStats[size];
+ }
+ };
+}
diff --git a/core/java/android/app/usage/IStorageStatsManager.aidl b/core/java/android/app/usage/IStorageStatsManager.aidl
new file mode 100644
index 0000000..62ebf60
--- /dev/null
+++ b/core/java/android/app/usage/IStorageStatsManager.aidl
@@ -0,0 +1,29 @@
+/*
+ * 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 android.app.usage;
+
+import android.app.usage.StorageStats;
+import android.app.usage.ExternalStorageStats;
+
+/** {@hide} */
+interface IStorageStatsManager {
+ long getTotalBytes(String volumeUuid, String callingPackage);
+ long getFreeBytes(String volumeUuid, String callingPackage);
+ StorageStats queryStatsForUid(String volumeUuid, int uid, String callingPackage);
+ StorageStats queryStatsForUser(String volumeUuid, int userId, String callingPackage);
+ ExternalStorageStats queryExternalStatsForUser(String volumeUuid, int userId, String callingPackage);
+}
diff --git a/core/java/android/view/GraphicBuffer.aidl b/core/java/android/app/usage/StorageStats.aidl
similarity index 83%
copy from core/java/android/view/GraphicBuffer.aidl
copy to core/java/android/app/usage/StorageStats.aidl
index 6dc6bed..fde6267 100644
--- a/core/java/android/view/GraphicBuffer.aidl
+++ b/core/java/android/app/usage/StorageStats.aidl
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2013 The Android Open Source Project
+ * 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.
@@ -14,6 +14,6 @@
* limitations under the License.
*/
-package android.view;
+package android.app.usage;
-parcelable GraphicBuffer;
+parcelable StorageStats;
diff --git a/core/java/android/app/usage/StorageStats.java b/core/java/android/app/usage/StorageStats.java
new file mode 100644
index 0000000..b3104f6
--- /dev/null
+++ b/core/java/android/app/usage/StorageStats.java
@@ -0,0 +1,104 @@
+/*
+ * 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 android.app.usage;
+
+import android.content.Context;
+import android.os.Parcel;
+import android.os.Parcelable;
+import android.os.UserHandle;
+
+/**
+ * Storage statistics for a UID or {@link UserHandle} on a single storage
+ * volume.
+ * <p class="note">
+ * Note: multiple packages using the same {@code sharedUserId} in their manifest
+ * will be merged into a single UID.
+ * </p>
+ *
+ * @see StorageStatsManager
+ */
+public final class StorageStats implements Parcelable {
+ /** {@hide} */ public long codeBytes;
+ /** {@hide} */ public long dataBytes;
+ /** {@hide} */ public long cacheBytes;
+
+ /**
+ * Return the size of all code. This includes {@code APK} files and
+ * optimized compiler output.
+ * <p>
+ * Code is shared between all users on a multiuser device.
+ */
+ public long getCodeBytes() {
+ return codeBytes;
+ }
+
+ /**
+ * Return the size of all data. This includes files stored under
+ * {@link Context#getDataDir()}, {@link Context#getCacheDir()},
+ * {@link Context#getCodeCacheDir()}.
+ * <p>
+ * Data is isolated for each user on a multiuser device.
+ */
+ public long getDataBytes() {
+ return dataBytes;
+ }
+
+ /**
+ * Return the size of all cached data. This includes files stored under
+ * {@link Context#getCacheDir()} and {@link Context#getCodeCacheDir()}.
+ * <p>
+ * Cached data is isolated for each user on a multiuser device.
+ */
+ public long getCacheBytes() {
+ return cacheBytes;
+ }
+
+ /** {@hide} */
+ public StorageStats() {
+ }
+
+ /** {@hide} */
+ public StorageStats(Parcel in) {
+ this.codeBytes = in.readLong();
+ this.dataBytes = in.readLong();
+ this.cacheBytes = in.readLong();
+ }
+
+ @Override
+ public int describeContents() {
+ return 0;
+ }
+
+ @Override
+ public void writeToParcel(Parcel dest, int flags) {
+ dest.writeLong(codeBytes);
+ dest.writeLong(dataBytes);
+ dest.writeLong(cacheBytes);
+ }
+
+ public static final Creator<StorageStats> CREATOR = new Creator<StorageStats>() {
+ @Override
+ public StorageStats createFromParcel(Parcel in) {
+ return new StorageStats(in);
+ }
+
+ @Override
+ public StorageStats[] newArray(int size) {
+ return new StorageStats[size];
+ }
+ };
+}
diff --git a/core/java/android/app/usage/StorageStatsManager.java b/core/java/android/app/usage/StorageStatsManager.java
new file mode 100644
index 0000000..695994b
--- /dev/null
+++ b/core/java/android/app/usage/StorageStatsManager.java
@@ -0,0 +1,154 @@
+/*
+ * 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 android.app.usage;
+
+import android.annotation.WorkerThread;
+import android.content.Context;
+import android.os.RemoteException;
+import android.os.UserHandle;
+
+import com.android.internal.util.Preconditions;
+
+import java.io.File;
+
+/**
+ * Provides access to detailed storage statistics.
+ * <p class="note">
+ * Note: this API requires the permission
+ * {@code android.permission.PACKAGE_USAGE_STATS}, which is a system-level
+ * permission that will not be granted to normal apps. However, declaring the
+ * permission expresses your intention to use this API and an end user can then
+ * choose to grant this permission through the Settings application.
+ * </p>
+ */
+public class StorageStatsManager {
+ private final Context mContext;
+ private final IStorageStatsManager mService;
+
+ /** {@hide} */
+ public StorageStatsManager(Context context, IStorageStatsManager service) {
+ mContext = Preconditions.checkNotNull(context);
+ mService = Preconditions.checkNotNull(service);
+ }
+
+ /**
+ * Return the total space on the requested storage volume.
+ * <p>
+ * To reduce end user confusion, this value is the total storage size
+ * advertised in a retail environment, which is typically larger than the
+ * actual writable partition total size.
+ * <p>
+ * This method may take several seconds to calculate the requested values,
+ * so it should only be called from a worker thread.
+ *
+ * @param volumeUuid the UUID of the storage volume you're interested in, or
+ * {@code null} to specify the default internal storage.
+ */
+ @WorkerThread
+ public long getTotalBytes(String volumeUuid) {
+ try {
+ return mService.getTotalBytes(volumeUuid, mContext.getOpPackageName());
+ } catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
+ }
+ }
+
+ /**
+ * Return the free space on the requested storage volume.
+ * <p>
+ * The free space is equivalent to {@link File#getFreeSpace()} plus the size
+ * of any cached data that can be automatically deleted by the system as
+ * additional space is needed.
+ * <p>
+ * This method may take several seconds to calculate the requested values,
+ * so it should only be called from a worker thread.
+ *
+ * @param volumeUuid the UUID of the storage volume you're interested in, or
+ * {@code null} to specify the default internal storage.
+ */
+ @WorkerThread
+ public long getFreeBytes(String volumeUuid) {
+ try {
+ return mService.getFreeBytes(volumeUuid, mContext.getOpPackageName());
+ } catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
+ }
+ }
+
+ /**
+ * Return storage statistics for a specific UID on the requested storage
+ * volume.
+ * <p>
+ * This method may take several seconds to calculate the requested values,
+ * so it should only be called from a worker thread.
+ *
+ * @param volumeUuid the UUID of the storage volume you're interested in, or
+ * {@code null} to specify the default internal storage.
+ * @param uid the UID you're interested in.
+ */
+ @WorkerThread
+ public StorageStats queryStatsForUid(String volumeUuid, int uid) {
+ try {
+ return mService.queryStatsForUid(volumeUuid, uid, mContext.getOpPackageName());
+ } catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
+ }
+ }
+
+ /**
+ * Return storage statistics for a specific {@link UserHandle} on the
+ * requested storage volume.
+ * <p>
+ * This method may take several seconds to calculate the requested values,
+ * so it should only be called from a worker thread.
+ *
+ * @param volumeUuid the UUID of the storage volume you're interested in, or
+ * {@code null} to specify the default internal storage.
+ * @param user the user you're interested in.
+ * @see android.os.Process#myUserHandle()
+ */
+ @WorkerThread
+ public StorageStats queryStatsForUser(String volumeUuid, UserHandle user) {
+ try {
+ return mService.queryStatsForUser(volumeUuid, user.getIdentifier(),
+ mContext.getOpPackageName());
+ } catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
+ }
+ }
+
+ /**
+ * Return shared/external storage statistics for a specific
+ * {@link UserHandle} on the requested storage volume.
+ * <p>
+ * This method may take several seconds to calculate the requested values,
+ * so it should only be called from a worker thread.
+ *
+ * @param volumeUuid the UUID of the storage volume you're interested in, or
+ * {@code null} to specify the default internal storage.
+ * @see android.os.Process#myUserHandle()
+ */
+ @WorkerThread
+ public ExternalStorageStats queryExternalStatsForUser(String volumeUuid, UserHandle user) {
+ try {
+ return mService.queryExternalStatsForUser(volumeUuid, user.getIdentifier(),
+ mContext.getOpPackageName());
+ } catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
+ }
+ }
+}
diff --git a/core/java/android/appwidget/AppWidgetManager.java b/core/java/android/appwidget/AppWidgetManager.java
index 9f654c2..3189681 100644
--- a/core/java/android/appwidget/AppWidgetManager.java
+++ b/core/java/android/appwidget/AppWidgetManager.java
@@ -16,11 +16,15 @@
package android.appwidget;
+import android.annotation.NonNull;
import android.annotation.Nullable;
+import android.app.PendingIntent;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
+import android.content.IntentSender;
import android.content.pm.ParceledListSlice;
+import android.content.pm.ShortcutInfo;
import android.os.Bundle;
import android.os.IBinder;
import android.os.Process;
@@ -1079,4 +1083,41 @@
info.minResizeHeight = TypedValue.complexToDimensionPixelSize(info.minResizeHeight,
mDisplayMetrics);
}
+
+ /**
+ * Request to pin an app widget on the current launcher. It's up to the launcher to accept this
+ * request (optionally showing a user confirmation). If the request is accepted, the caller will
+ * get a confirmation with extra {@link #EXTRA_APPWIDGET_ID}.
+ *
+ * <p>When a request is denied by the user, the caller app will not get any response.
+ *
+ * <p>Only apps with a foreground activity or a foreground service can call it. Otherwise
+ * it'll throw {@link IllegalStateException}.
+ *
+ * <p>When an app calls this API when a previous request is still waiting for a response,
+ * the previous request will be canceled.
+ *
+ * @param provider The {@link ComponentName} for the {@link
+ * android.content.BroadcastReceiver BroadcastReceiver} provider for your AppWidget.
+ * @param successCallback If not null, this intent will be sent when the widget is created.
+ *
+ * @return {@code TRUE} if the launcher supports this feature. Note the API will return without
+ * waiting for the user to respond, so getting {@code TRUE} from this API does *not* mean
+ * the shortcut is pinned. {@code FALSE} if the launcher doesn't support this feature.
+ *
+ * @see android.content.pm.ShortcutManager#isRequestPinShortcutSupported()
+ * @see android.content.pm.ShortcutManager#requestPinShortcut(ShortcutInfo, IntentSender)
+ *
+ * @throws IllegalStateException The caller doesn't have a foreground activity or a foreground
+ * service or when the user is locked.
+ */
+ public boolean requestPinAppWidget(@NonNull ComponentName provider,
+ @Nullable PendingIntent successCallback) {
+ try {
+ return mService.requestPinAppWidget(mPackageName, provider,
+ successCallback == null ? null : successCallback.getIntentSender());
+ } catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
+ }
+ }
}
diff --git a/core/java/android/bluetooth/BluetoothA2dp.java b/core/java/android/bluetooth/BluetoothA2dp.java
index 3de159a..1ce8007 100644
--- a/core/java/android/bluetooth/BluetoothA2dp.java
+++ b/core/java/android/bluetooth/BluetoothA2dp.java
@@ -103,6 +103,27 @@
"android.bluetooth.a2dp.profile.action.AVRCP_CONNECTION_STATE_CHANGED";
/**
+ * Intent used to broadcast the change in the Audio Codec state of the
+ * A2DP Source profile.
+ *
+ * <p>This intent will have 3 extras:
+ * <ul>
+ * <li> {@link #EXTRA_CODEC_CONFIG} - The current codec configuration. </li>
+ * <li> {@link #EXTRA_PREVIOUS_CODEC_CONFIG} - The previous codec configuration. </li>
+ * <li> {@link BluetoothDevice#EXTRA_DEVICE} - The remote device if the device is currently
+ * connected, otherwise it is not included.</li>
+ * </ul>
+ *
+ * <p>Requires {@link android.Manifest.permission#BLUETOOTH} permission to
+ * receive.
+ *
+ * @hide
+ */
+ @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
+ public static final String ACTION_CODEC_CONFIG_CHANGED =
+ "android.bluetooth.a2dp.profile.action.CODEC_CONFIG_CHANGED";
+
+ /**
* A2DP sink device is streaming music. This state can be one of
* {@link #EXTRA_STATE} or {@link #EXTRA_PREVIOUS_STATE} of
* {@link #ACTION_PLAYING_STATE_CHANGED} intent.
@@ -544,6 +565,54 @@
}
/**
+ * Gets the current codec configuration.
+ *
+ * @return the current codec configuration
+ * @hide
+ */
+ public BluetoothCodecConfig getCodecConfig() {
+ if (DBG) Log.d(TAG, "getCodecConfig");
+ try {
+ mServiceLock.readLock().lock();
+ if (mService != null && isEnabled()) {
+ return mService.getCodecConfig();
+ }
+ if (mService == null) {
+ Log.w(TAG, "Proxy not attached to service");
+ }
+ return null;
+ } catch (RemoteException e) {
+ Log.e(TAG, "Error talking to BT service in getCodecConfig()", e);
+ return null;
+ } finally {
+ mServiceLock.readLock().unlock();
+ }
+ }
+
+ /**
+ * Sets the codec configuration preference.
+ *
+ * @param codecConfig the codec configuration preference
+ * @hide
+ */
+ public void setCodecConfigPreference(BluetoothCodecConfig codecConfig) {
+ if (DBG) Log.d(TAG, "setCodecConfigPreference");
+ try {
+ mServiceLock.readLock().lock();
+ if (mService != null && isEnabled()) {
+ mService.setCodecConfigPreference(codecConfig);
+ }
+ if (mService == null) Log.w(TAG, "Proxy not attached to service");
+ return;
+ } catch (RemoteException e) {
+ Log.e(TAG, "Error talking to BT service in setCodecConfigPreference()", e);
+ return;
+ } finally {
+ mServiceLock.readLock().unlock();
+ }
+ }
+
+ /**
* Helper for converting a state to a string.
*
* For debug use only - strings are not internationalized.
diff --git a/wifi/java/android/net/wifi/aware/WifiAwareCharacteristics.aidl b/core/java/android/bluetooth/BluetoothCodecConfig.aidl
similarity index 89%
copy from wifi/java/android/net/wifi/aware/WifiAwareCharacteristics.aidl
copy to core/java/android/bluetooth/BluetoothCodecConfig.aidl
index a35e71d..553e66e 100644
--- a/wifi/java/android/net/wifi/aware/WifiAwareCharacteristics.aidl
+++ b/core/java/android/bluetooth/BluetoothCodecConfig.aidl
@@ -14,6 +14,6 @@
* limitations under the License.
*/
-package android.net.wifi.aware;
+package android.bluetooth;
-parcelable WifiAwareCharacteristics;
+parcelable BluetoothCodecConfig;
diff --git a/core/java/android/bluetooth/BluetoothCodecConfig.java b/core/java/android/bluetooth/BluetoothCodecConfig.java
new file mode 100644
index 0000000..52cd2de
--- /dev/null
+++ b/core/java/android/bluetooth/BluetoothCodecConfig.java
@@ -0,0 +1,294 @@
+/*
+ * Copyright (C) 2016 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 android.bluetooth;
+
+import android.os.Parcel;
+import android.os.Parcelable;
+
+import java.util.Objects;
+
+/**
+ * Represents the codec configuration for a Bluetooth A2DP source device.
+ *
+ * {@see BluetoothA2dp}
+ *
+ * {@hide}
+ */
+public final class BluetoothCodecConfig implements Parcelable {
+
+ /**
+ * Extra for the codec configuration intents of the individual profiles.
+ *
+ * This extra represents the current codec configuration of the A2DP
+ * profile.
+ */
+ public static final String EXTRA_CODEC_CONFIG = "android.bluetooth.codec.extra.CODEC_CONFIG";
+
+ /**
+ * Extra for the codec configuration intents of the individual profiles.
+ *
+ * This extra represents the previous codec configuration of the A2DP
+ * profile.
+ */
+ public static final String EXTRA_PREVIOUS_CODEC_CONFIG =
+ "android.bluetooth.codec.extra.PREVIOUS_CODEC_CONFIG";
+
+ // Add an entry for each source codec here.
+ // NOTE: The values should be same as those listed in the following file:
+ // hardware/libhardware/include/hardware/bt_av.h
+ public static final int SOURCE_CODEC_TYPE_SBC = 0;
+ public static final int SOURCE_CODEC_TYPE_APTX = 1;
+ public static final int SOURCE_CODEC_TYPE_APTX_HD = 2;
+ public static final int SOURCE_CODEC_TYPE_LDAC = 3;
+
+ public static final int SOURCE_CODEC_TYPE_INVALID = 1000 * 1000;
+
+ public static final int CODEC_PRIORITY_DEFAULT = 0;
+ public static final int CODEC_PRIORITY_HIGHEST = 1000 * 1000;
+
+ public static final int SAMPLE_RATE_NONE = 0;
+ public static final int SAMPLE_RATE_44100 = 0x1 << 0;
+ public static final int SAMPLE_RATE_48000 = 0x1 << 1;
+ public static final int SAMPLE_RATE_88200 = 0x1 << 2;
+ public static final int SAMPLE_RATE_96000 = 0x1 << 3;
+ public static final int SAMPLE_RATE_176400 = 0x1 << 4;
+ public static final int SAMPLE_RATE_192000 = 0x1 << 5;
+
+ public static final int BITS_PER_SAMPLE_NONE = 0;
+ public static final int BITS_PER_SAMPLE_16 = 0x1 << 0;
+ public static final int BITS_PER_SAMPLE_24 = 0x1 << 1;
+ public static final int BITS_PER_SAMPLE_32 = 0x1 << 2;
+
+ public static final int CHANNEL_MODE_NONE = 0;
+ public static final int CHANNEL_MODE_MONO = 0x1 << 0;
+ public static final int CHANNEL_MODE_STEREO = 0x1 << 1;
+
+ private final int mCodecType;
+ private final int mCodecPriority;
+ private final int mSampleRate;
+ private final int mBitsPerSample;
+ private final int mChannelMode;
+ private final long mCodecSpecific1;
+ private final long mCodecSpecific2;
+ private final long mCodecSpecific3;
+ private final long mCodecSpecific4;
+
+ public BluetoothCodecConfig(int codecType, int codecPriority,
+ int sampleRate, int bitsPerSample,
+ int channelMode,long codecSpecific1,
+ long codecSpecific2, long codecSpecific3,
+ long codecSpecific4) {
+ mCodecType = codecType;
+ mCodecPriority = codecPriority;
+ mSampleRate = sampleRate;
+ mBitsPerSample = bitsPerSample;
+ mChannelMode = channelMode;
+ mCodecSpecific1 = codecSpecific1;
+ mCodecSpecific2 = codecSpecific2;
+ mCodecSpecific3 = codecSpecific3;
+ mCodecSpecific4 = codecSpecific4;
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (o instanceof BluetoothCodecConfig) {
+ BluetoothCodecConfig other = (BluetoothCodecConfig)o;
+ return (other.mCodecType == mCodecType &&
+ other.mCodecPriority == mCodecPriority &&
+ other.mSampleRate == mSampleRate &&
+ other.mBitsPerSample == mBitsPerSample &&
+ other.mChannelMode == mChannelMode &&
+ other.mCodecSpecific1 == mCodecSpecific1 &&
+ other.mCodecSpecific2 == mCodecSpecific2 &&
+ other.mCodecSpecific3 == mCodecSpecific3 &&
+ other.mCodecSpecific4 == mCodecSpecific4);
+ }
+ return false;
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(mCodecType, mCodecPriority, mSampleRate,
+ mBitsPerSample, mChannelMode, mCodecSpecific1,
+ mCodecSpecific2, mCodecSpecific3, mCodecSpecific4);
+ }
+
+ @Override
+ public String toString() {
+ return "{mCodecType:" + mCodecType +
+ ",mCodecPriority:" + mCodecPriority +
+ ",mSampleRate:" + String.format("0x%x", mSampleRate) +
+ ",mBitsPerSample:" + String.format("0x%x", mBitsPerSample) +
+ ",mChannelMode:" + String.format("0x%x", mChannelMode) +
+ ",mCodecSpecific1:" + mCodecSpecific1 +
+ ",mCodecSpecific2:" + mCodecSpecific2 +
+ ",mCodecSpecific3:" + mCodecSpecific3 +
+ ",mCodecSpecific4:" + mCodecSpecific4 + "}";
+ }
+
+ public int describeContents() {
+ return 0;
+ }
+
+ public static final Parcelable.Creator<BluetoothCodecConfig> CREATOR =
+ new Parcelable.Creator<BluetoothCodecConfig>() {
+ public BluetoothCodecConfig createFromParcel(Parcel in) {
+ final int codecType = in.readInt();
+ final int codecPriority = in.readInt();
+ final int sampleRate = in.readInt();
+ final int bitsPerSample = in.readInt();
+ final int channelMode = in.readInt();
+ final long codecSpecific1 = in.readLong();
+ final long codecSpecific2 = in.readLong();
+ final long codecSpecific3 = in.readLong();
+ final long codecSpecific4 = in.readLong();
+ return new BluetoothCodecConfig(codecType, codecPriority,
+ sampleRate, bitsPerSample,
+ channelMode, codecSpecific1,
+ codecSpecific2, codecSpecific3,
+ codecSpecific4);
+ }
+ public BluetoothCodecConfig[] newArray(int size) {
+ return new BluetoothCodecConfig[size];
+ }
+ };
+
+ public void writeToParcel(Parcel out, int flags) {
+ out.writeInt(mCodecType);
+ out.writeInt(mCodecPriority);
+ out.writeInt(mSampleRate);
+ out.writeInt(mBitsPerSample);
+ out.writeInt(mChannelMode);
+ out.writeLong(mCodecSpecific1);
+ out.writeLong(mCodecSpecific2);
+ out.writeLong(mCodecSpecific3);
+ out.writeLong(mCodecSpecific4);
+ }
+
+ /**
+ * Returns the codec type.
+ * See {@link android.bluetooth.BluetoothCodecConfig#SOURCE_CODEC_TYPE_SBC}.
+ *
+ * @return the codec type
+ */
+ public int getCodecType() {
+ return mCodecType;
+ }
+
+ /**
+ * Returns the codec selection priority.
+ * The codec selection priority is relative to other codecs: larger value
+ * means higher priority. If 0, reset to default.
+ *
+ * @return the codec priority
+ */
+ public int getCodecPriority() {
+ return mCodecPriority;
+ }
+
+ /**
+ * Returns the codec sample rate. The value can be a bitmask with all
+ * supported sample rates:
+ * {@link android.bluetooth.BluetoothCodecConfig#SAMPLE_RATE_NONE} or
+ * {@link android.bluetooth.BluetoothCodecConfig#SAMPLE_RATE_44100} or
+ * {@link android.bluetooth.BluetoothCodecConfig#SAMPLE_RATE_48000} or
+ * {@link android.bluetooth.BluetoothCodecConfig#SAMPLE_RATE_88200} or
+ * {@link android.bluetooth.BluetoothCodecConfig#SAMPLE_RATE_96000} or
+ * {@link android.bluetooth.BluetoothCodecConfig#SAMPLE_RATE_176400} or
+ * {@link android.bluetooth.BluetoothCodecConfig#SAMPLE_RATE_192000}
+ *
+ * @return the codec sample rate
+ */
+ public int getSampleRate() {
+ return mSampleRate;
+ }
+
+ /**
+ * Returns the codec bits per sample. The value can be a bitmask with all
+ * bits per sample supported:
+ * {@link android.bluetooth.BluetoothCodecConfig#BITS_PER_SAMPLE_NONE} or
+ * {@link android.bluetooth.BluetoothCodecConfig#BITS_PER_SAMPLE_16} or
+ * {@link android.bluetooth.BluetoothCodecConfig#BITS_PER_SAMPLE_24} or
+ * {@link android.bluetooth.BluetoothCodecConfig#BITS_PER_SAMPLE_32}
+ *
+ * @return the codec bits per sample
+ */
+ public int getBitsPerSample() {
+ return mBitsPerSample;
+ }
+
+ /**
+ * Returns the codec channel mode. The value can be a bitmask with all
+ * supported channel modes:
+ * {@link android.bluetooth.BluetoothCodecConfig#CHANNEL_MODE_NONE} or
+ * {@link android.bluetooth.BluetoothCodecConfig#CHANNEL_MODE_MONO} or
+ * {@link android.bluetooth.BluetoothCodecConfig#CHANNEL_MODE_STEREO}
+ *
+ * @return the codec channel mode
+ */
+ public int getChannelMode() {
+ return mChannelMode;
+ }
+
+ /**
+ * Returns a codec specific value1.
+ *
+ * @return a codec specific value1.
+ */
+ public long getCodecSpecific1() {
+ return mCodecSpecific1;
+ }
+
+ /**
+ * Returns a codec specific value2.
+ *
+ * @return a codec specific value2
+ */
+ public long getCodecSpecific2() {
+ return mCodecSpecific2;
+ }
+
+ /**
+ * Returns a codec specific value3.
+ *
+ * @return a codec specific value3
+ */
+ public long getCodecSpecific3() {
+ return mCodecSpecific3;
+ }
+
+ /**
+ * Returns a codec specific value4.
+ *
+ * @return a codec specific value4
+ */
+ public long getCodecSpecific4() {
+ return mCodecSpecific4;
+ }
+
+ /**
+ * Checks whether the audio feeding parameters are same.
+ *
+ * @param other the codec config to compare against
+ * @return true if the audio feeding parameters are same, otherwise false
+ */
+ public boolean sameAudioFeedingParameters(BluetoothCodecConfig other) {
+ return (other != null && other.mSampleRate == mSampleRate &&
+ other.mBitsPerSample == mBitsPerSample &&
+ other.mChannelMode == mChannelMode);
+ }
+}
diff --git a/core/java/android/bluetooth/BluetoothHidDeviceCallback.java b/core/java/android/bluetooth/BluetoothHidDeviceCallback.java
index 0f0e050..f519776 100644
--- a/core/java/android/bluetooth/BluetoothHidDeviceCallback.java
+++ b/core/java/android/bluetooth/BluetoothHidDeviceCallback.java
@@ -45,9 +45,9 @@
* <code>false</code> otherwise.
*/
public void onAppStatusChanged(BluetoothDevice pluggedDevice,
- BluetoothHidDeviceAppConfiguration config, boolean registered) {
- Log.d(TAG, "onAppStatusChanged: pluggedDevice=" + (pluggedDevice == null ?
- null : pluggedDevice.toString()) + " registered=" + registered);
+ BluetoothHidDeviceAppConfiguration config, boolean registered) {
+ Log.d(TAG, "onAppStatusChanged: pluggedDevice=" + pluggedDevice + " registered="
+ + registered);
}
/**
@@ -60,13 +60,13 @@
* @param state Connection state as defined in {@link BluetoothProfile}.
*/
public void onConnectionStateChanged(BluetoothDevice device, int state) {
- Log.d(TAG, "onConnectionStateChanged: device=" + device.toString() + " state=" + state);
+ Log.d(TAG, "onConnectionStateChanged: device=" + device + " state=" + state);
}
/**
* Callback called when GET_REPORT is received from remote host. Should be
* replied by application using
- * {@link BluetoothHidDevice#replyReport(byte, byte, byte[])}.
+ * {@link BluetoothHidDevice#replyReport(BluetoothDevice, byte, byte, byte[])}.
*
* @param type Requested Report Type.
* @param id Requested Report Id, can be 0 if no Report Id are defined in
@@ -74,21 +74,22 @@
* @param bufferSize Requested buffer size, application shall respond with
* at least given number of bytes.
*/
- public void onGetReport(byte type, byte id, int bufferSize) {
- Log.d(TAG, "onGetReport: type=" + type + " id=" + id + " bufferSize=" + bufferSize);
+ public void onGetReport(BluetoothDevice device, byte type, byte id, int bufferSize) {
+ Log.d(TAG, "onGetReport: device=" + device + " type=" + type + " id=" + id + " bufferSize="
+ + bufferSize);
}
/**
* Callback called when SET_REPORT is received from remote host. In case
* received data are invalid, application shall respond with
- * {@link BluetoothHidDevice#reportError()}.
+ * {@link BluetoothHidDevice#reportError(BluetoothDevice)}.
*
* @param type Report Type.
* @param id Report Id.
* @param data Report data.
*/
- public void onSetReport(byte type, byte id, byte[] data) {
- Log.d(TAG, "onSetReport: type=" + type + " id=" + id);
+ public void onSetReport(BluetoothDevice device, byte type, byte id, byte[] data) {
+ Log.d(TAG, "onSetReport: device=" + device + " type=" + type + " id=" + id);
}
/**
@@ -99,8 +100,8 @@
*
* @param protocol Protocol Mode.
*/
- public void onSetProtocol(byte protocol) {
- Log.d(TAG, "onSetProtocol: protocol=" + protocol);
+ public void onSetProtocol(BluetoothDevice device, byte protocol) {
+ Log.d(TAG, "onSetProtocol: device=" + device + " protocol=" + protocol);
}
/**
@@ -111,16 +112,17 @@
* @param reportId Report Id.
* @param data Report data.
*/
- public void onIntrData(byte reportId, byte[] data) {
- Log.d(TAG, "onIntrData: reportId=" + reportId);
+ public void onIntrData(BluetoothDevice device, byte reportId, byte[] data) {
+ Log.d(TAG, "onIntrData: device=" + device + " reportId=" + reportId);
}
/**
* Callback called when Virtual Cable is removed. This can be either due to
- * {@link BluetoothHidDevice#unplug()} or request from remote side. After
- * this callback is received connection will be disconnected automatically.
+ * {@link BluetoothHidDevice#unplug(BluetoothDevice)} or request from remote
+ * side. After this callback is received connection will be disconnected
+ * automatically.
*/
- public void onVirtualCableUnplug() {
- Log.d(TAG, "onVirtualCableUnplug");
+ public void onVirtualCableUnplug(BluetoothDevice device) {
+ Log.d(TAG, "onVirtualCableUnplug: device=" + device);
}
}
diff --git a/core/java/android/bluetooth/BluetoothInputHost.java b/core/java/android/bluetooth/BluetoothInputHost.java
index 129fe7e..68d105f 100644
--- a/core/java/android/bluetooth/BluetoothInputHost.java
+++ b/core/java/android/bluetooth/BluetoothInputHost.java
@@ -27,6 +27,7 @@
import android.util.Log;
import java.util.Arrays;
+import java.util.ArrayList;
import java.util.List;
/**
@@ -137,28 +138,28 @@
}
@Override
- public void onGetReport(byte type, byte id, int bufferSize) {
- mCallback.onGetReport(type, id, bufferSize);
+ public void onGetReport(BluetoothDevice device, byte type, byte id, int bufferSize) {
+ mCallback.onGetReport(device, type, id, bufferSize);
}
@Override
- public void onSetReport(byte type, byte id, byte[] data) {
- mCallback.onSetReport(type, id, data);
+ public void onSetReport(BluetoothDevice device, byte type, byte id, byte[] data) {
+ mCallback.onSetReport(device, type, id, data);
}
@Override
- public void onSetProtocol(byte protocol) {
- mCallback.onSetProtocol(protocol);
+ public void onSetProtocol(BluetoothDevice device, byte protocol) {
+ mCallback.onSetProtocol(device, protocol);
}
@Override
- public void onIntrData(byte reportId, byte[] data) {
- mCallback.onIntrData(reportId, data);
+ public void onIntrData(BluetoothDevice device, byte reportId, byte[] data) {
+ mCallback.onIntrData(device, reportId, data);
}
@Override
- public void onVirtualCableUnplug() {
- mCallback.onVirtualCableUnplug();
+ public void onVirtualCableUnplug(BluetoothDevice device) {
+ mCallback.onVirtualCableUnplug(device);
}
}
@@ -276,21 +277,59 @@
mServiceListener = null;
}
- @Override
+ /**
+ * {@inheritDoc}
+ */
public List<BluetoothDevice> getConnectedDevices() {
Log.v(TAG, "getConnectedDevices()");
- return null;
+
+ if (mService != null) {
+ try {
+ return mService.getConnectedDevices();
+ } catch (RemoteException e) {
+ Log.e(TAG, e.toString());
+ }
+ } else {
+ Log.w(TAG, "Proxy not attached to service");
+ }
+
+ return new ArrayList<BluetoothDevice>();
}
- @Override
+ /**
+ * {@inheritDoc}
+ */
public List<BluetoothDevice> getDevicesMatchingConnectionStates(int[] states) {
Log.v(TAG, "getDevicesMatchingConnectionStates(): states=" + Arrays.toString(states));
- return null;
+
+ if (mService != null) {
+ try {
+ return mService.getDevicesMatchingConnectionStates(states);
+ } catch (RemoteException e) {
+ Log.e(TAG, e.toString());
+ }
+ } else {
+ Log.w(TAG, "Proxy not attached to service");
+ }
+
+ return new ArrayList<BluetoothDevice>();
}
- @Override
+ /**
+ * {@inheritDoc}
+ */
public int getConnectionState(BluetoothDevice device) {
- Log.v(TAG, "getConnectionState(): device=" + device.getAddress());
+ Log.v(TAG, "getConnectionState(): device=" + device);
+
+ if (mService != null) {
+ try {
+ return mService.getConnectionState(device);
+ } catch (RemoteException e) {
+ Log.e(TAG, e.toString());
+ }
+ } else {
+ Log.w(TAG, "Proxy not attached to service");
+ }
return STATE_DISCONNECTED;
}
@@ -379,14 +418,12 @@
* @param data Report data, not including Report Id.
* @return
*/
- public boolean sendReport(int id, byte[] data) {
- Log.v(TAG, "sendReport(): id=" + id);
-
+ public boolean sendReport(BluetoothDevice device, int id, byte[] data) {
boolean result = false;
if (mService != null) {
try {
- result = mService.sendReport(id, data);
+ result = mService.sendReport(device, id, data);
} catch (RemoteException e) {
Log.e(TAG, e.toString());
}
@@ -399,21 +436,21 @@
/**
* Sends report to remote host as reply for GET_REPORT request from
- * {@link BluetoothHidDeviceCallback#onGetReport(byte, byte, int)}.
+ * {@link BluetoothHidDeviceCallback#onGetReport(BluetoothDevice, byte, byte, int)}.
*
* @param type Report Type, as in request.
* @param id Report Id, as in request.
* @param data Report data, not including Report Id.
* @return
*/
- public boolean replyReport(byte type, byte id, byte[] data) {
- Log.v(TAG, "replyReport(): type=" + type + " id=" + id);
+ public boolean replyReport(BluetoothDevice device, byte type, byte id, byte[] data) {
+ Log.v(TAG, "replyReport(): device=" + device + " type=" + type + " id=" + id);
boolean result = false;
if (mService != null) {
try {
- result = mService.replyReport(type, id, data);
+ result = mService.replyReport(device, type, id, data);
} catch (RemoteException e) {
Log.e(TAG, e.toString());
}
@@ -426,19 +463,19 @@
/**
* Sends error handshake message as reply for invalid SET_REPORT request
- * from {@link BluetoothHidDeviceCallback#onSetReport(byte, byte, byte[])}.
+ * from {@link BluetoothHidDeviceCallback#onSetReport(BluetoothDevice, byte, byte, byte[])}.
*
* @param error Error to be sent for SET_REPORT via HANDSHAKE.
* @return
*/
- public boolean reportError(byte error) {
- Log.v(TAG, "reportError(): error = " + error);
+ public boolean reportError(BluetoothDevice device, byte error) {
+ Log.v(TAG, "reportError(): device=" + device + " error=" + error);
boolean result = false;
if (mService != null) {
try {
- result = mService.reportError(error);
+ result = mService.reportError(device, error);
} catch (RemoteException e) {
Log.e(TAG, e.toString());
}
@@ -454,14 +491,14 @@
*
* @return
*/
- public boolean unplug() {
- Log.v(TAG, "unplug()");
+ public boolean unplug(BluetoothDevice device) {
+ Log.v(TAG, "unplug(): device=" + device);
boolean result = false;
if (mService != null) {
try {
- result = mService.unplug();
+ result = mService.unplug(device);
} catch (RemoteException e) {
Log.e(TAG, e.toString());
}
@@ -478,14 +515,14 @@
*
* @return
*/
- public boolean connect() {
- Log.v(TAG, "connect()");
+ public boolean connect(BluetoothDevice device) {
+ Log.v(TAG, "connect(): device=" + device);
boolean result = false;
if (mService != null) {
try {
- result = mService.connect();
+ result = mService.connect(device);
} catch (RemoteException e) {
Log.e(TAG, e.toString());
}
@@ -501,14 +538,14 @@
*
* @return
*/
- public boolean disconnect() {
- Log.v(TAG, "disconnect()");
+ public boolean disconnect(BluetoothDevice device) {
+ Log.v(TAG, "disconnect(): device=" + device);
boolean result = false;
if (mService != null) {
try {
- result = mService.disconnect();
+ result = mService.disconnect(device);
} catch (RemoteException e) {
Log.e(TAG, e.toString());
}
diff --git a/core/java/android/bluetooth/IBluetoothA2dp.aidl b/core/java/android/bluetooth/IBluetoothA2dp.aidl
index 26ff9e27..5b524eb 100644
--- a/core/java/android/bluetooth/IBluetoothA2dp.aidl
+++ b/core/java/android/bluetooth/IBluetoothA2dp.aidl
@@ -16,6 +16,7 @@
package android.bluetooth;
+import android.bluetooth.BluetoothCodecConfig;
import android.bluetooth.BluetoothDevice;
/**
@@ -36,4 +37,6 @@
oneway void adjustAvrcpAbsoluteVolume(int direction);
oneway void setAvrcpAbsoluteVolume(int volume);
boolean isA2dpPlaying(in BluetoothDevice device);
+ BluetoothCodecConfig getCodecConfig();
+ oneway void setCodecConfigPreference(in BluetoothCodecConfig codecConfig);
}
diff --git a/core/java/android/bluetooth/IBluetoothHidDeviceCallback.aidl b/core/java/android/bluetooth/IBluetoothHidDeviceCallback.aidl
index 1252876..a737198 100644
--- a/core/java/android/bluetooth/IBluetoothHidDeviceCallback.aidl
+++ b/core/java/android/bluetooth/IBluetoothHidDeviceCallback.aidl
@@ -23,9 +23,9 @@
interface IBluetoothHidDeviceCallback {
void onAppStatusChanged(in BluetoothDevice device, in BluetoothHidDeviceAppConfiguration config, boolean registered);
void onConnectionStateChanged(in BluetoothDevice device, in int state);
- void onGetReport(in byte type, in byte id, in int bufferSize);
- void onSetReport(in byte type, in byte id, in byte[] data);
- void onSetProtocol(in byte protocol);
- void onIntrData(in byte reportId, in byte[] data);
- void onVirtualCableUnplug();
+ void onGetReport(in BluetoothDevice device, in byte type, in byte id, in int bufferSize);
+ void onSetReport(in BluetoothDevice device, in byte type, in byte id, in byte[] data);
+ void onSetProtocol(in BluetoothDevice device, in byte protocol);
+ void onIntrData(in BluetoothDevice device, in byte reportId, in byte[] data);
+ void onVirtualCableUnplug(in BluetoothDevice device);
}
diff --git a/core/java/android/bluetooth/IBluetoothInputHost.aidl b/core/java/android/bluetooth/IBluetoothInputHost.aidl
index b2c421c..6c4993f 100644
--- a/core/java/android/bluetooth/IBluetoothInputHost.aidl
+++ b/core/java/android/bluetooth/IBluetoothInputHost.aidl
@@ -28,10 +28,13 @@
in BluetoothHidDeviceAppSdpSettings sdp, in BluetoothHidDeviceAppQosSettings inQos,
in BluetoothHidDeviceAppQosSettings outQos, in IBluetoothHidDeviceCallback callback);
boolean unregisterApp(in BluetoothHidDeviceAppConfiguration config);
- boolean sendReport(in int id, in byte[] data);
- boolean replyReport(in byte type, in byte id, in byte[] data);
- boolean reportError(byte error);
- boolean unplug();
- boolean connect();
- boolean disconnect();
+ boolean sendReport(in BluetoothDevice device, in int id, in byte[] data);
+ boolean replyReport(in BluetoothDevice device, in byte type, in byte id, in byte[] data);
+ boolean reportError(in BluetoothDevice device, byte error);
+ boolean unplug(in BluetoothDevice device);
+ boolean connect(in BluetoothDevice device);
+ boolean disconnect(in BluetoothDevice device);
+ List<BluetoothDevice> getConnectedDevices();
+ List<BluetoothDevice> getDevicesMatchingConnectionStates(in int[] states);
+ int getConnectionState(in BluetoothDevice device);
}
diff --git a/core/java/android/content/Context.java b/core/java/android/content/Context.java
index 9dc60ab..ffe1248 100644
--- a/core/java/android/content/Context.java
+++ b/core/java/android/content/Context.java
@@ -2680,6 +2680,7 @@
SEARCH_SERVICE,
SENSOR_SERVICE,
STORAGE_SERVICE,
+ STORAGE_STATS_SERVICE,
WALLPAPER_SERVICE,
VIBRATOR_SERVICE,
//@hide: STATUS_BAR_SERVICE,
@@ -3077,6 +3078,16 @@
public static final String STORAGE_SERVICE = "storage";
/**
+ * Use with {@link #getSystemService} to retrieve a {@link
+ * android.app.usage.StorageStatsManager} for accessing system storage
+ * statistics.
+ *
+ * @see #getSystemService
+ * @see android.app.usage.StorageStatsManager
+ */
+ public static final String STORAGE_STATS_SERVICE = "storagestats";
+
+ /**
* Use with {@link #getSystemService} to retrieve a
* com.android.server.WallpaperService for accessing wallpapers.
*
diff --git a/core/java/android/content/IntentFilter.java b/core/java/android/content/IntentFilter.java
index 7036f87..e6cae69 100644
--- a/core/java/android/content/IntentFilter.java
+++ b/core/java/android/content/IntentFilter.java
@@ -1883,7 +1883,8 @@
*/
}
- private IntentFilter(Parcel source) {
+ /** @hide */
+ public IntentFilter(Parcel source) {
mActions = new ArrayList<String>();
source.readStringList(mActions);
if (source.readInt() != 0) {
diff --git a/core/java/android/content/pm/ApplicationInfo.java b/core/java/android/content/pm/ApplicationInfo.java
index 9b99bbf..adc99d3 100644
--- a/core/java/android/content/pm/ApplicationInfo.java
+++ b/core/java/android/content/pm/ApplicationInfo.java
@@ -36,6 +36,8 @@
import java.util.Comparator;
import java.util.Objects;
+import static android.os.Build.VERSION_CODES.DONUT;
+
/**
* Information you can retrieve about a particular application. This
* corresponds to information collected from the AndroidManifest.xml's
@@ -1085,6 +1087,18 @@
FLAG_SUPPORTS_SCREEN_DENSITIES | FLAG_SUPPORTS_XLARGE_SCREENS);
}
+ /**
+ * Is using compatibility mode for non densty aware legacy applications.
+ *
+ * @hide
+ */
+ public boolean usesCompatibilityMode() {
+ return targetSdkVersion < DONUT ||
+ (flags & (FLAG_SUPPORTS_LARGE_SCREENS | FLAG_SUPPORTS_NORMAL_SCREENS |
+ FLAG_SUPPORTS_SMALL_SCREENS | FLAG_RESIZEABLE_FOR_SCREENS |
+ FLAG_SUPPORTS_SCREEN_DENSITIES | FLAG_SUPPORTS_XLARGE_SCREENS)) == 0;
+ }
+
/** {@hide} */
public void initForUser(int userId) {
uid = UserHandle.getUid(userId, UserHandle.getAppId(uid));
diff --git a/core/java/android/content/pm/LauncherApps.java b/core/java/android/content/pm/LauncherApps.java
index 5f4bc00..4b5b995 100644
--- a/core/java/android/content/pm/LauncherApps.java
+++ b/core/java/android/content/pm/LauncherApps.java
@@ -22,6 +22,7 @@
import android.annotation.SdkConstant;
import android.annotation.SdkConstant.SdkConstantType;
import android.annotation.TestApi;
+import android.appwidget.AppWidgetProviderInfo;
import android.content.ActivityNotFoundException;
import android.content.ComponentName;
import android.content.Context;
@@ -1138,21 +1139,35 @@
/** This is a request to pin shortcut. */
public static final int REQUEST_TYPE_SHORTCUT = 1;
+ /** This is a request to pin app widget. */
+ public static final int REQUEST_TYPE_APPWIDGET = 2;
+
@IntDef(value = {REQUEST_TYPE_SHORTCUT})
@Retention(RetentionPolicy.SOURCE)
public @interface RequestType {}
private final int mRequestType;
private final ShortcutInfo mShortcutInfo;
+ private final AppWidgetProviderInfo mAppWidgetInfo;
private final IPinItemRequest mInner;
/**
* @hide
*/
- public PinItemRequest(@RequestType int requestType, ShortcutInfo shortcutInfo,
- IPinItemRequest inner) {
- mRequestType = requestType;
+ public PinItemRequest(ShortcutInfo shortcutInfo, IPinItemRequest inner) {
+ mRequestType = REQUEST_TYPE_SHORTCUT;
mShortcutInfo = shortcutInfo;
+ mAppWidgetInfo = null;
+ mInner = inner;
+ }
+
+ /**
+ * @hide
+ */
+ public PinItemRequest(AppWidgetProviderInfo appWidgetInfo, IPinItemRequest inner) {
+ mRequestType = REQUEST_TYPE_APPWIDGET;
+ mShortcutInfo = null;
+ mAppWidgetInfo = appWidgetInfo;
mInner = inner;
}
@@ -1175,6 +1190,15 @@
}
/**
+ * {@link AppWidgetProviderInfo} sent by the requesting app. Always non-null for a
+ * {@link #REQUEST_TYPE_APPWIDGET} request.
+ */
+ @Nullable
+ public AppWidgetProviderInfo getAppWidgetProviderInfo() {
+ return mAppWidgetInfo;
+ }
+
+ /**
* Return {@code TRUE} if a request is valid -- i.e. {@link #accept(Bundle)} has not been
* called, and it has not been canceled.
*/
@@ -1208,14 +1232,22 @@
final ClassLoader cl = getClass().getClassLoader();
mRequestType = source.readInt();
- mShortcutInfo = source.readParcelable(cl);
+ mShortcutInfo = mRequestType == REQUEST_TYPE_SHORTCUT ?
+ (ShortcutInfo) source.readParcelable(cl) : null;
+ mAppWidgetInfo = mRequestType == REQUEST_TYPE_APPWIDGET ?
+ (AppWidgetProviderInfo) source.readParcelable(cl) : null;
mInner = IPinItemRequest.Stub.asInterface(source.readStrongBinder());
}
@Override
public void writeToParcel(Parcel dest, int flags) {
dest.writeInt(mRequestType);
- dest.writeParcelable(mShortcutInfo, flags);
+ if (mRequestType == REQUEST_TYPE_SHORTCUT) {
+ dest.writeParcelable(mShortcutInfo, flags);
+ }
+ if (mRequestType == REQUEST_TYPE_APPWIDGET) {
+ dest.writeParcelable(mAppWidgetInfo, flags);
+ }
dest.writeStrongBinder(mInner.asBinder());
}
diff --git a/core/java/android/content/pm/PackageParser.java b/core/java/android/content/pm/PackageParser.java
index 2236291..ad1ed55 100644
--- a/core/java/android/content/pm/PackageParser.java
+++ b/core/java/android/content/pm/PackageParser.java
@@ -16,6 +16,8 @@
package android.content.pm;
+import android.os.Parcel;
+import android.os.Parcelable;
import com.android.internal.R;
import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.util.ArrayUtils;
@@ -65,6 +67,7 @@
import java.io.IOException;
import java.io.InputStream;
import java.io.PrintWriter;
+import java.lang.reflect.Constructor;
import java.security.GeneralSecurityException;
import java.security.KeyFactory;
import java.security.NoSuchAlgorithmException;
@@ -80,6 +83,7 @@
import java.util.Comparator;
import java.util.Iterator;
import java.util.List;
+import java.util.Objects;
import java.util.Set;
import java.util.concurrent.atomic.AtomicReference;
import java.util.zip.ZipEntry;
@@ -307,14 +311,16 @@
}
}
- static class ParseComponentArgs extends ParsePackageItemArgs {
+ /** @hide */
+ @VisibleForTesting
+ public static class ParseComponentArgs extends ParsePackageItemArgs {
final String[] sepProcesses;
final int processRes;
final int descriptionRes;
final int enabledRes;
int flags;
- ParseComponentArgs(Package _owner, String[] _outError,
+ public ParseComponentArgs(Package _owner, String[] _outError,
int _nameRes, int _labelRes, int _iconRes, int _roundIconRes, int _logoRes,
int _bannerRes,
String[] _sepProcesses, int _processRes,
@@ -874,12 +880,24 @@
@VisibleForTesting
protected Package fromCacheEntry(byte[] bytes) throws IOException {
- return null;
+ Parcel p = Parcel.obtain();
+ p.unmarshall(bytes, 0, bytes.length);
+ p.setDataPosition(0);
+
+ PackageParser.Package pkg = new PackageParser.Package(p);
+ p.recycle();
+
+ return pkg;
}
@VisibleForTesting
protected byte[] toCacheEntry(Package pkg) throws IOException {
- return null;
+ Parcel p = Parcel.obtain();
+ pkg.writeToParcel(p, 0 /* flags */);
+ byte[] serialized = p.marshall();
+ p.recycle();
+
+ return serialized;
}
/**
@@ -1344,6 +1362,11 @@
verified = true;
} catch (ApkSignatureSchemeV2Verifier.SignatureNotFoundException e) {
// No APK Signature Scheme v2 signature found
+ if ((parseFlags & PARSE_IS_EPHEMERAL) != 0) {
+ throw new PackageParserException(INSTALL_PARSE_FAILED_NO_CERTIFICATES,
+ "No APK Signature Scheme v2 signature in ephemeral package " + apkPath,
+ e);
+ }
} catch (Exception e) {
// APK Signature Scheme v2 signature was found but did not verify
throw new PackageParserException(INSTALL_PARSE_FAILED_NO_CERTIFICATES,
@@ -1516,10 +1539,10 @@
final Certificate[][] certificates;
if ((flags & PARSE_COLLECT_CERTIFICATES) != 0) {
// TODO: factor signature related items out of Package object
- final Package tempPkg = new Package(null);
+ final Package tempPkg = new Package((String) null);
Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "collectCertificates");
try {
- collectCertificates(tempPkg, apkFile, 0 /*parseFlags*/);
+ collectCertificates(tempPkg, apkFile, flags);
} finally {
Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER);
}
@@ -2364,10 +2387,28 @@
pkg.applicationInfo.flags |= ApplicationInfo.FLAG_SUPPORTS_SCREEN_DENSITIES;
}
+ // At this point we can check if an application is not supporting densities and hence
+ // cannot be windowed / resized. Note that an SDK version of 0 is common for
+ // pre-Doughnut applications.
+ if (pkg.applicationInfo.usesCompatibilityMode()) {
+ adjustPackageToBeUnresizeable(pkg);
+ }
return pkg;
}
/**
+ * This is a pre-density application which will get scaled - instead of being pixel perfect.
+ * This type of application is not resizable.
+ *
+ * @param pkg The package which needs to be marked as unresizable.
+ */
+ private void adjustPackageToBeUnresizeable(Package pkg) {
+ for (Activity a : pkg.activities) {
+ a.info.resizeMode = RESIZE_MODE_UNRESIZEABLE;
+ }
+ }
+
+ /**
* Computes the targetSdkVersion to use at runtime. If the package is not
* compatible with this platform, populates {@code outError[0]} with an
* error message.
@@ -3623,6 +3664,13 @@
private static boolean parsePackageItemInfo(Package owner, PackageItemInfo outInfo,
String[] outError, String tag, TypedArray sa, boolean nameRequired,
int nameRes, int labelRes, int iconRes, int roundIconRes, int logoRes, int bannerRes) {
+ // This case can only happen in unit tests where we sometimes need to create fakes
+ // of various package parser data structures.
+ if (sa == null) {
+ outError[0] = tag + " does not contain any attributes";
+ return false;
+ }
+
String name = sa.getNonConfigurationString(nameRes, 0);
if (name == null) {
if (nameRequired) {
@@ -5113,7 +5161,7 @@
* Representation of a full package parsed from APK files on disk. A package
* consists of a single base APK, and zero or more split APKs.
*/
- public final static class Package {
+ public final static class Package implements Parcelable {
public String packageName;
@@ -5154,7 +5202,7 @@
public boolean baseHardwareAccelerated;
// For now we only support one application per package.
- public final ApplicationInfo applicationInfo = new ApplicationInfo();
+ public ApplicationInfo applicationInfo = new ApplicationInfo();
public final ArrayList<Permission> permissions = new ArrayList<Permission>(0);
public final ArrayList<PermissionGroup> permissionGroups = new ArrayList<PermissionGroup>(0);
@@ -5578,13 +5626,296 @@
+ Integer.toHexString(System.identityHashCode(this))
+ " " + packageName + "}";
}
+
+ @Override
+ public int describeContents() {
+ return 0;
+ }
+
+ public Package(Parcel dest) {
+ // We use the boot classloader for all classes that we load.
+ final ClassLoader boot = Object.class.getClassLoader();
+
+ packageName = dest.readString();
+ splitNames = dest.readStringArray();
+ volumeUuid = dest.readString();
+ codePath = dest.readString();
+ baseCodePath = dest.readString();
+ splitCodePaths = dest.readStringArray();
+ baseRevisionCode = dest.readInt();
+ splitRevisionCodes = dest.createIntArray();
+ splitFlags = dest.createIntArray();
+ splitPrivateFlags = dest.createIntArray();
+ baseHardwareAccelerated = (dest.readInt() == 1);
+ applicationInfo = dest.readParcelable(boot);
+
+ // We don't serialize the "owner" package and the application info object for each of
+ // these components, in order to save space and to avoid circular dependencies while
+ // serialization. We need to fix them all up here.
+ dest.readParcelableList(permissions, boot);
+ fixupOwner(permissions);
+ dest.readParcelableList(permissionGroups, boot);
+ fixupOwner(permissionGroups);
+ dest.readParcelableList(activities, boot);
+ fixupOwner(activities);
+ dest.readParcelableList(receivers, boot);
+ fixupOwner(receivers);
+ dest.readParcelableList(providers, boot);
+ fixupOwner(providers);
+ dest.readParcelableList(services, boot);
+ fixupOwner(services);
+ dest.readParcelableList(instrumentation, boot);
+ fixupOwner(instrumentation);
+
+ dest.readStringList(requestedPermissions);
+ protectedBroadcasts = dest.createStringArrayList();
+ parentPackage = dest.readParcelable(boot);
+
+ childPackages = new ArrayList<>();
+ dest.readParcelableList(childPackages, boot);
+ if (childPackages.size() == 0) {
+ childPackages = null;
+ }
+
+ libraryNames = dest.createStringArrayList();
+ usesLibraries = dest.createStringArrayList();
+ usesOptionalLibraries = dest.createStringArrayList();
+ usesLibraryFiles = dest.readStringArray();
+
+ preferredActivityFilters = new ArrayList<>();
+ dest.readParcelableList(preferredActivityFilters, boot);
+ if (preferredActivityFilters.size() == 0) {
+ preferredActivityFilters = null;
+ }
+
+ mOriginalPackages = dest.createStringArrayList();
+ mRealPackage = dest.readString();
+ mAdoptPermissions = dest.createStringArrayList();
+ mAppMetaData = dest.readBundle();
+ mVersionCode = dest.readInt();
+ mVersionName = dest.readString();
+ mSharedUserId = dest.readString();
+ mSharedUserLabel = dest.readInt();
+
+ mSignatures = (Signature[]) dest.readParcelableArray(boot, Signature.class);
+ mCertificates = (Certificate[][]) dest.readSerializable();
+
+ mPreferredOrder = dest.readInt();
+
+ // long[] packageUsageTimeMillis is not persisted because it isn't information that
+ // is parsed from the APK.
+
+ // Object mExtras is not persisted because it is not information that is read from
+ // the APK, rather, it is supplied by callers.
+
+
+ configPreferences = new ArrayList<>();
+ dest.readParcelableList(configPreferences, boot);
+ if (configPreferences.size() == 0) {
+ configPreferences = null;
+ }
+
+ reqFeatures = new ArrayList<>();
+ dest.readParcelableList(reqFeatures, boot);
+ if (reqFeatures.size() == 0) {
+ reqFeatures = null;
+ }
+
+ featureGroups = new ArrayList<>();
+ dest.readParcelableList(featureGroups, boot);
+ if (featureGroups.size() == 0) {
+ featureGroups = null;
+ }
+
+ installLocation = dest.readInt();
+ coreApp = (dest.readInt() == 1);
+ mRequiredForAllUsers = (dest.readInt() == 1);
+ mRestrictedAccountType = dest.readString();
+ mRequiredAccountType = dest.readString();
+ mOverlayTarget = dest.readString();
+ mOverlayPriority = dest.readInt();
+ mTrustedOverlay = (dest.readInt() == 1);
+ mSigningKeys = (ArraySet<PublicKey>) dest.readArraySet(boot);
+ mUpgradeKeySets = (ArraySet<String>) dest.readArraySet(boot);
+
+ mKeySetMapping = readKeySetMapping(dest);
+
+ cpuAbiOverride = dest.readString();
+ use32bitAbi = (dest.readInt() == 1);
+ restrictUpdateHash = dest.createByteArray();
+ }
+
+ /**
+ * Sets the package owner and the the {@code applicationInfo} for every component
+ * owner by this package.
+ */
+ private void fixupOwner(List<? extends Component<?>> list) {
+ if (list != null) {
+ for (Component<?> c : list) {
+ c.owner = this;
+ if (c instanceof Activity) {
+ ((Activity) c).info.applicationInfo = this.applicationInfo;
+ } else if (c instanceof Service) {
+ ((Service) c).info.applicationInfo = this.applicationInfo;
+ } else if (c instanceof Provider) {
+ ((Provider) c).info.applicationInfo = this.applicationInfo;
+ }
+ }
+ }
+ }
+
+ @Override
+ public void writeToParcel(Parcel dest, int flags) {
+ dest.writeString(packageName);
+ dest.writeStringArray(splitNames);
+ dest.writeString(volumeUuid);
+ dest.writeString(codePath);
+ dest.writeString(baseCodePath);
+ dest.writeStringArray(splitCodePaths);
+ dest.writeInt(baseRevisionCode);
+ dest.writeIntArray(splitRevisionCodes);
+ dest.writeIntArray(splitFlags);
+ dest.writeIntArray(splitPrivateFlags);
+ dest.writeInt(baseHardwareAccelerated ? 1 : 0);
+ dest.writeParcelable(applicationInfo, flags);
+
+ dest.writeParcelableList(permissions, flags);
+ dest.writeParcelableList(permissionGroups, flags);
+ dest.writeParcelableList(activities, flags);
+ dest.writeParcelableList(receivers, flags);
+ dest.writeParcelableList(providers, flags);
+ dest.writeParcelableList(services, flags);
+ dest.writeParcelableList(instrumentation, flags);
+
+ dest.writeStringList(requestedPermissions);
+ dest.writeStringList(protectedBroadcasts);
+ dest.writeParcelable(parentPackage, flags);
+ dest.writeParcelableList(childPackages, flags);
+ dest.writeStringList(libraryNames);
+ dest.writeStringList(usesLibraries);
+ dest.writeStringList(usesOptionalLibraries);
+ dest.writeStringArray(usesLibraryFiles);
+
+ dest.writeParcelableList(preferredActivityFilters, flags);
+
+ dest.writeStringList(mOriginalPackages);
+ dest.writeString(mRealPackage);
+ dest.writeStringList(mAdoptPermissions);
+ dest.writeBundle(mAppMetaData);
+ dest.writeInt(mVersionCode);
+ dest.writeString(mVersionName);
+ dest.writeString(mSharedUserId);
+ dest.writeInt(mSharedUserLabel);
+
+ dest.writeParcelableArray(mSignatures, flags);
+ dest.writeSerializable(mCertificates);
+
+ dest.writeInt(mPreferredOrder);
+
+ // long[] packageUsageTimeMillis is not persisted because it isn't information that
+ // is parsed from the APK.
+
+ // Object mExtras is not persisted because it is not information that is read from
+ // the APK, rather, it is supplied by callers.
+
+ dest.writeParcelableList(configPreferences, flags);
+ dest.writeParcelableList(reqFeatures, flags);
+ dest.writeParcelableList(featureGroups, flags);
+
+ dest.writeInt(installLocation);
+ dest.writeInt(coreApp ? 1 : 0);
+ dest.writeInt(mRequiredForAllUsers ? 1 : 0);
+ dest.writeString(mRestrictedAccountType);
+ dest.writeString(mRequiredAccountType);
+ dest.writeString(mOverlayTarget);
+ dest.writeInt(mOverlayPriority);
+ dest.writeInt(mTrustedOverlay ? 1 : 0);
+ dest.writeArraySet(mSigningKeys);
+ dest.writeArraySet(mUpgradeKeySets);
+ writeKeySetMapping(dest, mKeySetMapping);
+ dest.writeString(cpuAbiOverride);
+ dest.writeInt(use32bitAbi ? 1 : 0);
+ dest.writeByteArray(restrictUpdateHash);
+ }
+
+
+ /**
+ * Writes the keyset mapping to the provided package. {@code null} mappings are permitted.
+ */
+ private static void writeKeySetMapping(
+ Parcel dest, ArrayMap<String, ArraySet<PublicKey>> keySetMapping) {
+ if (keySetMapping == null) {
+ dest.writeInt(-1);
+ return;
+ }
+
+ final int N = keySetMapping.size();
+ dest.writeInt(N);
+
+ for (int i = 0; i < N; i++) {
+ dest.writeString(keySetMapping.keyAt(i));
+ ArraySet<PublicKey> keys = keySetMapping.valueAt(i);
+ if (keys == null) {
+ dest.writeInt(-1);
+ continue;
+ }
+
+ final int M = keys.size();
+ dest.writeInt(M);
+ for (int j = 0; j < M; j++) {
+ dest.writeSerializable(keys.valueAt(j));
+ }
+ }
+ }
+
+ /**
+ * Reads a keyset mapping from the given parcel at the given data position. May return
+ * {@code null} if the serialized mapping was {@code null}.
+ */
+ private static ArrayMap<String, ArraySet<PublicKey>> readKeySetMapping(Parcel in) {
+ final int N = in.readInt();
+ if (N == -1) {
+ return null;
+ }
+
+ ArrayMap<String, ArraySet<PublicKey>> keySetMapping = new ArrayMap<>();
+ for (int i = 0; i < N; ++i) {
+ String key = in.readString();
+ final int M = in.readInt();
+ if (M == -1) {
+ keySetMapping.put(key, null);
+ continue;
+ }
+
+ ArraySet<PublicKey> keys = new ArraySet<>(M);
+ for (int j = 0; j < M; ++j) {
+ PublicKey pk = (PublicKey) in.readSerializable();
+ keys.add(pk);
+ }
+
+ keySetMapping.put(key, keys);
+ }
+
+ return keySetMapping;
+ }
+
+ public static final Parcelable.Creator CREATOR = new Parcelable.Creator<Package>() {
+ public Package createFromParcel(Parcel in) {
+ return new Package(in);
+ }
+
+ public Package[] newArray(int size) {
+ return new Package[size];
+ }
+ };
}
- public static class Component<II extends IntentInfo> {
- public final Package owner;
+ public static abstract class Component<II extends IntentInfo> {
public final ArrayList<II> intents;
public final String className;
+
public Bundle metaData;
+ public Package owner;
ComponentName componentName;
String componentShortName;
@@ -5655,6 +5986,83 @@
return componentName;
}
+ protected Component(Parcel in) {
+ className = in.readString();
+ metaData = in.readBundle();
+ intents = createIntentsList(in);
+
+ owner = null;
+ }
+
+ protected void writeToParcel(Parcel dest, int flags) {
+ dest.writeString(className);
+ dest.writeBundle(metaData);
+
+ writeIntentsList(intents, dest, flags);
+ }
+
+ /**
+ * <p>
+ * Implementation note: The serialized form for the intent list also contains the name
+ * of the concrete class that's stored in the list, and assumes that every element of the
+ * list is of the same type. This is very similar to the original parcelable mechanism.
+ * We cannot use that directly because IntentInfo extends IntentFilter, which is parcelable
+ * and is public API. It also declares Parcelable related methods as final which means
+ * we can't extend them. The approach of using composition instead of inheritance leads to
+ * a large set of cascading changes in the PackageManagerService, which seem undesirable.
+ *
+ * <p>
+ * <b>WARNING: </b> The list of objects returned by this function might need to be fixed up
+ * to make sure their owner fields are consistent. See {@code fixupOwner}.
+ */
+ private static void writeIntentsList(ArrayList<? extends IntentInfo> list, Parcel out,
+ int flags) {
+ if (list == null) {
+ out.writeInt(-1);
+ return;
+ }
+
+ final int N = list.size();
+ out.writeInt(N);
+
+ // Don't bother writing the component name if the list is empty.
+ if (N > 0) {
+ IntentInfo info = list.get(0);
+ out.writeString(info.getClass().getName());
+
+ for (int i = 0; i < N;i++) {
+ list.get(i).writeIntentInfoToParcel(out, flags);
+ }
+ }
+ }
+
+ private static <T extends IntentInfo> ArrayList<T> createIntentsList(Parcel in) {
+ int N = in.readInt();
+ if (N == -1) {
+ return null;
+ }
+
+ if (N == 0) {
+ return new ArrayList<>(0);
+ }
+
+ String componentName = in.readString();
+ final ArrayList<T> intentsList;
+ try {
+ final Class<T> cls = (Class<T>) Class.forName(componentName);
+ final Constructor<T> cons = cls.getConstructor(Parcel.class);
+
+ intentsList = new ArrayList<>(N);
+ for (int i = 0; i < N; ++i) {
+ intentsList.add(cons.newInstance(in));
+ }
+ } catch (ReflectiveOperationException ree) {
+ throw new AssertionError("Unable to construct intent list for: " + componentName);
+ }
+
+ return intentsList;
+ }
+
public void appendComponentShortName(StringBuilder sb) {
ComponentName.appendShortString(sb, owner.applicationInfo.packageName, className);
}
@@ -5669,7 +6077,7 @@
}
}
- public final static class Permission extends Component<IntentInfo> {
+ public final static class Permission extends Component<IntentInfo> implements Parcelable {
public final PermissionInfo info;
public boolean tree;
public PermissionGroup group;
@@ -5694,9 +6102,40 @@
+ Integer.toHexString(System.identityHashCode(this))
+ " " + info.name + "}";
}
+
+ @Override
+ public int describeContents() {
+ return 0;
+ }
+
+ @Override
+ public void writeToParcel(Parcel dest, int flags) {
+ super.writeToParcel(dest, flags);
+ dest.writeParcelable(info, flags);
+ dest.writeInt(tree ? 1 : 0);
+ dest.writeParcelable(group, flags);
+ }
+
+ private Permission(Parcel in) {
+ super(in);
+ final ClassLoader boot = Object.class.getClassLoader();
+ info = in.readParcelable(boot);
+ tree = (in.readInt() == 1);
+ group = in.readParcelable(boot);
+ }
+
+ public static final Parcelable.Creator CREATOR = new Parcelable.Creator<Permission>() {
+ public Permission createFromParcel(Parcel in) {
+ return new Permission(in);
+ }
+
+ public Permission[] newArray(int size) {
+ return new Permission[size];
+ }
+ };
}
- public final static class PermissionGroup extends Component<IntentInfo> {
+ public final static class PermissionGroup extends Component<IntentInfo> implements Parcelable {
public final PermissionGroupInfo info;
public PermissionGroup(Package _owner) {
@@ -5719,6 +6158,32 @@
+ Integer.toHexString(System.identityHashCode(this))
+ " " + info.name + "}";
}
+
+ @Override
+ public int describeContents() {
+ return 0;
+ }
+
+ @Override
+ public void writeToParcel(Parcel dest, int flags) {
+ super.writeToParcel(dest, flags);
+ dest.writeParcelable(info, flags);
+ }
+
+ private PermissionGroup(Parcel in) {
+ super(in);
+ info = in.readParcelable(Object.class.getClassLoader());
+ }
+
+ public static final Parcelable.Creator CREATOR = new Parcelable.Creator<PermissionGroup>() {
+ public PermissionGroup createFromParcel(Parcel in) {
+ return new PermissionGroup(in);
+ }
+
+ public PermissionGroup[] newArray(int size) {
+ return new PermissionGroup[size];
+ }
+ };
}
private static boolean copyNeeded(int flags, Package p,
@@ -5871,7 +6336,7 @@
return pgi;
}
- public final static class Activity extends Component<ActivityIntentInfo> {
+ public final static class Activity extends Component<ActivityIntentInfo> implements Parcelable {
public final ActivityInfo info;
public Activity(final ParseComponentArgs args, final ActivityInfo _info) {
@@ -5894,6 +6359,36 @@
sb.append('}');
return sb.toString();
}
+
+ @Override
+ public int describeContents() {
+ return 0;
+ }
+
+ @Override
+ public void writeToParcel(Parcel dest, int flags) {
+ super.writeToParcel(dest, flags);
+ dest.writeParcelable(info, flags | Parcelable.PARCELABLE_ELIDE_DUPLICATES);
+ }
+
+ private Activity(Parcel in) {
+ super(in);
+ info = in.readParcelable(Object.class.getClassLoader());
+
+ for (ActivityIntentInfo aii : intents) {
+ aii.activity = this;
+ }
+ }
+
+ public static final Parcelable.Creator CREATOR = new Parcelable.Creator<Activity>() {
+ public Activity createFromParcel(Parcel in) {
+ return new Activity(in);
+ }
+
+ public Activity[] newArray(int size) {
+ return new Activity[size];
+ }
+ };
}
public static final ActivityInfo generateActivityInfo(Activity a, int flags,
@@ -5925,7 +6420,7 @@
return ai;
}
- public final static class Service extends Component<ServiceIntentInfo> {
+ public final static class Service extends Component<ServiceIntentInfo> implements Parcelable {
public final ServiceInfo info;
public Service(final ParseComponentArgs args, final ServiceInfo _info) {
@@ -5948,6 +6443,36 @@
sb.append('}');
return sb.toString();
}
+
+ @Override
+ public int describeContents() {
+ return 0;
+ }
+
+ @Override
+ public void writeToParcel(Parcel dest, int flags) {
+ super.writeToParcel(dest, flags);
+ dest.writeParcelable(info, flags | Parcelable.PARCELABLE_ELIDE_DUPLICATES);
+ }
+
+ private Service(Parcel in) {
+ super(in);
+ info = in.readParcelable(Object.class.getClassLoader());
+
+ for (ServiceIntentInfo aii : intents) {
+ aii.service = this;
+ }
+ }
+
+ public static final Parcelable.Creator CREATOR = new Parcelable.Creator<Service>() {
+ public Service createFromParcel(Parcel in) {
+ return new Service(in);
+ }
+
+ public Service[] newArray(int size) {
+ return new Service[size];
+ }
+ };
}
public static final ServiceInfo generateServiceInfo(Service s, int flags,
@@ -5966,7 +6491,7 @@
return si;
}
- public final static class Provider extends Component<ProviderIntentInfo> {
+ public final static class Provider extends Component<ProviderIntentInfo> implements Parcelable {
public final ProviderInfo info;
public boolean syncable;
@@ -5997,6 +6522,38 @@
sb.append('}');
return sb.toString();
}
+
+ @Override
+ public int describeContents() {
+ return 0;
+ }
+
+ @Override
+ public void writeToParcel(Parcel dest, int flags) {
+ super.writeToParcel(dest, flags);
+ dest.writeParcelable(info, flags | Parcelable.PARCELABLE_ELIDE_DUPLICATES);
+ dest.writeInt((syncable) ? 1 : 0);
+ }
+
+ private Provider(Parcel in) {
+ super(in);
+ info = in.readParcelable(Object.class.getClassLoader());
+ syncable = (in.readInt() == 1);
+
+ for (ProviderIntentInfo aii : intents) {
+ aii.provider = this;
+ }
+ }
+
+ public static final Parcelable.Creator CREATOR = new Parcelable.Creator<Provider>() {
+ public Provider createFromParcel(Parcel in) {
+ return new Provider(in);
+ }
+
+ public Provider[] newArray(int size) {
+ return new Provider[size];
+ }
+ };
}
public static final ProviderInfo generateProviderInfo(Provider p, int flags,
@@ -6020,7 +6577,8 @@
return pi;
}
- public final static class Instrumentation extends Component<IntentInfo> {
+ public final static class Instrumentation extends Component<IntentInfo> implements
+ Parcelable {
public final InstrumentationInfo info;
public Instrumentation(final ParsePackageItemArgs args, final InstrumentationInfo _info) {
@@ -6042,6 +6600,32 @@
sb.append('}');
return sb.toString();
}
+
+ @Override
+ public int describeContents() {
+ return 0;
+ }
+
+ @Override
+ public void writeToParcel(Parcel dest, int flags) {
+ super.writeToParcel(dest, flags);
+ dest.writeParcelable(info, flags);
+ }
+
+ private Instrumentation(Parcel in) {
+ super(in);
+ info = in.readParcelable(Object.class.getClassLoader());
+ }
+
+ public static final Parcelable.Creator CREATOR = new Parcelable.Creator<Instrumentation>() {
+ public Instrumentation createFromParcel(Parcel in) {
+ return new Instrumentation(in);
+ }
+
+ public Instrumentation[] newArray(int size) {
+ return new Instrumentation[size];
+ }
+ };
}
public static final InstrumentationInfo generateInstrumentationInfo(
@@ -6055,7 +6639,7 @@
return ii;
}
- public static class IntentInfo extends IntentFilter {
+ public static abstract class IntentInfo extends IntentFilter {
public boolean hasDefault;
public int labelRes;
public CharSequence nonLocalizedLabel;
@@ -6063,10 +6647,36 @@
public int logo;
public int banner;
public int preferred;
+
+ protected IntentInfo() {
+ }
+
+ protected IntentInfo(Parcel dest) {
+ super(dest);
+ hasDefault = (dest.readInt() == 1);
+ labelRes = dest.readInt();
+ nonLocalizedLabel = dest.readCharSequence();
+ icon = dest.readInt();
+ logo = dest.readInt();
+ banner = dest.readInt();
+ preferred = dest.readInt();
+ }
+
+
+ public void writeIntentInfoToParcel(Parcel dest, int flags) {
+ super.writeToParcel(dest, flags);
+ dest.writeInt(hasDefault ? 1 : 0);
+ dest.writeInt(labelRes);
+ dest.writeCharSequence(nonLocalizedLabel);
+ dest.writeInt(icon);
+ dest.writeInt(logo);
+ dest.writeInt(banner);
+ dest.writeInt(preferred);
+ }
}
public final static class ActivityIntentInfo extends IntentInfo {
- public final Activity activity;
+ public Activity activity;
public ActivityIntentInfo(Activity _activity) {
activity = _activity;
@@ -6081,10 +6691,14 @@
sb.append('}');
return sb.toString();
}
+
+ public ActivityIntentInfo(Parcel in) {
+ super(in);
+ }
}
public final static class ServiceIntentInfo extends IntentInfo {
- public final Service service;
+ public Service service;
public ServiceIntentInfo(Service _service) {
service = _service;
@@ -6099,10 +6713,14 @@
sb.append('}');
return sb.toString();
}
+
+ public ServiceIntentInfo(Parcel in) {
+ super(in);
+ }
}
public static final class ProviderIntentInfo extends IntentInfo {
- public final Provider provider;
+ public Provider provider;
public ProviderIntentInfo(Provider provider) {
this.provider = provider;
@@ -6117,6 +6735,10 @@
sb.append('}');
return sb.toString();
}
+
+ public ProviderIntentInfo(Parcel in) {
+ super(in);
+ }
}
/**
diff --git a/core/java/android/content/pm/ShortcutInfo.java b/core/java/android/content/pm/ShortcutInfo.java
index a4d8916..b4dcdf7 100644
--- a/core/java/android/content/pm/ShortcutInfo.java
+++ b/core/java/android/content/pm/ShortcutInfo.java
@@ -1061,11 +1061,6 @@
* Launcher apps should show the launcher icon for the returned activity alongside
* this shortcut.
*
- * <p>When a shortcut is dynamic or manifest
- * (i.e. either {@link #isDynamic()} or {@link #isDeclaredInManifest()} returns {@code TRUE}),
- * then it should always have a non-null target activity.
- * Otherwise it will return null.
- *
* @see Builder#setActivity
*/
@Nullable
@@ -1372,7 +1367,7 @@
}
/**
- * Return {@code TRUE} if a shortcut is pinned but neither manifest nor dynamic.
+ * @return true if pinned but neither static nor dynamic.
* @hide
*/
public boolean isFloating() {
diff --git a/core/java/android/content/pm/ShortcutManager.java b/core/java/android/content/pm/ShortcutManager.java
index c8f00b8..c8fb3d1 100644
--- a/core/java/android/content/pm/ShortcutManager.java
+++ b/core/java/android/content/pm/ShortcutManager.java
@@ -867,7 +867,7 @@
*
* @throws IllegalArgumentException if a shortcut with the same ID exists and is disabled.
* @throws IllegalStateException The caller doesn't have a foreground activity or a foreground
- * service.
+ * service or when the user is locked.
*/
public boolean requestPinShortcut(@NonNull ShortcutInfo shortcut,
@Nullable IntentSender resultIntent) {
diff --git a/core/java/android/content/pm/ShortcutServiceInternal.java b/core/java/android/content/pm/ShortcutServiceInternal.java
index af56105..4773c73 100644
--- a/core/java/android/content/pm/ShortcutServiceInternal.java
+++ b/core/java/android/content/pm/ShortcutServiceInternal.java
@@ -19,8 +19,10 @@
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.UserIdInt;
+import android.appwidget.AppWidgetProviderInfo;
import android.content.ComponentName;
import android.content.Intent;
+import android.content.IntentSender;
import android.content.pm.LauncherApps.ShortcutQuery;
import android.os.ParcelFileDescriptor;
@@ -68,4 +70,8 @@
public abstract boolean hasShortcutHostPermission(int launcherUserId,
@NonNull String callingPackage);
+
+ public abstract boolean requestPinAppWidget(@NonNull String callingPackage,
+ @NonNull AppWidgetProviderInfo appWidget, @Nullable IntentSender resultIntent,
+ int userId);
}
diff --git a/core/java/android/content/res/TypedArray.java b/core/java/android/content/res/TypedArray.java
index ca95ce1..3912201 100644
--- a/core/java/android/content/res/TypedArray.java
+++ b/core/java/android/content/res/TypedArray.java
@@ -79,7 +79,7 @@
final int dataLen = len * AssetManager.STYLE_NUM_ENTRIES;
final int indicesLen = len + 1;
final VMRuntime runtime = VMRuntime.getRuntime();
- if (mData == null || mData.length < dataLen) {
+ if (mDataAddress == 0 || mData.length < dataLen) {
mData = (int[]) runtime.newNonMovableArray(int.class, dataLen);
mDataAddress = runtime.addressOf(mData);
mIndices = (int[]) runtime.newNonMovableArray(int.class, indicesLen);
diff --git a/core/java/android/net/INetworkScoreService.aidl b/core/java/android/net/INetworkScoreService.aidl
index 932f031..b097f12 100644
--- a/core/java/android/net/INetworkScoreService.aidl
+++ b/core/java/android/net/INetworkScoreService.aidl
@@ -100,4 +100,13 @@
* @hide
*/
boolean requestScores(in NetworkKey[] networks);
+
+ /**
+ * Determine whether the application with the given UID is the enabled scorer.
+ *
+ * @param callingUid the UID to check
+ * @return true if the provided UID is the active scorer, false otherwise.
+ * @hide
+ */
+ boolean isCallerActiveScorer(int callingUid);
}
diff --git a/core/java/android/net/LocalServerSocket.java b/core/java/android/net/LocalServerSocket.java
index 9464222..e1eaf00 100644
--- a/core/java/android/net/LocalServerSocket.java
+++ b/core/java/android/net/LocalServerSocket.java
@@ -87,9 +87,9 @@
{
LocalSocketImpl acceptedImpl = new LocalSocketImpl();
- impl.accept (acceptedImpl);
+ impl.accept(acceptedImpl);
- return new LocalSocket(acceptedImpl, LocalSocket.SOCKET_UNKNOWN);
+ return LocalSocket.createLocalSocketForAccept(acceptedImpl, LocalSocket.SOCKET_UNKNOWN);
}
/**
diff --git a/core/java/android/net/LocalSocket.java b/core/java/android/net/LocalSocket.java
index e14facb1..d9ad74b 100644
--- a/core/java/android/net/LocalSocket.java
+++ b/core/java/android/net/LocalSocket.java
@@ -73,19 +73,27 @@
this(new LocalSocketImpl(fd), SOCKET_UNKNOWN);
isBound = true;
isConnected = true;
+ implCreated = true;
}
- /**
- * for use with AndroidServerSocket
- * @param impl a SocketImpl
- */
- /*package*/ LocalSocket(LocalSocketImpl impl, int sockType) {
+ private LocalSocket(LocalSocketImpl impl, int sockType) {
this.impl = impl;
this.sockType = sockType;
this.isConnected = false;
this.isBound = false;
}
+ /**
+ * for use with LocalServerSocket.accept()
+ */
+ static LocalSocket createLocalSocketForAccept(LocalSocketImpl impl, int sockType) {
+ LocalSocket socket = new LocalSocket(impl, sockType);
+ socket.isConnected = true;
+ socket.isBound = true;
+ socket.implCreated = true;
+ return socket;
+ }
+
/** {@inheritDoc} */
@Override
public String toString() {
@@ -216,11 +224,11 @@
implCreateIfNeeded();
impl.shutdownOutput();
}
-
+
public void setReceiveBufferSize(int size) throws IOException {
impl.setOption(SocketOptions.SO_RCVBUF, Integer.valueOf(size));
}
-
+
public int getReceiveBufferSize() throws IOException {
return ((Integer) impl.getOption(SocketOptions.SO_RCVBUF)).intValue();
}
@@ -228,7 +236,7 @@
public void setSoTimeout(int n) throws IOException {
impl.setOption(SocketOptions.SO_TIMEOUT, Integer.valueOf(n));
}
-
+
public int getSoTimeout() throws IOException {
return ((Integer) impl.getOption(SocketOptions.SO_TIMEOUT)).intValue();
}
@@ -236,7 +244,7 @@
public void setSendBufferSize(int n) throws IOException {
impl.setOption(SocketOptions.SO_SNDBUF, Integer.valueOf(n));
}
-
+
public int getSendBufferSize() throws IOException {
return ((Integer) impl.getOption(SocketOptions.SO_SNDBUF)).intValue();
}
@@ -321,5 +329,5 @@
*/
public FileDescriptor getFileDescriptor() {
return impl.getFileDescriptor();
- }
+ }
}
diff --git a/core/java/android/net/LocalSocketImpl.java b/core/java/android/net/LocalSocketImpl.java
index 0f0e9c4..d8f7821 100644
--- a/core/java/android/net/LocalSocketImpl.java
+++ b/core/java/android/net/LocalSocketImpl.java
@@ -235,29 +235,29 @@
* @throws IOException
*/
public void create(int sockType) throws IOException {
- // no error if socket already created
- // need this for LocalServerSocket.accept()
- if (fd == null) {
- int osType;
- switch (sockType) {
- case LocalSocket.SOCKET_DGRAM:
- osType = OsConstants.SOCK_DGRAM;
- break;
- case LocalSocket.SOCKET_STREAM:
- osType = OsConstants.SOCK_STREAM;
- break;
- case LocalSocket.SOCKET_SEQPACKET:
- osType = OsConstants.SOCK_SEQPACKET;
- break;
- default:
- throw new IllegalStateException("unknown sockType");
- }
- try {
- fd = Os.socket(OsConstants.AF_UNIX, osType, 0);
- mFdCreatedInternally = true;
- } catch (ErrnoException e) {
- e.rethrowAsIOException();
- }
+ if (fd != null) {
+ throw new IOException("LocalSocketImpl already has an fd");
+ }
+
+ int osType;
+ switch (sockType) {
+ case LocalSocket.SOCKET_DGRAM:
+ osType = OsConstants.SOCK_DGRAM;
+ break;
+ case LocalSocket.SOCKET_STREAM:
+ osType = OsConstants.SOCK_STREAM;
+ break;
+ case LocalSocket.SOCKET_SEQPACKET:
+ osType = OsConstants.SOCK_SEQPACKET;
+ break;
+ default:
+ throw new IllegalStateException("unknown sockType");
+ }
+ try {
+ fd = Os.socket(OsConstants.AF_UNIX, osType, 0);
+ mFdCreatedInternally = true;
+ } catch (ErrnoException e) {
+ e.rethrowAsIOException();
}
}
diff --git a/core/java/android/net/NetworkScoreManager.java b/core/java/android/net/NetworkScoreManager.java
index 4e606ef..c633349 100644
--- a/core/java/android/net/NetworkScoreManager.java
+++ b/core/java/android/net/NetworkScoreManager.java
@@ -16,18 +16,15 @@
package android.net;
-import android.Manifest;
import android.annotation.IntDef;
import android.annotation.SdkConstant;
import android.annotation.SdkConstant.SdkConstantType;
import android.annotation.SystemApi;
import android.content.Context;
-import android.content.Intent;
import android.net.NetworkScorerAppManager.NetworkScorerAppData;
import android.os.RemoteException;
import android.os.ServiceManager;
import android.os.ServiceManager.ServiceNotFoundException;
-import android.os.UserHandle;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
@@ -44,19 +41,11 @@
* <p>A network scorer is any application which:
* <ul>
* <li>Declares the {@link android.Manifest.permission#SCORE_NETWORKS} permission.
- * <li>Includes a receiver for {@link #ACTION_SCORE_NETWORKS} guarded by the
- * {@link android.Manifest.permission#BROADCAST_NETWORK_PRIVILEGED} permission which scores
- * networks and (eventually) calls {@link #updateScores} with the results. If this receiver
- * specifies an android:label attribute, this label will be used when referring to the
- * application throughout system settings; otherwise, the application label will be used.
+ * <li>Include a Service for the {@link #ACTION_RECOMMEND_NETWORKS} action
+ * protected by the {@link android.Manifest.permission#BIND_NETWORK_RECOMMENDATION_SERVICE}
+ * permission.
* </ul>
*
- * <p>The system keeps track of an active scorer application; at any time, only this application
- * will receive {@link #ACTION_SCORE_NETWORKS} broadcasts and will be permitted to call
- * {@link #updateScores}. Applications may determine the current active scorer with
- * {@link #getActiveScorerPackage()} and request to change the active scorer by sending an
- * {@link #ACTION_CHANGE_ACTIVE} broadcast with another scorer.
- *
* @hide
*/
@SystemApi
@@ -263,12 +252,9 @@
/**
* Request scoring for networks.
*
- * <p>Note that this is just a helper method to assemble the broadcast, and will run in the
- * calling process.
- *
* @return true if the broadcast was sent, or false if there is no active scorer.
* @throws SecurityException if the caller does not hold the
- * {@link android.Manifest.permission#BROADCAST_NETWORK_PRIVILEGED} permission.
+ * {@link android.Manifest.permission#REQUEST_NETWORK_SCORES} permission.
* @hide
*/
public boolean requestScores(NetworkKey[] networks) throws SecurityException {
@@ -285,7 +271,7 @@
* @param networkType the type of network this cache can handle. See {@link NetworkKey#type}.
* @param scoreCache implementation of {@link INetworkScoreCache} to store the scores.
* @throws SecurityException if the caller does not hold the
- * {@link android.Manifest.permission#BROADCAST_NETWORK_PRIVILEGED} permission.
+ * {@link android.Manifest.permission#REQUEST_NETWORK_SCORES} permission.
* @throws IllegalArgumentException if a score cache is already registered for this type.
* @deprecated equivalent to registering for cache updates with CACHE_FILTER_NONE.
* @hide
@@ -302,7 +288,7 @@
* @param scoreCache implementation of {@link INetworkScoreCache} to store the scores
* @param filterType the {@link CacheUpdateFilter} to apply
* @throws SecurityException if the caller does not hold the
- * {@link android.Manifest.permission#BROADCAST_NETWORK_PRIVILEGED} permission.
+ * {@link android.Manifest.permission#REQUEST_NETWORK_SCORES} permission.
* @throws IllegalArgumentException if a score cache is already registered for this type.
* @hide
*/
@@ -321,7 +307,7 @@
* @param networkType the type of network this cache can handle. See {@link NetworkKey#type}.
* @param scoreCache implementation of {@link INetworkScoreCache} to store the scores.
* @throws SecurityException if the caller does not hold the
- * {@link android.Manifest.permission#BROADCAST_NETWORK_PRIVILEGED} permission.
+ * {@link android.Manifest.permission#REQUEST_NETWORK_SCORES} permission.
* @throws IllegalArgumentException if a score cache is already registered for this type.
* @hide
*/
@@ -342,7 +328,8 @@
* request details
* @return a {@link RecommendationResult} instance containing the recommended network
* to connect to
- * @throws SecurityException
+ * @throws SecurityException if the caller does not hold the
+ * {@link android.Manifest.permission#REQUEST_NETWORK_SCORES} permission.
*/
public RecommendationResult requestRecommendation(RecommendationRequest request)
throws SecurityException {
@@ -352,4 +339,19 @@
throw e.rethrowFromSystemServer();
}
}
+
+ /**
+ * Determine whether the application with the given UID is the enabled scorer.
+ *
+ * @param callingUid the UID to check
+ * @return true if the provided UID is the active scorer, false otherwise.
+ * @hide
+ */
+ public boolean isCallerActiveScorer(int callingUid) {
+ try {
+ return mService.isCallerActiveScorer(callingUid);
+ } catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
+ }
+ }
}
diff --git a/core/java/android/net/NetworkScorerAppManager.java b/core/java/android/net/NetworkScorerAppManager.java
index 4282ca7..23d5af5 100644
--- a/core/java/android/net/NetworkScorerAppManager.java
+++ b/core/java/android/net/NetworkScorerAppManager.java
@@ -16,7 +16,6 @@
package android.net;
-import android.Manifest;
import android.Manifest.permission;
import android.annotation.Nullable;
import android.content.ContentResolver;
@@ -28,7 +27,9 @@
import android.provider.Settings;
import android.text.TextUtils;
import android.util.Log;
+
import com.android.internal.R;
+
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
@@ -226,18 +227,13 @@
}
/** Determine whether the application with the given UID is the enabled scorer. */
+ @Deprecated // Use NetworkScoreManager.isCallerActiveScorer()
public boolean isCallerActiveScorer(int callingUid) {
NetworkScorerAppData defaultApp = getActiveScorer();
if (defaultApp == null) {
return false;
}
- if (callingUid != defaultApp.packageUid) {
- return false;
- }
- // To be extra safe, ensure the caller holds the SCORE_NETWORKS permission. It always
- // should, since it couldn't become the active scorer otherwise, but this can't hurt.
- return mContext.checkCallingPermission(Manifest.permission.SCORE_NETWORKS) ==
- PackageManager.PERMISSION_GRANTED;
+ return callingUid == defaultApp.packageUid;
}
private boolean isNetworkRecommendationsDisabled() {
diff --git a/core/java/android/net/RecommendationRequest.java b/core/java/android/net/RecommendationRequest.java
index a96f90d..d013f64 100644
--- a/core/java/android/net/RecommendationRequest.java
+++ b/core/java/android/net/RecommendationRequest.java
@@ -41,6 +41,7 @@
* Builder class for constructing {@link RecommendationRequest} instances.
* @hide
*/
+ @SystemApi
public static final class Builder {
private ScanResult[] mScanResults;
private WifiConfiguration mCurrentConfig;
diff --git a/core/java/android/net/ScoredNetwork.java b/core/java/android/net/ScoredNetwork.java
index 94e5187..7e3dd77 100644
--- a/core/java/android/net/ScoredNetwork.java
+++ b/core/java/android/net/ScoredNetwork.java
@@ -16,6 +16,7 @@
package android.net;
+import android.annotation.IntDef;
import android.annotation.Nullable;
import android.annotation.SystemApi;
import android.os.Bundle;
@@ -24,6 +25,8 @@
import java.lang.Math;
import java.lang.UnsupportedOperationException;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
import java.util.Objects;
/**
@@ -33,6 +36,15 @@
*/
@SystemApi
public class ScoredNetwork implements Parcelable {
+
+ /**
+ * Key used with the {@link #attributes} bundle to define the badging curve.
+ *
+ * <p>The badging curve is a {@link RssiCurve} used to map different RSSI values to {@link
+ * Badging} enums.
+ */
+ public static final String ATTRIBUTES_KEY_BADGING_CURVE =
+ "android.net.attributes.key.BADGING_CURVE";
/**
* Extra used with {@link #attributes} to specify whether the
* network is believed to have a captive portal.
@@ -58,6 +70,15 @@
public static final String ATTRIBUTES_KEY_RANKING_SCORE_OFFSET =
"android.net.attributes.key.RANKING_SCORE_OFFSET";
+ @IntDef({BADGING_NONE, BADGING_SD, BADGING_HD, BADGING_4K})
+ @Retention(RetentionPolicy.SOURCE)
+ public @interface Badging {}
+
+ public static final int BADGING_NONE = 0;
+ public static final int BADGING_SD = 10;
+ public static final int BADGING_HD = 20;
+ public static final int BADGING_4K = 30;
+
/** A {@link NetworkKey} uniquely identifying this network. */
public final NetworkKey networkKey;
@@ -249,6 +270,25 @@
}
}
+ /**
+ * Return the {@link Badging} enum for this network for the given RSSI, derived from the
+ * badging curve.
+ *
+ * <p>If no badging curve is present, {@link #BADGE_NONE} will be returned.
+ *
+ * @param rssi The rssi level for which the badge should be calculated
+ */
+ @Badging
+ public int calculateBadge(int rssi) {
+ if (attributes != null && attributes.containsKey(ATTRIBUTES_KEY_BADGING_CURVE)) {
+ RssiCurve badgingCurve =
+ attributes.getParcelable(ATTRIBUTES_KEY_BADGING_CURVE);
+ return badgingCurve.lookupScore(rssi);
+ }
+
+ return BADGING_NONE;
+ }
+
public static final Parcelable.Creator<ScoredNetwork> CREATOR =
new Parcelable.Creator<ScoredNetwork>() {
@Override
diff --git a/core/java/android/os/BaseBundle.java b/core/java/android/os/BaseBundle.java
index e771aa4..14760ab 100644
--- a/core/java/android/os/BaseBundle.java
+++ b/core/java/android/os/BaseBundle.java
@@ -213,7 +213,7 @@
* If the underlying data are stored as a Parcel, unparcel them
* using the currently assigned class loader.
*/
- /* package */ synchronized void unparcel() {
+ /* package */ void unparcel() {
synchronized (this) {
final Parcel parcelledData = mParcelledData;
if (parcelledData == null) {
@@ -319,34 +319,37 @@
}
void copyInternal(BaseBundle from, boolean deep) {
- if (from.mParcelledData != null) {
- if (from.isEmptyParcel()) {
- mParcelledData = NoImagePreloadHolder.EMPTY_PARCEL;
- } else {
- mParcelledData = Parcel.obtain();
- mParcelledData.appendFrom(from.mParcelledData, 0, from.mParcelledData.dataSize());
- mParcelledData.setDataPosition(0);
- }
- } else {
- mParcelledData = null;
- }
-
- if (from.mMap != null) {
- if (!deep) {
- mMap = new ArrayMap<>(from.mMap);
- } else {
- final ArrayMap<String, Object> fromMap = from.mMap;
- final int N = fromMap.size();
- mMap = new ArrayMap<>(N);
- for (int i=0; i<N; i++) {
- mMap.append(fromMap.keyAt(i), deepcopyValue(fromMap.valueAt(i)));
+ synchronized (from) {
+ if (from.mParcelledData != null) {
+ if (from.isEmptyParcel()) {
+ mParcelledData = NoImagePreloadHolder.EMPTY_PARCEL;
+ } else {
+ mParcelledData = Parcel.obtain();
+ mParcelledData.appendFrom(from.mParcelledData, 0,
+ from.mParcelledData.dataSize());
+ mParcelledData.setDataPosition(0);
}
+ } else {
+ mParcelledData = null;
}
- } else {
- mMap = null;
- }
- mClassLoader = from.mClassLoader;
+ if (from.mMap != null) {
+ if (!deep) {
+ mMap = new ArrayMap<>(from.mMap);
+ } else {
+ final ArrayMap<String, Object> fromMap = from.mMap;
+ final int N = fromMap.size();
+ mMap = new ArrayMap<>(N);
+ for (int i = 0; i < N; i++) {
+ mMap.append(fromMap.keyAt(i), deepcopyValue(fromMap.valueAt(i)));
+ }
+ }
+ } else {
+ mMap = null;
+ }
+
+ mClassLoader = from.mClassLoader;
+ }
}
Object deepcopyValue(Object value) {
@@ -1441,39 +1444,42 @@
void writeToParcelInner(Parcel parcel, int flags) {
// Keep implementation in sync with writeToParcel() in
// frameworks/native/libs/binder/PersistableBundle.cpp.
- final Parcel parcelledData;
+ final ArrayMap<String, Object> map;
synchronized (this) {
- parcelledData = mParcelledData;
- }
- if (parcelledData != null) {
- if (isEmptyParcel()) {
- parcel.writeInt(0);
- } else {
- int length = parcelledData.dataSize();
- parcel.writeInt(length);
- parcel.writeInt(BUNDLE_MAGIC);
- parcel.appendFrom(parcelledData, 0, length);
- }
- } else {
- // Special case for empty bundles.
- if (mMap == null || mMap.size() <= 0) {
- parcel.writeInt(0);
+ // unparcel() can race with this method and cause the parcel to recycle
+ // at the wrong time. So synchronize access the mParcelledData's content.
+ if (mParcelledData != null) {
+ if (mParcelledData == NoImagePreloadHolder.EMPTY_PARCEL) {
+ parcel.writeInt(0);
+ } else {
+ int length = mParcelledData.dataSize();
+ parcel.writeInt(length);
+ parcel.writeInt(BUNDLE_MAGIC);
+ parcel.appendFrom(mParcelledData, 0, length);
+ }
return;
}
- int lengthPos = parcel.dataPosition();
- parcel.writeInt(-1); // dummy, will hold length
- parcel.writeInt(BUNDLE_MAGIC);
-
- int startPos = parcel.dataPosition();
- parcel.writeArrayMapInternal(mMap);
- int endPos = parcel.dataPosition();
-
- // Backpatch length
- parcel.setDataPosition(lengthPos);
- int length = endPos - startPos;
- parcel.writeInt(length);
- parcel.setDataPosition(endPos);
+ map = mMap;
}
+
+ // Special case for empty bundles.
+ if (map == null || map.size() <= 0) {
+ parcel.writeInt(0);
+ return;
+ }
+ int lengthPos = parcel.dataPosition();
+ parcel.writeInt(-1); // dummy, will hold length
+ parcel.writeInt(BUNDLE_MAGIC);
+
+ int startPos = parcel.dataPosition();
+ parcel.writeArrayMapInternal(map);
+ int endPos = parcel.dataPosition();
+
+ // Backpatch length
+ parcel.setDataPosition(lengthPos);
+ int length = endPos - startPos;
+ parcel.writeInt(length);
+ parcel.setDataPosition(endPos);
}
/**
diff --git a/core/java/android/os/BatteryProperties.java b/core/java/android/os/BatteryProperties.java
index b509d76..af328d0 100644
--- a/core/java/android/os/BatteryProperties.java
+++ b/core/java/android/os/BatteryProperties.java
@@ -30,6 +30,7 @@
public int batteryLevel;
public int batteryVoltage;
public int batteryTemperature;
+ public int batteryFullCharge;
public int batteryChargeCounter;
public String batteryTechnology;
@@ -48,6 +49,7 @@
batteryLevel = other.batteryLevel;
batteryVoltage = other.batteryVoltage;
batteryTemperature = other.batteryTemperature;
+ batteryFullCharge = other.batteryFullCharge;
batteryChargeCounter = other.batteryChargeCounter;
batteryTechnology = other.batteryTechnology;
}
@@ -69,6 +71,7 @@
batteryLevel = p.readInt();
batteryVoltage = p.readInt();
batteryTemperature = p.readInt();
+ batteryFullCharge = p.readInt();
batteryChargeCounter = p.readInt();
batteryTechnology = p.readString();
}
@@ -85,6 +88,7 @@
p.writeInt(batteryLevel);
p.writeInt(batteryVoltage);
p.writeInt(batteryTemperature);
+ p.writeInt(batteryFullCharge);
p.writeInt(batteryChargeCounter);
p.writeString(batteryTechnology);
}
diff --git a/core/java/android/os/BatteryStats.java b/core/java/android/os/BatteryStats.java
index e5aeb4b..013972d 100644
--- a/core/java/android/os/BatteryStats.java
+++ b/core/java/android/os/BatteryStats.java
@@ -24,6 +24,7 @@
import java.util.HashMap;
import java.util.List;
import java.util.Map;
+import java.util.function.Predicate;
import android.content.Context;
import android.content.pm.ApplicationInfo;
@@ -39,6 +40,7 @@
import android.util.SparseIntArray;
import android.util.TimeUtils;
import android.view.Display;
+
import com.android.internal.os.BatterySipper;
import com.android.internal.os.BatteryStatsHelper;
@@ -181,6 +183,8 @@
*
* New in version 19:
* - Wakelock data (wl) gets current and max times.
+ * New in version 20:
+ * - Sensor gets a background counter.
*/
static final String CHECKIN_VERSION = "20";
@@ -600,10 +604,13 @@
*/
// Magic sensor number for the GPS.
public static final int GPS = -10000;
-
+
public abstract int getHandle();
-
+
public abstract Timer getSensorTime();
+
+ /** Returns a counter for usage count when in the background. */
+ public abstract Counter getSensorBgCount();
}
public class Pid {
@@ -1336,9 +1343,11 @@
public static final int EVENT_WAKEUP_AP = 0x0013;
// Event for reporting that a specific partial wake lock has been held for a long duration.
public static final int EVENT_LONG_WAKE_LOCK = 0x0014;
+ // Event reporting the new estimated (learned) capacity of the battery in mAh.
+ public static final int EVENT_ESTIMATED_BATTERY_CAP = 0x0015;
// Number of event types.
- public static final int EVENT_COUNT = 0x0015;
+ public static final int EVENT_COUNT = 0x0016;
// Mask to extract out only the type part of the event.
public static final int EVENT_TYPE_MASK = ~(EVENT_FLAG_START|EVENT_FLAG_FINISH);
@@ -2034,13 +2043,28 @@
public static final String[] HISTORY_EVENT_NAMES = new String[] {
"null", "proc", "fg", "top", "sync", "wake_lock_in", "job", "user", "userfg", "conn",
"active", "pkginst", "pkgunin", "alarm", "stats", "inactive", "active", "tmpwhitelist",
- "screenwake", "wakeupap", "longwake"
+ "screenwake", "wakeupap", "longwake", "est_capacity"
};
public static final String[] HISTORY_EVENT_CHECKIN_NAMES = new String[] {
"Enl", "Epr", "Efg", "Etp", "Esy", "Ewl", "Ejb", "Eur", "Euf", "Ecn",
"Eac", "Epi", "Epu", "Eal", "Est", "Eai", "Eaa", "Etw",
- "Esw", "Ewa", "Elw"
+ "Esw", "Ewa", "Elw", "Eec"
+ };
+
+ @FunctionalInterface
+ public interface IntToString {
+ String applyAsString(int val);
+ }
+
+ private static final IntToString sUidToString = UserHandle::formatUid;
+ private static final IntToString sIntToString = Integer::toString;
+
+ public static final IntToString[] HISTORY_EVENT_INT_FORMATTERS = new IntToString[] {
+ sUidToString, sUidToString, sUidToString, sUidToString, sUidToString, sUidToString,
+ sUidToString, sUidToString, sUidToString, sUidToString, sUidToString, sUidToString,
+ sUidToString, sUidToString, sUidToString, sUidToString, sUidToString, sUidToString,
+ sUidToString, sUidToString, sUidToString, sIntToString
};
/**
@@ -3318,13 +3342,16 @@
final Uid.Sensor se = sensors.valueAt(ise);
final int sensorNumber = sensors.keyAt(ise);
final Timer timer = se.getSensorTime();
+ final Counter bgCounter = se.getSensorBgCount();
if (timer != null) {
// Convert from microseconds to milliseconds with rounding
final long totalTime = (timer.getTotalTimeLocked(rawRealtime, which) + 500)
/ 1000;
final int count = timer.getCountLocked(which);
+ final int bgCount = bgCounter != null ? bgCounter.getCountLocked(which) : 0;
if (totalTime != 0) {
- dumpLine(pw, uid, category, SENSOR_DATA, sensorNumber, totalTime, count);
+ dumpLine(pw, uid, category, SENSOR_DATA, sensorNumber, totalTime, count,
+ bgCount);
}
}
}
@@ -4493,17 +4520,25 @@
sb.append(": ");
final Timer timer = se.getSensorTime();
+ final Counter bgCounter = se.getSensorBgCount();
if (timer != null) {
// Convert from microseconds to milliseconds with rounding
final long totalTime = (timer.getTotalTimeLocked(
rawRealtime, which) + 500) / 1000;
final int count = timer.getCountLocked(which);
+ final int bgCount = bgCounter != null ? bgCounter.getCountLocked(which) : 0;
//timer.logState();
if (totalTime != 0) {
formatTimeMs(sb, totalTime);
sb.append("realtime (");
sb.append(count);
- sb.append(" times)");
+ sb.append(" times");
+ if (bgCount > 0) {
+ sb.append(", ");
+ sb.append(bgCount);
+ sb.append(" bg");
+ }
+ sb.append(")");
} else {
sb.append("(not used)");
}
@@ -4958,7 +4993,8 @@
if (checkin) {
pw.print(rec.eventTag.poolIdx);
} else {
- UserHandle.formatUid(pw, rec.eventTag.uid);
+ pw.append(HISTORY_EVENT_INT_FORMATTERS[idx]
+ .applyAsString(rec.eventTag.uid));
pw.print(":\"");
pw.print(rec.eventTag.string);
pw.print("\"");
diff --git a/core/java/android/os/Build.java b/core/java/android/os/Build.java
index 0d6d369..daf8b2d 100644
--- a/core/java/android/os/Build.java
+++ b/core/java/android/os/Build.java
@@ -818,7 +818,7 @@
*/
public static boolean isBuildConsistent() {
// Don't care on eng builds. Incremental build may trigger false negative.
- if ("eng".equals(TYPE)) return true;
+ if (IS_ENG) return true;
final String system = SystemProperties.get("ro.build.fingerprint");
final String vendor = SystemProperties.get("ro.vendor.build.fingerprint");
@@ -882,6 +882,10 @@
public static final boolean IS_DEBUGGABLE =
SystemProperties.getInt("ro.debuggable", 0) == 1;
+ /** {@hide} */
+ public static final boolean IS_ENG =
+ "eng".equals(getString("ro.build.type"));
+
/**
* Specifies whether the permissions needed by a legacy app should be
* reviewed before any of its components can run. A legacy app is one
diff --git a/core/java/android/os/FileUtils.java b/core/java/android/os/FileUtils.java
index 760df45..73c9462 100644
--- a/core/java/android/os/FileUtils.java
+++ b/core/java/android/os/FileUtils.java
@@ -762,4 +762,19 @@
public static @Nullable File newFileOrNull(@Nullable String path) {
return (path != null) ? new File(path) : null;
}
+
+ /**
+ * Creates a directory with name {@code name} under an existing directory {@code baseDir}.
+ * Returns a {@code File} object representing the directory on success, {@code null} on
+ * failure.
+ */
+ public static @Nullable File createDir(File baseDir, String name) {
+ final File dir = new File(baseDir, name);
+
+ if (dir.exists()) {
+ return dir.isDirectory() ? dir : null;
+ }
+
+ return dir.mkdir() ? dir : null;
+ }
}
diff --git a/core/java/android/os/HwBinder.java b/core/java/android/os/HwBinder.java
index 481b2dc..e025494 100644
--- a/core/java/android/os/HwBinder.java
+++ b/core/java/android/os/HwBinder.java
@@ -17,6 +17,7 @@
package android.os;
import java.util.ArrayList;
+import java.util.NoSuchElementException;
import libcore.util.NativeAllocationRegistry;
/** @hide */
@@ -33,19 +34,24 @@
mNativeContext);
}
+ @Override
public final native void transact(
- int code, HwParcel request, HwParcel reply, int flags);
+ int code, HwParcel request, HwParcel reply, int flags)
+ throws RemoteException;
public abstract void onTransact(
- int code, HwParcel request, HwParcel reply, int flags);
+ int code, HwParcel request, HwParcel reply, int flags)
+ throws RemoteException;
public native final void registerService(
ArrayList<String> interfaceChain,
- String serviceName);
+ String serviceName)
+ throws RemoteException;
public static native final IHwBinder getService(
String iface,
- String serviceName);
+ String serviceName)
+ throws RemoteException, NoSuchElementException;
// Returns address of the "freeFunction".
private static native final long native_init();
diff --git a/core/java/android/os/HwRemoteBinder.java b/core/java/android/os/HwRemoteBinder.java
index e617e0a..2f89ce6 100644
--- a/core/java/android/os/HwRemoteBinder.java
+++ b/core/java/android/os/HwRemoteBinder.java
@@ -32,12 +32,15 @@
mNativeContext);
}
+ @Override
public IHwInterface queryLocalInterface(String descriptor) {
return null;
}
+ @Override
public native final void transact(
- int code, HwParcel request, HwParcel reply, int flags);
+ int code, HwParcel request, HwParcel reply, int flags)
+ throws RemoteException;
public native boolean linkToDeath(DeathRecipient recipient, long cookie);
public native boolean unlinkToDeath(DeathRecipient recipient);
diff --git a/core/java/android/os/IHwBinder.java b/core/java/android/os/IHwBinder.java
index f93bfd7..619f4dc 100644
--- a/core/java/android/os/IHwBinder.java
+++ b/core/java/android/os/IHwBinder.java
@@ -23,7 +23,8 @@
public static final int FLAG_ONEWAY = 1;
public void transact(
- int code, HwParcel request, HwParcel reply, int flags);
+ int code, HwParcel request, HwParcel reply, int flags)
+ throws RemoteException;
public IHwInterface queryLocalInterface(String descriptor);
@@ -36,6 +37,5 @@
}
public boolean linkToDeath(DeathRecipient recipient, long cookie);
-
public boolean unlinkToDeath(DeathRecipient recipient);
}
diff --git a/core/java/android/os/IUserManager.aidl b/core/java/android/os/IUserManager.aidl
index d443b66..9513854 100644
--- a/core/java/android/os/IUserManager.aidl
+++ b/core/java/android/os/IUserManager.aidl
@@ -40,6 +40,7 @@
in String[] disallowedPackages);
UserInfo createRestrictedProfile(String name, int parentUserHandle);
void setUserEnabled(int userHandle);
+ void evictCredentialEncryptionKey(int userHandle);
boolean removeUser(int userHandle);
void setUserName(int userHandle, String name);
void setUserIcon(int userHandle, in Bitmap icon);
diff --git a/core/java/android/os/Process.java b/core/java/android/os/Process.java
index 9cd1a42..d6688e3 100644
--- a/core/java/android/os/Process.java
+++ b/core/java/android/os/Process.java
@@ -184,6 +184,11 @@
*/
public static final int LAST_SHARED_APPLICATION_GID = 59999;
+ /** {@hide} */
+ public static final int FIRST_APPLICATION_CACHE_GID = 20000;
+ /** {@hide} */
+ public static final int LAST_APPLICATION_CACHE_GID = 29999;
+
/**
* Standard priority of application threads.
* Use with {@link #setThreadPriority(int)} and
diff --git a/core/java/android/os/UserHandle.java b/core/java/android/os/UserHandle.java
index b04d149..4aec8ae 100644
--- a/core/java/android/os/UserHandle.java
+++ b/core/java/android/os/UserHandle.java
@@ -215,6 +215,15 @@
}
/**
+ * Returns the cache GID for a given UID or appId.
+ * @hide
+ */
+ public static int getCacheAppGid(int id) {
+ return Process.FIRST_APPLICATION_CACHE_GID + (id % PER_USER_RANGE)
+ - Process.FIRST_APPLICATION_UID;
+ }
+
+ /**
* Generate a text representation of the uid, breaking out its individual
* components -- user, app, isolated, etc.
* @hide
diff --git a/core/java/android/os/UserManager.java b/core/java/android/os/UserManager.java
index 0a32f0d..3478eaa 100644
--- a/core/java/android/os/UserManager.java
+++ b/core/java/android/os/UserManager.java
@@ -256,7 +256,7 @@
* Specifies if managed profiles of this user can be removed, other than by its profile owner.
* The default value is <code>false</code>.
* <p>
- * This restriction can only be set by device owners.
+ * This restriction has no effect on managed profiles.
*
* <p>Key for user restrictions.
* <p>Type: Boolean
@@ -353,8 +353,8 @@
/**
* Specifies if a user is disallowed from adding managed profiles.
* <p>The default value for an unmanaged user is <code>false</code>.
- * For users with a device owner set, the default is <code>true</code>
- * <p>This restriction can only be set by device owners.
+ * For users with a device owner set, the default is <code>true</code>.
+ * <p>This restriction has no effect on managed profiles.
*
* <p>Key for user restrictions.
* <p>Type: Boolean
@@ -1641,6 +1641,19 @@
}
/**
+ * Evicts the user's credential encryption key from memory by stopping and restarting the user.
+ *
+ * @hide
+ */
+ public void evictCredentialEncryptionKey(@UserIdInt int userHandle) {
+ try {
+ mService.evictCredentialEncryptionKey(userHandle);
+ } catch (RemoteException re) {
+ throw re.rethrowFromSystemServer();
+ }
+ }
+
+ /**
* Return the number of users currently created on the device.
*/
public int getUserCount() {
diff --git a/core/java/android/os/storage/StorageManager.java b/core/java/android/os/storage/StorageManager.java
index 3fc7dba..03fd8d3 100644
--- a/core/java/android/os/storage/StorageManager.java
+++ b/core/java/android/os/storage/StorageManager.java
@@ -52,6 +52,7 @@
import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
+import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStreamReader;
import java.lang.ref.WeakReference;
@@ -974,10 +975,17 @@
try (final FileInputStream fis = new FileInputStream(path);
final BufferedReader reader = new BufferedReader(new InputStreamReader(fis));) {
return Long.parseLong(reader.readLine());
- } catch (Exception e) {
- Slog.w(TAG, "readLong(): could not read " + path + ": " + e);
+ } catch (FileNotFoundException e) {
+ // This is expected since we are trying to parse multiple paths.
+ Slog.i(TAG, "readLong(): Path doesn't exist: " + path + ": " + e);
return 0;
- }
+ } catch (NumberFormatException e) {
+ Slog.e(TAG, "readLong(): Could not parse " + path + ": " + e);
+ return 0;
+ } catch (Exception e) {
+ Slog.e(TAG, "readLong(): Unknown exception while opening " + path + ": " + e);
+ return 0;
+ }
}
/** @removed */
diff --git a/core/java/android/provider/AlarmClock.java b/core/java/android/provider/AlarmClock.java
index 63ae9a9..23134cd 100644
--- a/core/java/android/provider/AlarmClock.java
+++ b/core/java/android/provider/AlarmClock.java
@@ -153,6 +153,15 @@
public static final String ACTION_SET_TIMER = "android.intent.action.SET_TIMER";
/**
+ * Activity Action: Show the timers.
+ * <p>
+ * This action opens the timers page.
+ * </p>
+ */
+ @SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION)
+ public static final String ACTION_SHOW_TIMERS = "android.intent.action.SHOW_TIMERS";
+
+ /**
* Activity Action: Show the alarms.
* <p>
* This action opens the alarms page.
diff --git a/core/java/android/provider/DocumentsContract.java b/core/java/android/provider/DocumentsContract.java
index 5a69409..ded715f 100644
--- a/core/java/android/provider/DocumentsContract.java
+++ b/core/java/android/provider/DocumentsContract.java
@@ -393,6 +393,9 @@
* Flag indicating that a document is virtual, and doesn't have byte
* representation in the MIME type specified as {@link #COLUMN_MIME_TYPE}.
*
+ * <p><em>Virtual documents must have at least one alternative streamable
+ * format via {@link DocumentsProvider#openTypedDocument}</em>
+ *
* @see #COLUMN_FLAGS
* @see #COLUMN_MIME_TYPE
* @see DocumentsProvider#openTypedDocument(String, String, Bundle,
diff --git a/core/java/android/provider/DocumentsProvider.java b/core/java/android/provider/DocumentsProvider.java
index 96c2556..584f5fe 100644
--- a/core/java/android/provider/DocumentsProvider.java
+++ b/core/java/android/provider/DocumentsProvider.java
@@ -575,6 +575,8 @@
* <p>
* A provider may perform a conversion if the documents's MIME type is not
* matching the specified MIME type filter.
+ * <p>
+ * Virtual documents must have at least one streamable format.
*
* @param documentId the document to return.
* @param mimeTypeFilter the MIME type filter for the requested format. May
@@ -1044,6 +1046,8 @@
* {@link #queryDocument(String, String[])} as long as it matches the filter and the document
* does not have the {@link Document#FLAG_VIRTUAL_DOCUMENT} flag set.
*
+ * <p>Virtual documents must have at least one streamable format.
+ *
* @see #getStreamTypes(Uri, String)
* @see #openTypedDocument(String, String, Bundle, CancellationSignal)
*/
diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java
index 43590c7..cede9eb 100755
--- a/core/java/android/provider/Settings.java
+++ b/core/java/android/provider/Settings.java
@@ -6394,13 +6394,6 @@
public static final String ENABLED_NOTIFICATION_POLICY_ACCESS_PACKAGES =
"enabled_notification_policy_access_packages";
- /** @hide */
- public static final String BAR_SERVICE_COMPONENT = "bar_service_component";
-
- /** @hide */
- public static final String VOLUME_CONTROLLER_SERVICE_COMPONENT
- = "volume_controller_service_component";
-
/**
* Defines whether managed profile ringtones should be synced from it's parent profile
* <p>
@@ -6809,7 +6802,8 @@
QS_TILES,
DOZE_ENABLED,
DOZE_PULSE_ON_PICK_UP,
- DOZE_PULSE_ON_DOUBLE_TAP
+ DOZE_PULSE_ON_DOUBLE_TAP,
+ NFC_PAYMENT_DEFAULT_COMPONENT
};
/**
diff --git a/core/java/android/service/notification/NotificationAssistantService.java b/core/java/android/service/notification/NotificationAssistantService.java
index 51ba8c72..cab390f 100644
--- a/core/java/android/service/notification/NotificationAssistantService.java
+++ b/core/java/android/service/notification/NotificationAssistantService.java
@@ -210,7 +210,14 @@
args.recycle();
Adjustment adjustment = onNotificationEnqueued(sbn, importance, user);
if (adjustment != null) {
- adjustNotification(adjustment);
+ if (!isBound()) return;
+ try {
+ getNotificationInterface().applyEnqueuedAdjustmentFromAssistant(
+ mWrapper, adjustment);
+ } catch (android.os.RemoteException ex) {
+ Log.v(TAG, "Unable to contact notification manager", ex);
+ throw ex.rethrowFromSystemServer();
+ }
}
} break;
}
diff --git a/core/java/android/transition/ArcMotion.java b/core/java/android/transition/ArcMotion.java
index 70443ba..da14834 100644
--- a/core/java/android/transition/ArcMotion.java
+++ b/core/java/android/transition/ArcMotion.java
@@ -199,83 +199,77 @@
float ex;
float ey;
- if (startY == endY) {
- ex = (startX + endX) / 2;
- ey = startY + mMinimumHorizontalTangent * Math.abs(endX - startX) / 2;
- } else if (startX == endX) {
- ex = startX + mMinimumVerticalTangent * Math.abs(endY - startY) / 2;
- ey = (startY + endY) / 2;
- } else {
- float deltaX = endX - startX;
- float deltaY = endY - startY;
- // hypotenuse squared.
- float h2 = deltaX * deltaX + deltaY * deltaY;
+ float deltaX = endX - startX;
+ float deltaY = endY - startY;
- // Midpoint between start and end
- float dx = (startX + endX) / 2;
- float dy = (startY + endY) / 2;
+ // hypotenuse squared.
+ float h2 = deltaX * deltaX + deltaY * deltaY;
- // Distance squared between end point and mid point is (1/2 hypotenuse)^2
- float midDist2 = h2 * 0.25f;
+ // Midpoint between start and end
+ float dx = (startX + endX) / 2;
+ float dy = (startY + endY) / 2;
- float minimumArcDist2 = 0;
- boolean isQuadrant1Or3 = (deltaX * deltaY) > 0;
+ // Distance squared between end point and mid point is (1/2 hypotenuse)^2
+ float midDist2 = h2 * 0.25f;
- if ((Math.abs(deltaX) < Math.abs(deltaY))) {
- // Similar triangles bfa and bde mean that (ab/fb = eb/bd)
- // Therefore, eb = ab * bd / fb
- // ab = hypotenuse
- // bd = hypotenuse/2
- // fb = deltaY
- float eDistY = h2 / (2 * deltaY);
- if (isQuadrant1Or3) {
- ey = startY + eDistY;
- ex = startX;
- } else {
- ey = endY - eDistY;
- ex = endX;
- }
+ float minimumArcDist2 = 0;
- minimumArcDist2 = midDist2 * mMinimumVerticalTangent
- * mMinimumVerticalTangent;
+ boolean isMovingUpwards = startY > endY;
+
+ if ((Math.abs(deltaX) < Math.abs(deltaY))) {
+ // Similar triangles bfa and bde mean that (ab/fb = eb/bd)
+ // Therefore, eb = ab * bd / fb
+ // ab = hypotenuse
+ // bd = hypotenuse/2
+ // fb = deltaY
+ float eDistY = Math.abs(h2 / (2 * deltaY));
+ if (isMovingUpwards) {
+ ey = endY + eDistY;
+ ex = endX;
} else {
- // Same as above, but flip X & Y
- float eDistX = h2 / (2 * deltaX);
- if (isQuadrant1Or3) {
- ex = endX - eDistX;
- ey = endY;
- } else {
- ex = startX + eDistX;
- ey = startY;
- }
-
- minimumArcDist2 = midDist2 * mMinimumHorizontalTangent
- * mMinimumHorizontalTangent;
+ ey = startY + eDistY;
+ ex = startX;
}
- float arcDistX = dx - ex;
- float arcDistY = dy - ey;
- float arcDist2 = arcDistX * arcDistX + arcDistY * arcDistY;
- float maximumArcDist2 = midDist2 * mMaximumTangent * mMaximumTangent;
+ minimumArcDist2 = midDist2 * mMinimumVerticalTangent
+ * mMinimumVerticalTangent;
+ } else {
+ // Same as above, but flip X & Y and account for negative eDist
+ float eDistX = h2 / (2 * deltaX);
+ if (isMovingUpwards) {
+ ex = startX + eDistX;
+ ey = startY;
+ } else {
+ ex = endX - eDistX;
+ ey = endY;
+ }
- float newArcDistance2 = 0;
- if (arcDist2 < minimumArcDist2) {
- newArcDistance2 = minimumArcDist2;
- } else if (arcDist2 > maximumArcDist2) {
- newArcDistance2 = maximumArcDist2;
- }
- if (newArcDistance2 != 0) {
- float ratio2 = newArcDistance2 / arcDist2;
- float ratio = (float) Math.sqrt(ratio2);
- ex = dx + (ratio * (ex - dx));
- ey = dy + (ratio * (ey - dy));
- }
+ minimumArcDist2 = midDist2 * mMinimumHorizontalTangent
+ * mMinimumHorizontalTangent;
}
- float controlX1 = (startX + ex) / 2;
- float controlY1 = (startY + ey) / 2;
- float controlX2 = (ex + endX) / 2;
- float controlY2 = (ey + endY) / 2;
- path.cubicTo(controlX1, controlY1, controlX2, controlY2, endX, endY);
+ float arcDistX = dx - ex;
+ float arcDistY = dy - ey;
+ float arcDist2 = arcDistX * arcDistX + arcDistY * arcDistY;
+
+ float maximumArcDist2 = midDist2 * mMaximumTangent * mMaximumTangent;
+
+ float newArcDistance2 = 0;
+ if (arcDist2 < minimumArcDist2) {
+ newArcDistance2 = minimumArcDist2;
+ } else if (arcDist2 > maximumArcDist2) {
+ newArcDistance2 = maximumArcDist2;
+ }
+ if (newArcDistance2 != 0) {
+ float ratio2 = newArcDistance2 / arcDist2;
+ float ratio = (float) Math.sqrt(ratio2);
+ ex = dx + (ratio * (ex - dx));
+ ey = dy + (ratio * (ey - dy));
+ }
+ float control1X = (startX + ex) / 2;
+ float control1Y = (startY + ey) / 2;
+ float control2X = (ex + endX) / 2;
+ float control2Y = (ey + endY) / 2;
+ path.cubicTo(control1X, control1Y, control2X, control2Y, endX, endY);
return path;
}
}
diff --git a/core/java/android/view/FocusFinder.java b/core/java/android/view/FocusFinder.java
index 3f3d519..a07a7ef 100644
--- a/core/java/android/view/FocusFinder.java
+++ b/core/java/android/view/FocusFinder.java
@@ -16,12 +16,16 @@
package android.view;
+import static android.view.View.KEYBOARD_NAVIGATION_GROUP_CLUSTER;
+import static android.view.View.KEYBOARD_NAVIGATION_GROUP_SECTION;
+
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.graphics.Rect;
import android.util.ArrayMap;
import android.util.SparseArray;
import android.util.SparseBooleanArray;
+import android.view.View.KeyboardNavigationGroupType;
import java.util.ArrayList;
import java.util.Collections;
@@ -106,25 +110,31 @@
}
/**
- * Find the root of the next keyboard navigation cluster after the current one.
- * @param root Thew view tree to look inside. Cannot be null
- * @param currentCluster The starting point of the search. Null means the default cluster
+ * Find the root of the next keyboard navigation group after the current one. The group type can
+ * be either a cluster or a section.
+ * @param groupType Type of the keyboard navigation group
+ * @param root The view tree to look inside. Cannot be null
+ * @param currentGroup The starting point of the search. Null means the default group
* @param direction Direction to look
- * @return The next cluster, or null if none exists
+ * @return The next group, or null if none exists
*/
- public View findNextKeyboardNavigationCluster(
- @NonNull ViewGroup root, @Nullable View currentCluster, int direction) {
+ public View findNextKeyboardNavigationGroup(
+ @KeyboardNavigationGroupType int groupType,
+ @NonNull View root,
+ @Nullable View currentGroup,
+ int direction) {
View next = null;
- final ArrayList<View> clusters = mTempList;
+ final ArrayList<View> groups = mTempList;
try {
- clusters.clear();
- root.addKeyboardNavigationClusters(clusters, direction);
- if (!clusters.isEmpty()) {
- next = findNextKeyboardNavigationCluster(root, currentCluster, clusters, direction);
+ groups.clear();
+ root.addKeyboardNavigationGroups(groupType, groups, direction);
+ if (!groups.isEmpty()) {
+ next = findNextKeyboardNavigationGroup(
+ groupType, root, currentGroup, groups, direction);
}
} finally {
- clusters.clear();
+ groups.clear();
}
return next;
}
@@ -197,19 +207,25 @@
}
}
- private View findNextKeyboardNavigationCluster(ViewGroup root, View currentCluster,
- List<View> clusters, int direction) {
- final int count = clusters.size();
+ private View findNextKeyboardNavigationGroup(
+ @KeyboardNavigationGroupType int groupType,
+ View root,
+ View currentGroup,
+ List<View> groups,
+ int direction) {
+ final int count = groups.size();
switch (direction) {
case View.FOCUS_FORWARD:
case View.FOCUS_DOWN:
case View.FOCUS_RIGHT:
- return getNextKeyboardNavigationCluster(root, currentCluster, clusters, count);
+ return getNextKeyboardNavigationGroup(
+ groupType, root, currentGroup, groups, count);
case View.FOCUS_BACKWARD:
case View.FOCUS_UP:
case View.FOCUS_LEFT:
- return getPreviousKeyboardNavigationCluster(root, currentCluster, clusters, count);
+ return getPreviousKeyboardNavigationGroup(
+ groupType, root, currentGroup, groups, count);
default:
throw new IllegalArgumentException("Unknown direction: " + direction);
}
@@ -315,43 +331,70 @@
return null;
}
- private static View getNextKeyboardNavigationCluster(ViewGroup root, View currentCluster,
- List<View> clusters, int count) {
- if (currentCluster == null) {
- // The current cluster is the default one.
- // The next cluster after the default one is the first one.
- // Note that the caller guarantees that 'clusters' is not empty.
- return clusters.get(0);
+ private static View getNextKeyboardNavigationGroup(
+ @KeyboardNavigationGroupType int groupType,
+ View root,
+ View currentGroup,
+ List<View> groups,
+ int count) {
+ if (currentGroup == null) {
+ // The current group is the default one.
+ // The next group after the default one is the first one.
+ // Note that the caller guarantees that 'group' is not empty.
+ return groups.get(0);
}
- final int position = clusters.lastIndexOf(currentCluster);
+ final int position = groups.lastIndexOf(currentGroup);
if (position >= 0 && position + 1 < count) {
- // Return the next non-default cluster if we can find it.
- return clusters.get(position + 1);
+ // Return the next non-default group if we can find it.
+ return groups.get(position + 1);
}
- // The current cluster is the last one. The next one is the default one, i.e. the root.
- return root;
+ switch (groupType) {
+ case KEYBOARD_NAVIGATION_GROUP_CLUSTER:
+ // The current cluster is the last one. The next one is the default one, i.e. the
+ // root.
+ return root;
+ case KEYBOARD_NAVIGATION_GROUP_SECTION:
+ // There is no "default section", hence returning the first one.
+ return groups.get(0);
+ default:
+ throw new IllegalArgumentException(
+ "Unknown keyboard navigation group type: " + groupType);
+ }
}
- private static View getPreviousKeyboardNavigationCluster(ViewGroup root, View currentCluster,
- List<View> clusters, int count) {
- if (currentCluster == null) {
- // The current cluster is the default one.
- // The previous cluster before the default one is the last one.
- // Note that the caller guarantees that 'clusters' is not empty.
- return clusters.get(count - 1);
+ private static View getPreviousKeyboardNavigationGroup(
+ @KeyboardNavigationGroupType int groupType,
+ View root,
+ View currentGroup,
+ List<View> groups,
+ int count) {
+ if (currentGroup == null) {
+ // The current group is the default one.
+ // The previous group before the default one is the last one.
+ // Note that the caller guarantees that 'groups' is not empty.
+ return groups.get(count - 1);
}
- final int position = clusters.indexOf(currentCluster);
+ final int position = groups.indexOf(currentGroup);
if (position > 0) {
- // Return the previous non-default cluster if we can find it.
- return clusters.get(position - 1);
+ // Return the previous non-default group if we can find it.
+ return groups.get(position - 1);
}
- // The current cluster is the first one. The previous one is the default one, i.e. the
- // root.
- return root;
+ switch (groupType) {
+ case KEYBOARD_NAVIGATION_GROUP_CLUSTER:
+ // The current cluster is the first one. The previous one is the default one, i.e.
+ // the root.
+ return root;
+ case KEYBOARD_NAVIGATION_GROUP_SECTION:
+ // There is no "default section", hence returning the last one.
+ return groups.get(count - 1);
+ default:
+ throw new IllegalArgumentException(
+ "Unknown keyboard navigation group type: " + groupType);
+ }
}
/**
diff --git a/core/java/android/view/IApplicationToken.aidl b/core/java/android/view/IApplicationToken.aidl
index 633b40f..b01c0ef 100644
--- a/core/java/android/view/IApplicationToken.aidl
+++ b/core/java/android/view/IApplicationToken.aidl
@@ -20,10 +20,5 @@
/** {@hide} */
interface IApplicationToken
{
- void windowsDrawn();
- void windowsVisible();
- void windowsGone();
- boolean keyDispatchingTimedOut(String reason);
- long getKeyDispatchingTimeout();
}
diff --git a/core/java/android/view/IWindowManager.aidl b/core/java/android/view/IWindowManager.aidl
index 21875fe..8611d69 100644
--- a/core/java/android/view/IWindowManager.aidl
+++ b/core/java/android/view/IWindowManager.aidl
@@ -83,41 +83,9 @@
void setOverscan(int displayId, int left, int top, int right, int bottom);
// These can only be called when holding the MANAGE_APP_TOKENS permission.
- void pauseKeyDispatching(IBinder token);
- void resumeKeyDispatching(IBinder token);
void setEventDispatching(boolean enabled);
void addWindowToken(IBinder token, int type, int displayId);
void removeWindowToken(IBinder token, int displayId);
- /**
- * Creates the object representation for the application token in the window manager and adds it
- * to the specified task Id.
- *
- * @param addPos The position to add the token to in the task.
- * @param token The token to add.
- * @param taskId The Id of the task we are adding the token to.
- * @param requestedOrientation Orientation to use.
- * @param fullscreen True if the application token is fullscreen.
- * @param showWhenLocked True if the application token should be shown when locked.
- * @param configChanges Input configuration changes.
- * @param voiceInteraction True if the token is in voice interaction mode.
- * @param launchTaskBehind True if the token is been launched from behind.
- * @param alwaysFocusable True if the app windows are always focusable regardless of the stack
- * they are in.
- * @param targetSdkVersion The application's target SDK version
- */
- void addAppToken(int addPos, IApplicationToken token, int taskId, int requestedOrientation,
- boolean fullscreen, boolean showWhenLocked, int configChanges, boolean voiceInteraction,
- boolean launchTaskBehind, boolean alwaysFocusable, int targetSdkVersion,
- int rotationAnimationHint);
- /**
- * Adds an already existing application token on the window manager side to the input task id.
- *
- * @param token The token we are adding to the input task Id.
- * @param taskId The Id of the task we are adding the token to.
- */
- void addAppToTask(IBinder token, int taskId);
- void setAppOrientation(IApplicationToken token, int requestedOrientation);
- int getAppOrientation(IApplicationToken token);
void setFocusedApp(IBinder token, boolean moveFocusNow);
void prepareAppTransition(int transit, boolean alwaysKeepCurrent);
int getPendingAppTransition();
@@ -154,20 +122,6 @@
boolean scaleUp);
void executeAppTransition();
- /**
- * Called to set the starting window for the input token and returns true if the starting
- * window was set for the token.
- */
- boolean setAppStartingWindow(IBinder token, String pkg, int theme,
- in CompatibilityInfo compatInfo, CharSequence nonLocalizedLabel, int labelRes,
- int icon, int logo, int windowFlags, IBinder transferFrom, boolean createIfNeeded);
- void setAppVisibility(IBinder token, boolean visible);
- void notifyAppResumed(IBinder token, boolean wasStopped, boolean allowSavedSurface);
- void notifyAppStopped(IBinder token);
- void startAppFreezingScreen(IBinder token, int configChanges);
- void stopAppFreezingScreen(IBinder token, boolean force);
- void removeAppToken(IBinder token, int displayId);
-
/** Used by system ui to report that recents has shown itself. */
void endProlongedAnimations();
@@ -315,15 +269,6 @@
boolean requestAssistScreenshot(IAssistScreenshotReceiver receiver);
/**
- * Create a screenshot of the applications currently displayed.
- *
- * @param frameScale the scale to apply to the frame, only used when width = -1 and
- * height = -1
- */
- Bitmap screenshotApplications(IBinder appToken, int displayId, int maxWidth, int maxHeight,
- float frameScale);
-
- /**
* Called by the status bar to notify Views of changes to System UI visiblity.
*/
oneway void statusBarVisibilityChanged(int visibility);
diff --git a/core/java/android/view/MenuInflater.java b/core/java/android/view/MenuInflater.java
index 73ea9ee..f3f3d40 100644
--- a/core/java/android/view/MenuInflater.java
+++ b/core/java/android/view/MenuInflater.java
@@ -334,6 +334,9 @@
private ActionProvider itemActionProvider;
+ private CharSequence itemContentDescription;
+ private CharSequence itemTooltip;
+
private static final int defaultGroupId = NO_ID;
private static final int defaultItemId = NO_ID;
private static final int defaultItemCategory = 0;
@@ -424,6 +427,10 @@
itemActionProvider = null;
}
+ itemContentDescription =
+ a.getText(com.android.internal.R.styleable.MenuItem_contentDescription);
+ itemTooltip = a.getText(com.android.internal.R.styleable.MenuItem_tooltip);
+
a.recycle();
itemAdded = false;
@@ -486,6 +493,9 @@
if (itemActionProvider != null) {
item.setActionProvider(itemActionProvider);
}
+
+ item.setContentDescription(itemContentDescription);
+ item.setTooltip(itemTooltip);
}
public MenuItem addItem() {
diff --git a/core/java/android/view/MenuItem.java b/core/java/android/view/MenuItem.java
index 9e8b97e..5ced765 100644
--- a/core/java/android/view/MenuItem.java
+++ b/core/java/android/view/MenuItem.java
@@ -599,4 +599,40 @@
* @return This menu item instance for call chaining
*/
public MenuItem setOnActionExpandListener(OnActionExpandListener listener);
+
+ /**
+ * Change the content description associated with this menu item.
+ *
+ * @param contentDescription The new content description.
+ */
+ default MenuItem setContentDescription(CharSequence contentDescription) {
+ return this;
+ }
+
+ /**
+ * Retrieve the content description associated with this menu item.
+ *
+ * @return The content description.
+ */
+ default CharSequence getContentDescription() {
+ return null;
+ }
+
+ /**
+ * Change the tooltip text associated with this menu item.
+ *
+ * @param tooltip The new tooltip text.
+ */
+ default MenuItem setTooltip(CharSequence tooltip) {
+ return this;
+ }
+
+ /**
+ * Retrieve the tooltip text associated with this menu item.
+ *
+ * @return The tooltip text.
+ */
+ default CharSequence getTooltip() {
+ return null;
+ }
}
diff --git a/core/java/android/view/RenderNodeAnimator.java b/core/java/android/view/RenderNodeAnimator.java
index 7747580..9515040 100644
--- a/core/java/android/view/RenderNodeAnimator.java
+++ b/core/java/android/view/RenderNodeAnimator.java
@@ -200,8 +200,7 @@
// in mTransformationInfo instead of in RenderNode, so we need to update
// it with the final value here.
if (mRenderProperty == RenderNodeAnimator.ALPHA) {
- // Don't need null check because ViewPropertyAnimator's
- // ctor calls ensureTransformationInfo()
+ mViewTarget.ensureTransformationInfo();
mViewTarget.mTransformationInfo.mAlpha = mFinalValue;
}
diff --git a/core/java/android/view/ThreadedRenderer.java b/core/java/android/view/ThreadedRenderer.java
index 5012215..f3ebcb4 100644
--- a/core/java/android/view/ThreadedRenderer.java
+++ b/core/java/android/view/ThreadedRenderer.java
@@ -28,7 +28,6 @@
import android.os.Binder;
import android.os.IBinder;
import android.os.ParcelFileDescriptor;
-import android.os.RemoteException;
import android.os.ServiceManager;
import android.os.Trace;
import android.util.Log;
@@ -72,17 +71,6 @@
private static final String CACHE_PATH_SHADERS = "com.android.opengl.shaders_cache";
/**
- * System property used to enable or disable dirty regions invalidation.
- * This property is only queried if {@link #RENDER_DIRTY_REGIONS} is true.
- * The default value of this property is assumed to be true.
- *
- * Possible values:
- * "true", to enable partial invalidates
- * "false", to disable partial invalidates
- */
- static final String RENDER_DIRTY_REGIONS_PROPERTY = "debug.hwui.render_dirty_regions";
-
- /**
* System property used to enable or disable threaded rendering profiling.
* The default value of this property is assumed to be false.
*
diff --git a/core/java/android/view/View.java b/core/java/android/view/View.java
index f51e029..0b1dfa2 100644
--- a/core/java/android/view/View.java
+++ b/core/java/android/view/View.java
@@ -1248,6 +1248,14 @@
@Retention(RetentionPolicy.SOURCE)
public @interface FocusRealDirection {} // Like @FocusDirection, but without forward/backward
+ /** @hide */
+ @IntDef({
+ KEYBOARD_NAVIGATION_GROUP_CLUSTER,
+ KEYBOARD_NAVIGATION_GROUP_SECTION
+ })
+ @Retention(RetentionPolicy.SOURCE)
+ public @interface KeyboardNavigationGroupType {}
+
/**
* Use with {@link #focusSearch(int)}. Move focus to the previous selectable
* item.
@@ -1281,6 +1289,18 @@
public static final int FOCUS_DOWN = 0x00000082;
/**
+ * Use with {@link #keyboardNavigationGroupSearch(int, View, int)}. Search for a keyboard
+ * navigation cluster.
+ */
+ public static final int KEYBOARD_NAVIGATION_GROUP_CLUSTER = 1;
+
+ /**
+ * Use with {@link #keyboardNavigationGroupSearch(int, View, int)}. Search for a keyboard
+ * navigation section.
+ */
+ public static final int KEYBOARD_NAVIGATION_GROUP_SECTION = 2;
+
+ /**
* Bits of {@link #getMeasuredWidthAndState()} and
* {@link #getMeasuredWidthAndState()} that provide the actual measured size.
*/
@@ -3293,7 +3313,9 @@
@ViewDebug.FlagToString(mask = PFLAG_DIRTY_MASK, equals = PFLAG_DIRTY_OPAQUE, name = "DIRTY_OPAQUE"),
@ViewDebug.FlagToString(mask = PFLAG_DIRTY_MASK, equals = PFLAG_DIRTY, name = "DIRTY")
}, formatToHexString = true)
- int mPrivateFlags;
+
+ /* @hide */
+ public int mPrivateFlags;
int mPrivateFlags2;
int mPrivateFlags3;
@@ -3374,7 +3396,8 @@
float mTransitionAlpha = 1f;
}
- TransformationInfo mTransformationInfo;
+ /** @hide */
+ public TransformationInfo mTransformationInfo;
/**
* Current clip bounds. to which all drawing of this view are constrained.
@@ -9096,22 +9119,50 @@
}
}
+ final boolean isKeyboardNavigationGroupOfType(@KeyboardNavigationGroupType int groupType) {
+ switch (groupType) {
+ case KEYBOARD_NAVIGATION_GROUP_CLUSTER:
+ return isKeyboardNavigationCluster();
+ case KEYBOARD_NAVIGATION_GROUP_SECTION:
+ return isKeyboardNavigationSection();
+ default:
+ throw new IllegalArgumentException(
+ "Unknown keyboard navigation group type: " + groupType);
+ }
+ }
+
/**
- * Find the nearest keyboard navigation cluster in the specified direction.
- * This does not actually give focus to that cluster.
+ * Find the nearest keyboard navigation group in the specified direction. The group type can be
+ * either a cluster or a section.
+ * This does not actually give focus to that group.
*
+ * @param groupType Type of the keyboard navigation group
+ * @param currentGroup The starting point of the search. Null means the current group is not
+ * found yet
* @param direction Direction to look
*
- * @return The nearest keyboard navigation cluster in the specified direction, or null if none
+ * @return The nearest keyboard navigation group in the specified direction, or null if none
* can be found
*/
- public View keyboardNavigationClusterSearch(int direction) {
- if (mParent != null) {
- final View currentCluster = isKeyboardNavigationCluster() ? this : null;
- return mParent.keyboardNavigationClusterSearch(currentCluster, direction);
- } else {
- return null;
+ public View keyboardNavigationGroupSearch(
+ @KeyboardNavigationGroupType int groupType, View currentGroup, int direction) {
+ if (isKeyboardNavigationGroupOfType(groupType)) {
+ currentGroup = this;
}
+ if (isRootNamespace()
+ || (groupType == KEYBOARD_NAVIGATION_GROUP_SECTION
+ && isKeyboardNavigationCluster())) {
+ // Root namespace means we should consider ourselves the top of the
+ // tree for group searching; otherwise we could be group searching
+ // into other tabs. see LocalActivityManager and TabHost for more info.
+ // In addition, a cluster node works as a root for section searches.
+ return FocusFinder.getInstance().findNextKeyboardNavigationGroup(
+ groupType, this, currentGroup, direction);
+ } else if (mParent != null) {
+ return mParent.keyboardNavigationGroupSearch(
+ groupType, currentGroup, direction);
+ }
+ return null;
}
/**
@@ -9237,14 +9288,19 @@
}
/**
- * Adds any keyboard navigation cluster roots that are descendants of this view (possibly
- * including this view if it is a cluster root itself) to views.
+ * Adds any keyboard navigation group roots that are descendants of this view (possibly
+ * including this view if it is a group root itself) to views. The group type can be either a
+ * cluster or a section.
*
- * @param views Cluster roots found so far
+ * @param groupType Type of the keyboard navigation group
+ * @param views Keyboard navigation group roots found so far
* @param direction Direction to look
*/
- public void addKeyboardNavigationClusters(@NonNull Collection<View> views, int direction) {
- if (!isKeyboardNavigationCluster()) {
+ public void addKeyboardNavigationGroups(
+ @KeyboardNavigationGroupType int groupType,
+ @NonNull Collection<View> views,
+ int direction) {
+ if (!(isKeyboardNavigationGroupOfType(groupType))) {
return;
}
views.add(this);
@@ -14056,8 +14112,9 @@
* invalidated as well. This is usually true for a full
* invalidate, but may be set to false if the View's contents or
* dimensions have not changed.
+ * @hide
*/
- void invalidate(boolean invalidateCache) {
+ public void invalidate(boolean invalidateCache) {
invalidateInternal(0, 0, mRight - mLeft, mBottom - mTop, invalidateCache, true);
}
diff --git a/core/java/android/view/ViewGroup.java b/core/java/android/view/ViewGroup.java
index 7c133ac..56501ec 100644
--- a/core/java/android/view/ViewGroup.java
+++ b/core/java/android/view/ViewGroup.java
@@ -902,23 +902,6 @@
}
@Override
- public View keyboardNavigationClusterSearch(View currentCluster, int direction) {
- if (isKeyboardNavigationCluster()) {
- currentCluster = this;
- }
- if (isRootNamespace()) {
- // root namespace means we should consider ourselves the top of the
- // tree for cluster searching; otherwise we could be focus searching
- // into other tabs. see LocalActivityManager and TabHost for more info
- return FocusFinder.getInstance().findNextKeyboardNavigationCluster(
- this, currentCluster, direction);
- } else if (mParent != null) {
- return mParent.keyboardNavigationClusterSearch(currentCluster, direction);
- }
- return null;
- }
-
- @Override
public boolean requestChildRectangleOnScreen(View child, Rect rectangle, boolean immediate) {
return false;
}
@@ -1164,13 +1147,14 @@
}
@Override
- public void addKeyboardNavigationClusters(Collection<View> views, int direction) {
+ public void addKeyboardNavigationGroups(
+ @KeyboardNavigationGroupType int groupType, Collection<View> views, int direction) {
final int focusableCount = views.size();
- super.addKeyboardNavigationClusters(views, direction);
+ super.addKeyboardNavigationGroups(groupType, views, direction);
if (focusableCount != views.size()) {
- // No need to look for clusters inside a cluster.
+ // No need to look for groups inside a group.
return;
}
@@ -1183,8 +1167,14 @@
for (int i = 0; i < count; i++) {
final View child = children[i];
+ if (groupType == KEYBOARD_NAVIGATION_GROUP_SECTION
+ && child.isKeyboardNavigationCluster()) {
+ // When the current cluster is the default cluster, and we are searching for
+ // sections, ignore sections inside non-default clusters.
+ continue;
+ }
if ((child.mViewFlags & VISIBILITY_MASK) == VISIBLE) {
- child.addKeyboardNavigationClusters(views, direction);
+ child.addKeyboardNavigationGroups(groupType, views, direction);
}
}
}
@@ -5350,11 +5340,96 @@
}
/**
+ * HW-only, Rect-ignoring invalidation path.
+ *
+ * Returns false if this path was unable to complete successfully. This means
+ * it hit a ViewParent it doesn't recognize and needs to fall back to calculating
+ * damage area.
+ *
+ * Hardware acceleration ignores damage rectangles, since native computes damage for everything
+ * drawn by HWUI (and SW layer / drawing cache doesn't keep track of damage area).
+ *
+ * Ignores opaque dirty optimizations, always using the full PFLAG_DIRTY flag.
+ *
+ * Ignores FLAG_OPTIMIZE_INVALIDATE, since we're not computing a rect,
+ * so no point in optimizing that.
+ * @hide
+ */
+ public boolean tryInvalidateChildHardware(View child) {
+ final AttachInfo attachInfo = mAttachInfo;
+ if (attachInfo == null || !attachInfo.mHardwareAccelerated) {
+ return false;
+ }
+
+ // verify it's ViewGroups up to a ViewRootImpl
+ ViewRootImpl viewRoot = null;
+ ViewParent parent = getParent();
+ while (parent != null) {
+ if (parent instanceof ViewGroup) {
+ parent = parent.getParent();
+ } else if (parent instanceof ViewRootImpl) {
+ viewRoot = (ViewRootImpl) parent;
+ break;
+ } else {
+ // unknown parent type, abort
+ return false;
+ }
+ }
+ if (viewRoot == null) {
+ // unable to find ViewRoot
+ return false;
+ }
+
+ final boolean drawAnimation = (child.mPrivateFlags & PFLAG_DRAW_ANIMATION) != 0;
+
+ if (child.mLayerType != LAYER_TYPE_NONE) {
+ mPrivateFlags |= PFLAG_INVALIDATED;
+ }
+
+ parent = this;
+ do {
+ if (parent != viewRoot) {
+ // Note: we cast here without checking isinstance, to avoid cost of isinstance again
+ ViewGroup viewGroup = (ViewGroup) parent;
+ if (drawAnimation) {
+ viewGroup.mPrivateFlags |= PFLAG_DRAW_ANIMATION;
+ }
+
+ // We lazily use PFLAG_DIRTY, since computing opaque isn't worth the potential
+ // optimization in provides in a DisplayList world.
+ viewGroup.mPrivateFlags =
+ (viewGroup.mPrivateFlags & ~PFLAG_DIRTY_MASK) | PFLAG_DIRTY;
+
+ // simplified invalidateChildInParent behavior: clear cache validity to be safe,
+ // and mark inval if in layer
+ viewGroup.mPrivateFlags &= ~PFLAG_DRAWING_CACHE_VALID;
+ if (viewGroup.mLayerType != LAYER_TYPE_NONE) {
+ viewGroup.mPrivateFlags |= PFLAG_INVALIDATED;
+ }
+ } else {
+ if (drawAnimation) {
+ viewRoot.mIsAnimating = true;
+ }
+ ((ViewRootImpl) parent).invalidate();
+ return true;
+ }
+
+ parent = parent.getParent();
+ } while (parent != null);
+ return true;
+ }
+
+
+ /**
* Don't call or override this method. It is used for the implementation of
* the view hierarchy.
*/
@Override
public final void invalidateChild(View child, final Rect dirty) {
+ if (tryInvalidateChildHardware(child)) {
+ return;
+ }
+
ViewParent parent = this;
final AttachInfo attachInfo = mAttachInfo;
@@ -5362,8 +5437,7 @@
// If the child is drawing an animation, we want to copy this flag onto
// ourselves and the parent to make sure the invalidate request goes
// through
- final boolean drawAnimation = (child.mPrivateFlags & PFLAG_DRAW_ANIMATION)
- == PFLAG_DRAW_ANIMATION;
+ final boolean drawAnimation = (child.mPrivateFlags & PFLAG_DRAW_ANIMATION) != 0;
// Check whether the child that requests the invalidate is fully opaque
// Views being animated or transformed are not considered opaque because we may
@@ -5464,10 +5538,10 @@
*/
@Override
public ViewParent invalidateChildInParent(final int[] location, final Rect dirty) {
- if ((mPrivateFlags & PFLAG_DRAWN) == PFLAG_DRAWN ||
- (mPrivateFlags & PFLAG_DRAWING_CACHE_VALID) == PFLAG_DRAWING_CACHE_VALID) {
- if ((mGroupFlags & (FLAG_OPTIMIZE_INVALIDATE | FLAG_ANIMATION_DONE)) !=
- FLAG_OPTIMIZE_INVALIDATE) {
+ if ((mPrivateFlags & (PFLAG_DRAWN | PFLAG_DRAWING_CACHE_VALID)) != 0) {
+ // either DRAWN, or DRAWING_CACHE_VALID
+ if ((mGroupFlags & (FLAG_OPTIMIZE_INVALIDATE | FLAG_ANIMATION_DONE))
+ != FLAG_OPTIMIZE_INVALIDATE) {
dirty.offset(location[CHILD_LEFT_INDEX] - mScrollX,
location[CHILD_TOP_INDEX] - mScrollY);
if ((mGroupFlags & FLAG_CLIP_CHILDREN) == 0) {
@@ -5482,35 +5556,28 @@
dirty.setEmpty();
}
}
- mPrivateFlags &= ~PFLAG_DRAWING_CACHE_VALID;
location[CHILD_LEFT_INDEX] = left;
location[CHILD_TOP_INDEX] = top;
-
- if (mLayerType != LAYER_TYPE_NONE) {
- mPrivateFlags |= PFLAG_INVALIDATED;
- }
-
- return mParent;
-
} else {
- mPrivateFlags &= ~PFLAG_DRAWN & ~PFLAG_DRAWING_CACHE_VALID;
- location[CHILD_LEFT_INDEX] = mLeft;
- location[CHILD_TOP_INDEX] = mTop;
if ((mGroupFlags & FLAG_CLIP_CHILDREN) == FLAG_CLIP_CHILDREN) {
dirty.set(0, 0, mRight - mLeft, mBottom - mTop);
} else {
// in case the dirty rect extends outside the bounds of this container
dirty.union(0, 0, mRight - mLeft, mBottom - mTop);
}
+ location[CHILD_LEFT_INDEX] = mLeft;
+ location[CHILD_TOP_INDEX] = mTop;
- if (mLayerType != LAYER_TYPE_NONE) {
- mPrivateFlags |= PFLAG_INVALIDATED;
- }
-
- return mParent;
+ mPrivateFlags &= ~PFLAG_DRAWN;
}
+ mPrivateFlags &= ~PFLAG_DRAWING_CACHE_VALID;
+ if (mLayerType != LAYER_TYPE_NONE) {
+ mPrivateFlags |= PFLAG_INVALIDATED;
+ }
+
+ return mParent;
}
return null;
@@ -5523,7 +5590,7 @@
* damage area
* @hide
*/
- public boolean damageChildDeferred(View child) {
+ public boolean damageChildDeferred() {
ViewParent parent = getParent();
while (parent != null) {
if (parent instanceof ViewGroup) {
@@ -5546,7 +5613,7 @@
* @hide
*/
public void damageChild(View child, final Rect dirty) {
- if (damageChildDeferred(child)) {
+ if (damageChildDeferred()) {
return;
}
diff --git a/core/java/android/view/ViewOverlay.java b/core/java/android/view/ViewOverlay.java
index b770bd5..61cf0c7 100644
--- a/core/java/android/view/ViewOverlay.java
+++ b/core/java/android/view/ViewOverlay.java
@@ -283,8 +283,9 @@
}
}
+ /** @hide */
@Override
- void invalidate(boolean invalidateCache) {
+ public void invalidate(boolean invalidateCache) {
super.invalidate(invalidateCache);
if (mHostView != null) {
mHostView.invalidate(invalidateCache);
diff --git a/core/java/android/view/ViewParent.java b/core/java/android/view/ViewParent.java
index 79b05cd..c9277ca 100644
--- a/core/java/android/view/ViewParent.java
+++ b/core/java/android/view/ViewParent.java
@@ -18,6 +18,7 @@
import android.graphics.Rect;
import android.os.Bundle;
+import android.view.View.KeyboardNavigationGroupType;
import android.view.accessibility.AccessibilityEvent;
/**
@@ -147,17 +148,20 @@
public View focusSearch(View v, int direction);
/**
- * Find the nearest keyboard navigation cluster in the specified direction.
- * This does not actually give focus to that cluster.
+ * Find the nearest keyboard navigation group in the specified direction. The group type can be
+ * either a cluster or a section.
+ * This does not actually give focus to that group.
*
- * @param currentCluster The starting point of the search. Null means the current cluster is not
- * found yet
+ * @param groupType Type of the keyboard navigation group
+ * @param currentGroup The starting point of the search. Null means the current group is not
+ * found yet
* @param direction Direction to look
*
- * @return The nearest keyboard navigation cluster in the specified direction, or null if none
+ * @return The nearest keyboard navigation group in the specified direction, or null if none
* can be found
*/
- View keyboardNavigationClusterSearch(View currentCluster, int direction);
+ View keyboardNavigationGroupSearch(
+ @KeyboardNavigationGroupType int groupType, View currentGroup, int direction);
/**
* Change the z order of the child so it's on top of all other children.
diff --git a/core/java/android/view/ViewRootImpl.java b/core/java/android/view/ViewRootImpl.java
index 69464fc..b42f769 100644
--- a/core/java/android/view/ViewRootImpl.java
+++ b/core/java/android/view/ViewRootImpl.java
@@ -16,6 +16,8 @@
package android.view;
+import static android.view.View.KEYBOARD_NAVIGATION_GROUP_CLUSTER;
+import static android.view.View.KEYBOARD_NAVIGATION_GROUP_SECTION;
import static android.view.WindowCallbacks.RESIZE_MODE_DOCKED_DIVIDER;
import static android.view.WindowCallbacks.RESIZE_MODE_FREEFORM;
import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_FORCE_DECOR_VIEW_VISIBILITY;
@@ -71,6 +73,7 @@
import android.util.TypedValue;
import android.view.Surface.OutOfResourcesException;
import android.view.View.AttachInfo;
+import android.view.View.KeyboardNavigationGroupType;
import android.view.View.MeasureSpec;
import android.view.accessibility.AccessibilityEvent;
import android.view.accessibility.AccessibilityManager;
@@ -238,7 +241,7 @@
int mWidth;
int mHeight;
Rect mDirty;
- boolean mIsAnimating;
+ public boolean mIsAnimating;
private boolean mDragResizing;
private boolean mInvalidateRootRequested;
@@ -259,7 +262,7 @@
final Rect mTempRect; // used in the transaction to not thrash the heap.
final Rect mVisRect; // used to retrieve visible rect of focused view.
- boolean mTraversalScheduled;
+ public boolean mTraversalScheduled;
int mTraversalBarrier;
boolean mWillDrawSoon;
/** Set to true while in performTraversals for detecting when die(true) is called from internal
@@ -4393,13 +4396,14 @@
return false;
}
- private boolean performClusterNavigation(int direction) {
+ private boolean performKeyboardGroupNavigation(
+ @KeyboardNavigationGroupType int groupType, int direction) {
final View focused = mView.findFocus();
- final View cluster = focused != null
- ? focused.keyboardNavigationClusterSearch(direction)
- : keyboardNavigationClusterSearch(null, direction);
+ final View group = focused != null
+ ? focused.keyboardNavigationGroupSearch(groupType, null, direction)
+ : keyboardNavigationGroupSearch(groupType, null, direction);
- if (cluster != null && cluster.restoreLastFocus()) {
+ if (group != null && group.restoreLastFocus()) {
return true;
}
@@ -4418,17 +4422,34 @@
return FINISH_NOT_HANDLED;
}
- int clusterNavigationDirection = 0;
+ int groupNavigationDirection = 0;
+ @KeyboardNavigationGroupType int groupType = 0;
if (event.getAction() == KeyEvent.ACTION_DOWN && event.isCtrlPressed()) {
final int character =
event.getUnicodeChar(event.getMetaState() & ~KeyEvent.META_CTRL_MASK);
if (character == '+') {
- clusterNavigationDirection = View.FOCUS_FORWARD;
+ groupType = KEYBOARD_NAVIGATION_GROUP_CLUSTER;
+ groupNavigationDirection = View.FOCUS_FORWARD;
}
if (character == '_') {
- clusterNavigationDirection = View.FOCUS_BACKWARD;
+ groupType = KEYBOARD_NAVIGATION_GROUP_CLUSTER;
+ groupNavigationDirection = View.FOCUS_BACKWARD;
+ }
+ }
+
+ if (event.getAction() == KeyEvent.ACTION_DOWN && event.isAltPressed()) {
+ final int character =
+ event.getUnicodeChar(event.getMetaState() & ~KeyEvent.META_ALT_MASK);
+ if (character == '+') {
+ groupType = KEYBOARD_NAVIGATION_GROUP_SECTION;
+ groupNavigationDirection = View.FOCUS_FORWARD;
+ }
+
+ if (character == '_') {
+ groupType = KEYBOARD_NAVIGATION_GROUP_SECTION;
+ groupNavigationDirection = View.FOCUS_BACKWARD;
}
}
@@ -4437,7 +4458,7 @@
&& event.isCtrlPressed()
&& event.getRepeatCount() == 0
&& !KeyEvent.isModifierKey(event.getKeyCode())
- && clusterNavigationDirection == 0) {
+ && groupNavigationDirection == 0) {
if (mView.dispatchKeyShortcutEvent(event)) {
return FINISH_HANDLED;
}
@@ -4456,8 +4477,8 @@
// Handle automatic focus changes.
if (event.getAction() == KeyEvent.ACTION_DOWN) {
- if (clusterNavigationDirection != 0) {
- if (performClusterNavigation(clusterNavigationDirection)) {
+ if (groupNavigationDirection != 0) {
+ if (performKeyboardGroupNavigation(groupType, groupNavigationDirection)) {
return FINISH_HANDLED;
}
} else {
@@ -4553,8 +4574,8 @@
if (mPointerIconType != pointerType) {
mPointerIconType = pointerType;
+ mCustomPointerIcon = null;
if (mPointerIconType != PointerIcon.TYPE_CUSTOM) {
- mCustomPointerIcon = null;
InputManager.getInstance().setPointerIconType(pointerType);
return true;
}
@@ -5888,13 +5909,11 @@
* {@inheritDoc}
*/
@Override
- public View keyboardNavigationClusterSearch(View currentCluster, int direction) {
+ public View keyboardNavigationGroupSearch(
+ @KeyboardNavigationGroupType int groupType, View currentGroup, int direction) {
checkThread();
- if (!(mView instanceof ViewGroup)) {
- return null;
- }
- return FocusFinder.getInstance().findNextKeyboardNavigationCluster(
- (ViewGroup) mView, currentCluster, direction);
+ return FocusFinder.getInstance().findNextKeyboardNavigationGroup(groupType,
+ mView, currentGroup, direction);
}
public void debug() {
diff --git a/core/java/android/view/WindowManagerGlobal.java b/core/java/android/view/WindowManagerGlobal.java
index 83fc362..fc6448a 100644
--- a/core/java/android/view/WindowManagerGlobal.java
+++ b/core/java/android/view/WindowManagerGlobal.java
@@ -249,6 +249,19 @@
return views;
}
+ public View getWindowView(IBinder windowToken) {
+ synchronized (mLock) {
+ final int numViews = mViews.size();
+ for (int i = 0; i < numViews; ++i) {
+ final View view = mViews.get(i);
+ if (view.getWindowToken() == windowToken) {
+ return view;
+ }
+ }
+ }
+ return null;
+ }
+
public View getRootView(String name) {
synchronized (mLock) {
for (int i = mRoots.size() - 1; i >= 0; --i) {
diff --git a/core/java/android/view/accessibility/AccessibilityCache.java b/core/java/android/view/accessibility/AccessibilityCache.java
index 9bc4bc7..db2ea48 100644
--- a/core/java/android/view/accessibility/AccessibilityCache.java
+++ b/core/java/android/view/accessibility/AccessibilityCache.java
@@ -370,6 +370,9 @@
mIsAllWindowsCached = false;
}
+ /**
+ * Clears nodes for the window with the given id
+ */
private void clearNodesForWindowLocked(int windowId) {
if (DEBUG) {
Log.i(LOG_TAG, "clearNodesForWindowLocked(" + windowId + ")");
diff --git a/core/java/android/webkit/RenderProcessGoneDetail.java b/core/java/android/webkit/RenderProcessGoneDetail.java
new file mode 100644
index 0000000..77d8596
--- /dev/null
+++ b/core/java/android/webkit/RenderProcessGoneDetail.java
@@ -0,0 +1,35 @@
+/*
+ * Copyright (C) 2016 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 android.webkit;
+
+/**
+ * This class provides more specific information about why the render process
+ * exited. The application may use this to decide how to handle the situation.
+ **/
+public abstract class RenderProcessGoneDetail {
+ /**
+ * Indicates whether the render process was observed to crash, or whether
+ * it was killed by the system.
+ *
+ * If the render process was killed, this is most likely caused by the
+ * system being low on memory.
+ *
+ * @return True if render process crashed, otherwise it was killed by
+ * system.
+ **/
+ public abstract boolean didCrash();
+}
diff --git a/core/java/android/webkit/WebViewClient.java b/core/java/android/webkit/WebViewClient.java
index 76d3fb1..8703468 100644
--- a/core/java/android/webkit/WebViewClient.java
+++ b/core/java/android/webkit/WebViewClient.java
@@ -466,4 +466,31 @@
public void onReceivedLoginRequest(WebView view, String realm,
String account, String args) {
}
+
+ /**
+ * Notify host application that the given webview's render process has exited.
+ *
+ * Multiple WebView instances may be associated with a single render process;
+ * onRenderProcessGone will be called for each WebView that was affected.
+ * The application's implementation of this callback should only attempt to
+ * clean up the specific WebView given as a parameter, and should not assume
+ * that other WebView instances are affected.
+ *
+ * The given WebView can't be used, and should be removed from the view hierarchy,
+ * all references to it should be cleaned up, e.g any references in the Activity
+ * or other classes saved using findViewById and similar calls, etc
+ *
+ * To cause an render process crash for test purpose, the application can
+ * call loadUrl("chrome://crash") on the WebView. Note that multiple WebView
+ * instances may be affected if they share a render process, not just the
+ * specific WebView which loaded chrome://crash.
+ *
+ * @param view The WebView which needs to be cleaned up.
+ * @param detail the reason why it exited.
+ * @return true if the host application handled the situation that process has
+ * exited, otherwise, application will crash.
+ */
+ public boolean onRenderProcessGone(WebView view, RenderProcessGoneDetail detail) {
+ return false;
+ }
}
diff --git a/core/java/android/webkit/WebViewZygote.java b/core/java/android/webkit/WebViewZygote.java
index e0d589a..2d6f443 100644
--- a/core/java/android/webkit/WebViewZygote.java
+++ b/core/java/android/webkit/WebViewZygote.java
@@ -24,6 +24,8 @@
import android.text.TextUtils;
import android.util.Log;
+import com.android.internal.annotations.GuardedBy;
+
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
@@ -38,70 +40,104 @@
private static final String WEBVIEW_ZYGOTE_SERVICE_32 = "webview_zygote32";
private static final String WEBVIEW_ZYGOTE_SERVICE_64 = "webview_zygote64";
+ /**
+ * Lock object that protects all other static members.
+ */
+ private static final Object sLock = new Object();
+
+ /**
+ * Instance that maintains the socket connection to the zygote. This is null if the zygote
+ * is not running or is not connected.
+ */
+ @GuardedBy("sLock")
private static ZygoteProcess sZygote;
+ /**
+ * Information about the selected WebView package. This is set from #onWebViewProviderChanged().
+ */
+ @GuardedBy("sLock")
private static PackageInfo sPackage;
+ /**
+ * Flag for whether multi-process WebView is enabled. If this is false, the zygote
+ * will not be started.
+ */
+ @GuardedBy("sLock")
private static boolean sMultiprocessEnabled = false;
public static ZygoteProcess getProcess() {
- connectToZygoteIfNeeded();
- return sZygote;
+ synchronized (sLock) {
+ connectToZygoteIfNeededLocked();
+ return sZygote;
+ }
}
public static String getPackageName() {
- return sPackage.packageName;
+ synchronized (sLock) {
+ return sPackage.packageName;
+ }
}
public static boolean isMultiprocessEnabled() {
- return sMultiprocessEnabled && sPackage != null;
+ synchronized (sLock) {
+ return sMultiprocessEnabled && sPackage != null;
+ }
}
public static void setMultiprocessEnabled(boolean enabled) {
- sMultiprocessEnabled = enabled;
+ synchronized (sLock) {
+ sMultiprocessEnabled = enabled;
- // When toggling between multi-process being on/off, start or stop the
- // service. If it is enabled and the zygote is not yet started, bring up the service.
- // Otherwise, bring down the service. The name may be null if the package
- // information has not yet been resolved.
- final String serviceName = getServiceName();
- if (serviceName == null) return;
+ // When toggling between multi-process being on/off, start or stop the
+ // service. If it is enabled and the zygote is not yet started, bring up the service.
+ // Otherwise, bring down the service. The name may be null if the package
+ // information has not yet been resolved.
+ final String serviceName = getServiceNameLocked();
+ if (serviceName == null) return;
- if (enabled && sZygote == null) {
- SystemService.start(serviceName);
- } else {
- SystemService.stop(serviceName);
- sZygote = null;
+ if (enabled && sZygote == null) {
+ SystemService.start(serviceName);
+ } else {
+ SystemService.stop(serviceName);
+ sZygote = null;
+ }
}
}
public static void onWebViewProviderChanged(PackageInfo packageInfo) {
- sPackage = packageInfo;
+ String serviceName;
+ synchronized (sLock) {
+ sPackage = packageInfo;
- // If multi-process is not enabled, then do not start the zygote service.
- if (!sMultiprocessEnabled) {
- return;
+ // If multi-process is not enabled, then do not start the zygote service.
+ if (!sMultiprocessEnabled) {
+ return;
+ }
+
+ serviceName = getServiceNameLocked();
+ sZygote = null;
+
+ // The service may enter the RUNNING state before it opens the socket,
+ // so connectToZygoteIfNeededLocked() may still fail.
+ if (SystemService.isStopped(serviceName)) {
+ SystemService.start(serviceName);
+ } else {
+ SystemService.restart(serviceName);
+ }
+
+ try {
+ SystemService.waitForState(serviceName, SystemService.State.RUNNING, 5000);
+ } catch (TimeoutException e) {
+ Log.e(LOGTAG, "Timed out waiting for " + serviceName);
+ return;
+ }
+
+ connectToZygoteIfNeededLocked();
}
-
- final String serviceName = getServiceName();
-
- if (SystemService.isStopped(serviceName)) {
- SystemService.start(serviceName);
- } else if (sZygote != null) {
- SystemService.restart(serviceName);
- }
-
- try {
- SystemService.waitForState(serviceName, SystemService.State.RUNNING, 5000);
- } catch (TimeoutException e) {
- Log.e(LOGTAG, "Timed out waiting for " + serviceName);
- return;
- }
-
- connectToZygoteIfNeeded();
}
- private static String getServiceName() {
+ @GuardedBy("sLock")
+ private static String getServiceNameLocked() {
if (sPackage == null)
return null;
@@ -113,7 +149,8 @@
return WEBVIEW_ZYGOTE_SERVICE_32;
}
- private static void connectToZygoteIfNeeded() {
+ @GuardedBy("sLock")
+ private static void connectToZygoteIfNeededLocked() {
if (sZygote != null)
return;
@@ -122,7 +159,7 @@
return;
}
- final String serviceName = getServiceName();
+ final String serviceName = getServiceNameLocked();
if (!SystemService.isRunning(serviceName)) {
Log.e(LOGTAG, serviceName + " is not running");
return;
diff --git a/core/java/android/widget/CompoundButton.java b/core/java/android/widget/CompoundButton.java
index dd63fef..3213a34 100644
--- a/core/java/android/widget/CompoundButton.java
+++ b/core/java/android/widget/CompoundButton.java
@@ -169,7 +169,7 @@
*
* @param listener the callback to call on checked state change
*/
- public void setOnCheckedChangeListener(OnCheckedChangeListener listener) {
+ public void setOnCheckedChangeListener(@Nullable OnCheckedChangeListener listener) {
mOnCheckedChangeListener = listener;
}
diff --git a/core/java/com/android/internal/app/ChooserActivity.java b/core/java/com/android/internal/app/ChooserActivity.java
index c314cae..6c4faa4 100644
--- a/core/java/com/android/internal/app/ChooserActivity.java
+++ b/core/java/com/android/internal/app/ChooserActivity.java
@@ -69,6 +69,7 @@
import android.widget.BaseAdapter;
import android.widget.ListView;
import com.android.internal.R;
+import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.app.ResolverActivity.TargetInfo;
import com.android.internal.logging.MetricsLogger;
import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
@@ -93,9 +94,13 @@
private IntentSender mRefinementIntentSender;
private RefinementResultReceiver mRefinementResultReceiver;
private ChooserTarget[] mCallerChooserTargets;
+ private ComponentName[] mFilteredComponentNames;
private Intent mReferrerFillInIntent;
+ private long mChooserShownTime;
+ private boolean mIsSuccessfullySelected;
+
private ChooserListAdapter mChooserListAdapter;
private ChooserRowAdapter mChooserRowAdapter;
@@ -155,6 +160,8 @@
@Override
protected void onCreate(Bundle savedInstanceState) {
+ final long intentReceivedTime = System.currentTimeMillis();
+ mIsSuccessfullySelected = false;
Intent intent = getIntent();
Parcelable targetParcelable = intent.getParcelableExtra(Intent.EXTRA_INTENT);
if (!(targetParcelable instanceof Intent)) {
@@ -235,7 +242,7 @@
}
names[i] = (ComponentName) pa[i];
}
- setFilteredComponents(names);
+ mFilteredComponentNames = names;
}
pa = intent.getParcelableArrayExtra(Intent.EXTRA_CHOOSER_TARGETS);
@@ -257,6 +264,13 @@
null, false);
MetricsLogger.action(this, MetricsEvent.ACTION_ACTIVITY_CHOOSER_SHOWN);
+
+ mChooserShownTime = System.currentTimeMillis();
+ final long systemCost = mChooserShownTime - intentReceivedTime;
+ MetricsLogger.histogram(null, "system_cost_for_smart_sharing", (int) systemCost);
+ if (DEBUG) {
+ Log.d(TAG, "System Time Cost is " + systemCost);
+ }
}
static SharedPreferences getPinnedSharedPrefs(Context context) {
@@ -410,6 +424,7 @@
@Override
public void startSelected(int which, boolean always, boolean filtered) {
+ final long selectionCost = System.currentTimeMillis() - mChooserShownTime;
super.startSelected(which, always, filtered);
if (mChooserListAdapter != null) {
@@ -435,6 +450,17 @@
if (cat != 0) {
MetricsLogger.action(this, cat, value);
}
+
+ if (mIsSuccessfullySelected) {
+ if (DEBUG) {
+ Log.d(TAG, "User Selection Time Cost is " + selectionCost);
+ Log.d(TAG, "position of selected app/service/caller is " +
+ Integer.toString(value));
+ }
+ MetricsLogger.histogram(null, "user_selection_cost_for_smart_sharing",
+ (int) selectionCost);
+ MetricsLogger.histogram(null, "app_position_for_smart_sharing", value);
+ }
}
}
@@ -563,6 +589,9 @@
if (ri != null && ri.activityInfo != null) {
usageStatsManager.reportChooserSelection(ri.activityInfo.packageName, getUserId(),
annotation, null, info.getResolvedIntent().getAction());
+ if (mAdapter != null) {
+ mAdapter.updateModel(info.getResolvedComponentName());
+ }
if (DEBUG) {
Log.d(TAG, "ResolveInfo Package is" + ri.activityInfo.packageName);
}
@@ -570,6 +599,7 @@
Log.d(TAG, "Can not log Chooser Counts of null ResovleInfo");
}
}
+ mIsSuccessfullySelected = true;
}
void onRefinementResult(TargetInfo selectedTarget, Intent matchingIntent) {
@@ -642,17 +672,65 @@
}
}
+ public class ChooserListController extends ResolverListController {
+ public ChooserListController(Context context,
+ PackageManager pm,
+ Intent targetIntent,
+ String referrerPackageName,
+ int launchedFromUid) {
+ super(context, pm, targetIntent, referrerPackageName, launchedFromUid);
+ }
+
+ @Override
+ boolean isComponentPinned(ComponentName name) {
+ return mPinnedSharedPrefs.getBoolean(name.flattenToString(), false);
+ }
+
+ @Override
+ boolean isComponentFiltered(ComponentName name) {
+ if (mFilteredComponentNames == null) {
+ return false;
+ }
+ for (ComponentName filteredComponentName : mFilteredComponentNames) {
+ if (name.equals(filteredComponentName)) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ @Override
+ public float getScore(DisplayResolveInfo target) {
+ if (target == null) {
+ return CALLER_TARGET_SCORE_BOOST;
+ }
+ float score = super.getScore(target);
+ if (target.isPinned()) {
+ score += PINNED_TARGET_SCORE_BOOST;
+ }
+ return score;
+ }
+ }
+
@Override
public ResolveListAdapter createAdapter(Context context, List<Intent> payloadIntents,
Intent[] initialIntents, List<ResolveInfo> rList, int launchedFromUid,
boolean filterLastUsed) {
final ChooserListAdapter adapter = new ChooserListAdapter(context, payloadIntents,
- initialIntents, rList, launchedFromUid, filterLastUsed);
- if (DEBUG) Log.d(TAG, "Adapter created; querying services");
- queryTargetServices(adapter);
+ initialIntents, rList, launchedFromUid, filterLastUsed, createListController());
return adapter;
}
+ @VisibleForTesting
+ protected ResolverListController createListController() {
+ return new ChooserListController(
+ this,
+ mPm,
+ getTargetIntent(),
+ getReferrerPackageName(),
+ mLaunchedFromUid);
+ }
+
final class ChooserTargetInfo implements TargetInfo {
private final DisplayResolveInfo mSourceInfo;
private final ResolveInfo mBackupResolveInfo;
@@ -853,10 +931,11 @@
public ChooserListAdapter(Context context, List<Intent> payloadIntents,
Intent[] initialIntents, List<ResolveInfo> rList, int launchedFromUid,
- boolean filterLastUsed) {
+ boolean filterLastUsed, ResolverListController resolverListController) {
// Don't send the initial intents through the shared ResolverActivity path,
// we want to separate them into a different section.
- super(context, payloadIntents, null, rList, launchedFromUid, filterLastUsed);
+ super(context, payloadIntents, null, rList, launchedFromUid, filterLastUsed,
+ resolverListController);
if (initialIntents != null) {
final PackageManager pm = getPackageManager();
@@ -922,18 +1001,6 @@
}
@Override
- public float getScore(DisplayResolveInfo target) {
- if (target == null) {
- return CALLER_TARGET_SCORE_BOOST;
- }
- float score = super.getScore(target);
- if (target.isPinned()) {
- score += PINNED_TARGET_SCORE_BOOST;
- }
- return score;
- }
-
- @Override
public View onCreateView(ViewGroup parent) {
return mInflater.inflate(
com.android.internal.R.layout.resolve_grid_item, parent, false);
@@ -944,6 +1011,8 @@
if (mServiceTargets != null) {
pruneServiceTargets();
}
+ if (DEBUG) Log.d(TAG, "List built querying services");
+ queryTargetServices(this);
}
@Override
diff --git a/core/java/com/android/internal/app/IBatteryStats.aidl b/core/java/com/android/internal/app/IBatteryStats.aidl
index 5623a2c..99a25fd 100644
--- a/core/java/com/android/internal/app/IBatteryStats.aidl
+++ b/core/java/com/android/internal/app/IBatteryStats.aidl
@@ -125,7 +125,7 @@
void noteNetworkStatsEnabled();
void noteDeviceIdleMode(int mode, String activeReason, int activeUid);
void setBatteryState(int status, int health, int plugType, int level, int temp, int volt,
- int chargeUAh);
+ int chargeUAh, int chargeFullUAh);
long getAwakeTimeBattery();
long getAwakeTimePlugged();
diff --git a/core/java/com/android/internal/app/ResolverActivity.java b/core/java/com/android/internal/app/ResolverActivity.java
index c516b5c..23c1969 100644
--- a/core/java/com/android/internal/app/ResolverActivity.java
+++ b/core/java/com/android/internal/app/ResolverActivity.java
@@ -16,15 +16,14 @@
package com.android.internal.app;
-import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.StringRes;
+import android.annotation.UiThread;
import android.app.Activity;
import android.app.ActivityThread;
import android.app.VoiceInteractor.PickOptionRequest;
import android.app.VoiceInteractor.PickOptionRequest.Option;
import android.app.VoiceInteractor.Prompt;
-import android.content.pm.ComponentInfo;
import android.os.AsyncTask;
import android.os.RemoteException;
import android.provider.MediaStore;
@@ -33,6 +32,7 @@
import android.util.Slog;
import android.widget.AbsListView;
import com.android.internal.R;
+import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.content.PackageMonitor;
import android.app.ActivityManager;
@@ -75,7 +75,6 @@
import java.util.ArrayList;
import java.util.Arrays;
-import java.util.Collections;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
@@ -83,21 +82,16 @@
import java.util.Set;
import static android.content.Intent.FLAG_ACTIVITY_NEW_TASK;
-import static android.view.WindowManager.LayoutParams.FLAG_LAYOUT_INSET_DECOR;
-import static android.view.WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN;
/**
* This activity is displayed when the system attempts to start an Intent for
* which there is more than one matching activity, allowing the user to decide
* which to go to. It is not normally used directly by application developers.
*/
+@UiThread
public class ResolverActivity extends Activity {
- private static final String TAG = "ResolverActivity";
- private static final boolean DEBUG = false;
- private int mLaunchedFromUid;
- private ResolveListAdapter mAdapter;
- private PackageManager mPm;
+ protected ResolveListAdapter mAdapter;
private boolean mSafeForwardingMode;
private boolean mAlwaysUseOption;
private AbsListView mAdapterView;
@@ -108,13 +102,18 @@
private int mLastSelected = AbsListView.INVALID_POSITION;
private boolean mResolvingHome = false;
private int mProfileSwitchMessageId = -1;
+ private int mLayoutId;
private final ArrayList<Intent> mIntents = new ArrayList<>();
- private ResolverComparator mResolverComparator;
private PickTargetOptionRequest mPickOptionRequest;
- private ComponentName[] mFilteredComponents;
+ private String mReferrerPackage;
protected ResolverDrawerLayout mResolverDrawerLayout;
protected String mContentType;
+ protected PackageManager mPm;
+ protected int mLaunchedFromUid;
+
+ private static final String TAG = "ResolverActivity";
+ private static final boolean DEBUG = false;
private boolean mRegistered;
private final PackageMonitor mPackageMonitor = new PackageMonitor() {
@@ -261,6 +260,7 @@
mPackageMonitor.register(this, getMainLooper(), false);
mRegistered = true;
+ mReferrerPackage = getReferrerPackageName();
final ActivityManager am = (ActivityManager) getSystemService(ACTIVITY_SERVICE);
mIconDpi = am.getLauncherLargeIconDensity();
@@ -268,11 +268,6 @@
// Add our initial intent as the first item, regardless of what else has already been added.
mIntents.add(0, new Intent(intent));
- final String referrerPackage = getReferrerPackageName();
-
- mResolverComparator = new ResolverComparator(this, getTargetIntent(), referrerPackage);
- mContentType = mResolverComparator.mContentType;
-
if (configureContentView(mIntents, initialIntents, rList, alwaysUseOption)) {
return;
}
@@ -306,11 +301,11 @@
if (titleIcon != null) {
ApplicationInfo ai = null;
try {
- if (!TextUtils.isEmpty(referrerPackage)) {
- ai = mPm.getApplicationInfo(referrerPackage, 0);
+ if (!TextUtils.isEmpty(mReferrerPackage)) {
+ ai = mPm.getApplicationInfo(mReferrerPackage, 0);
}
} catch (NameNotFoundException e) {
- Log.e(TAG, "Could not find referrer package " + referrerPackage);
+ Log.e(TAG, "Could not find referrer package " + mReferrerPackage);
}
if (ai != null) {
@@ -372,24 +367,6 @@
+ (categories != null ? Arrays.toString(categories.toArray()) : ""));
}
- public final void setFilteredComponents(ComponentName[] components) {
- mFilteredComponents = components;
- }
-
- public final boolean isComponentFiltered(ComponentInfo component) {
- if (mFilteredComponents == null) {
- return false;
- }
-
- final ComponentName checkName = component.getComponentName();
- for (ComponentName name : mFilteredComponents) {
- if (name.equals(checkName)) {
- return true;
- }
- }
- return false;
- }
-
/**
* Perform any initialization needed for voice interaction.
*/
@@ -431,7 +408,7 @@
return mIntents.isEmpty() ? null : mIntents.get(0);
}
- private String getReferrerPackageName() {
+ protected String getReferrerPackageName() {
final Uri referrer = getReferrer();
if (referrer != null && "android-app".equals(referrer.getScheme())) {
return referrer.getHost();
@@ -689,7 +666,7 @@
final Intent intent = target != null ? target.getResolvedIntent() : null;
if (intent != null && (mAlwaysUseOption || mAdapter.hasFilteredItem())
- && mAdapter.mOrigResolveList != null) {
+ && mAdapter.mUnfilteredResolveList != null) {
// Build a reasonable intent filter, based on what matched.
IntentFilter filter = new IntentFilter();
Intent filterIntent;
@@ -774,11 +751,11 @@
}
if (filter != null) {
- final int N = mAdapter.mOrigResolveList.size();
+ final int N = mAdapter.mUnfilteredResolveList.size();
ComponentName[] set = new ComponentName[N];
int bestMatch = 0;
for (int i=0; i<N; i++) {
- ResolveInfo r = mAdapter.mOrigResolveList.get(i).getResolveInfoAt(0);
+ ResolveInfo r = mAdapter.mUnfilteredResolveList.get(i).getResolveInfoAt(0);
set[i] = new ComponentName(r.activityInfo.packageName,
r.activityInfo.name);
if (r.match > bestMatch) bestMatch = r.match;
@@ -899,7 +876,17 @@
Intent[] initialIntents, List<ResolveInfo> rList, int launchedFromUid,
boolean filterLastUsed) {
return new ResolveListAdapter(context, payloadIntents, initialIntents, rList,
- launchedFromUid, filterLastUsed);
+ launchedFromUid, filterLastUsed, createListController());
+ }
+
+ @VisibleForTesting
+ protected ResolverListController createListController() {
+ return new ResolverListController(
+ this,
+ mPm,
+ getTargetIntent(),
+ getReferrerPackageName(),
+ mLaunchedFromUid);
}
/**
@@ -914,32 +901,38 @@
// to handle.
mAdapter = createAdapter(this, payloadIntents, initialIntents, rList,
mLaunchedFromUid, alwaysUseOption && !isVoiceInteraction());
+ boolean rebuildCompleted = mAdapter.rebuildList();
- final int layoutId;
if (mAdapter.hasFilteredItem()) {
- layoutId = R.layout.resolver_list_with_default;
+ mLayoutId = R.layout.resolver_list_with_default;
alwaysUseOption = false;
} else {
- layoutId = getLayoutResource();
+ mLayoutId = getLayoutResource();
}
mAlwaysUseOption = alwaysUseOption;
int count = mAdapter.getUnfilteredCount();
- if (count == 1 && mAdapter.getOtherProfile() == null) {
- // Only one target, so we're a candidate to auto-launch!
- final TargetInfo target = mAdapter.targetInfoForPosition(0, false);
- if (shouldAutoLaunchSingleChoice(target)) {
- safelyStartActivity(target);
- mPackageMonitor.unregister();
- mRegistered = false;
- finish();
- return true;
+
+ // We only rebuild asynchronously when we have multiple elements to sort. In the case where
+ // we're already done, we can check if we should auto-launch immediately.
+ if (rebuildCompleted) {
+ if (count == 1 && mAdapter.getOtherProfile() == null) {
+ // Only one target, so we're a candidate to auto-launch!
+ final TargetInfo target = mAdapter.targetInfoForPosition(0, false);
+ if (shouldAutoLaunchSingleChoice(target)) {
+ safelyStartActivity(target);
+ mPackageMonitor.unregister();
+ mRegistered = false;
+ finish();
+ return true;
+ }
}
}
- if (count > 0) {
- setContentView(layoutId);
+
+ if (count > 0 || !rebuildCompleted) {
+ setContentView(mLayoutId);
mAdapterView = (AbsListView) findViewById(R.id.resolver_list);
- onPrepareAdapterView(mAdapterView, mAdapter, alwaysUseOption);
+ onPrepareAdapterView(mAdapterView, mAdapter, mAlwaysUseOption);
} else {
setContentView(R.layout.resolver_list);
@@ -1236,20 +1229,21 @@
private final List<ResolveInfo> mBaseResolveList;
private ResolveInfo mLastChosen;
private DisplayResolveInfo mOtherProfile;
- private final int mLaunchedFromUid;
private boolean mHasExtendedInfo;
+ private ResolverListController mResolverListController;
protected final LayoutInflater mInflater;
List<DisplayResolveInfo> mDisplayList;
- List<ResolvedComponentInfo> mOrigResolveList;
+ List<ResolvedComponentInfo> mUnfilteredResolveList;
private int mLastChosenPosition = -1;
private boolean mFilterLastUsed;
public ResolveListAdapter(Context context, List<Intent> payloadIntents,
Intent[] initialIntents, List<ResolveInfo> rList, int launchedFromUid,
- boolean filterLastUsed) {
+ boolean filterLastUsed,
+ ResolverListController resolverListController) {
mIntents = payloadIntents;
mInitialIntents = initialIntents;
mBaseResolveList = rList;
@@ -1257,12 +1251,11 @@
mInflater = LayoutInflater.from(context);
mDisplayList = new ArrayList<>();
mFilterLastUsed = filterLastUsed;
- rebuildList();
+ mResolverListController = resolverListController;
}
public void handlePackagesChanged() {
rebuildList();
- notifyDataSetChanged();
if (getCount() == 0) {
// We no longer have any items... just finish the activity.
finish();
@@ -1293,12 +1286,21 @@
}
public float getScore(DisplayResolveInfo target) {
- return mResolverComparator.getScore(target.getResolvedComponentName());
+ return mResolverListController.getScore(target);
}
- private void rebuildList() {
- List<ResolvedComponentInfo> currentResolveList = null;
+ public void updateModel(ComponentName componentName) {
+ mResolverListController.updateModel(componentName);
+ }
+ /**
+ * Rebuild the list of resolvers. In some cases some parts will need some asynchronous work
+ * to complete.
+ *
+ * @return Whether or not the list building is completed.
+ */
+ protected boolean rebuildList() {
+ List<ResolvedComponentInfo> currentResolveList = null;
try {
final Intent primaryIntent = getTargetIntent();
mLastChosen = AppGlobals.getPackageManager().getLastChosenActivity(
@@ -1312,84 +1314,88 @@
mOtherProfile = null;
mDisplayList.clear();
if (mBaseResolveList != null) {
- currentResolveList = mOrigResolveList = new ArrayList<>();
- addResolveListDedupe(currentResolveList, getTargetIntent(), mBaseResolveList);
+ currentResolveList = mUnfilteredResolveList = new ArrayList<>();
+ mResolverListController.addResolveListDedupe(currentResolveList,
+ getTargetIntent(),
+ mBaseResolveList);
} else {
- final boolean shouldGetResolvedFilter = shouldGetResolvedFilter();
- final boolean shouldGetActivityMetadata = shouldGetActivityMetadata();
- for (int i = 0, N = mIntents.size(); i < N; i++) {
- final Intent intent = mIntents.get(i);
- final List<ResolveInfo> infos = mPm.queryIntentActivities(intent,
- PackageManager.MATCH_DEFAULT_ONLY
- | (shouldGetResolvedFilter ? PackageManager.GET_RESOLVED_FILTER : 0)
- | (shouldGetActivityMetadata ? PackageManager.GET_META_DATA : 0));
- if (infos != null) {
- if (currentResolveList == null) {
- currentResolveList = mOrigResolveList = new ArrayList<>();
- }
- addResolveListDedupe(currentResolveList, intent, infos);
- }
+ currentResolveList =
+ mResolverListController.getResolversForIntent(shouldGetResolvedFilter(),
+ shouldGetActivityMetadata(),
+ mIntents);
+ if (currentResolveList == null) {
+ processSortedList(currentResolveList);
+ return true;
}
-
- // Filter out any activities that the launched uid does not
- // have permission for.
- // Also filter out those that are suspended because they couldn't
- // be started. We don't do this when we have an explicit
- // list of resolved activities, because that only happens when
- // we are being subclassed, so we can safely launch whatever
- // they gave us.
- if (currentResolveList != null) {
- for (int i=currentResolveList.size()-1; i >= 0; i--) {
- ActivityInfo ai = currentResolveList.get(i)
- .getResolveInfoAt(0).activityInfo;
- int granted = ActivityManager.checkComponentPermission(
- ai.permission, mLaunchedFromUid,
- ai.applicationInfo.uid, ai.exported);
- boolean suspended = (ai.applicationInfo.flags
- & ApplicationInfo.FLAG_SUSPENDED) != 0;
- if (granted != PackageManager.PERMISSION_GRANTED || suspended
- || isComponentFiltered(ai)) {
- // Access not allowed!
- if (mOrigResolveList == currentResolveList) {
- mOrigResolveList = new ArrayList<>(mOrigResolveList);
- }
- currentResolveList.remove(i);
- }
- }
+ List<ResolvedComponentInfo> originalList =
+ mResolverListController.filterIneligibleActivities(currentResolveList,
+ true);
+ if (originalList != null) {
+ mUnfilteredResolveList = originalList;
}
}
int N;
if ((currentResolveList != null) && ((N = currentResolveList.size()) > 0)) {
- // Only display the first matches that are either of equal
- // priority or have asked to be default options.
- ResolvedComponentInfo rci0 = currentResolveList.get(0);
- ResolveInfo r0 = rci0.getResolveInfoAt(0);
- for (int i=1; i<N; i++) {
- ResolveInfo ri = currentResolveList.get(i).getResolveInfoAt(0);
- if (DEBUG) Log.v(
- TAG,
- r0.activityInfo.name + "=" +
- r0.priority + "/" + r0.isDefault + " vs " +
- ri.activityInfo.name + "=" +
- ri.priority + "/" + ri.isDefault);
- if (r0.priority != ri.priority ||
- r0.isDefault != ri.isDefault) {
- while (i < N) {
- if (mOrigResolveList == currentResolveList) {
- mOrigResolveList = new ArrayList<>(mOrigResolveList);
- }
- currentResolveList.remove(i);
- N--;
- }
- }
+ // We only care about fixing the unfilteredList if the current resolve list and
+ // current resolve list are currently the same.
+ List<ResolvedComponentInfo> originalList =
+ mResolverListController.filterLowPriority(currentResolveList,
+ mUnfilteredResolveList == currentResolveList);
+ if (originalList != null) {
+ mUnfilteredResolveList = originalList;
}
+
if (N > 1) {
- mResolverComparator.compute(currentResolveList);
- Collections.sort(currentResolveList, mResolverComparator);
+ AsyncTask<List<ResolvedComponentInfo>,
+ Void,
+ List<ResolvedComponentInfo>> sortingTask =
+ new AsyncTask<List<ResolvedComponentInfo>,
+ Void,
+ List<ResolvedComponentInfo>>() {
+ @Override
+ protected List<ResolvedComponentInfo> doInBackground(
+ List<ResolvedComponentInfo>... params) {
+ mResolverListController.sort(params[0]);
+ return params[0];
+ }
+
+ @Override
+ protected void onPostExecute(List<ResolvedComponentInfo> sortedComponents) {
+ processSortedList(sortedComponents);
+ onPrepareAdapterView(mAdapterView, mAdapter, mAlwaysUseOption);
+ if (mProfileView != null) {
+ bindProfileView();
+ }
+ }
+ };
+ sortingTask.execute(currentResolveList);
+ return false;
+ } else {
+ processSortedList(currentResolveList);
+ return true;
}
+ } else {
+ processSortedList(currentResolveList);
+ return true;
+ }
+ }
+
+ private void disableLastChosenIfNeeded() {
+ // Layout doesn't handle both profile button and last chosen
+ // so disable last chosen if profile button is present.
+ if (mOtherProfile != null && mLastChosenPosition >= 0) {
+ mLastChosenPosition = -1;
+ mFilterLastUsed = false;
+ }
+ }
+
+
+ private void processSortedList(List<ResolvedComponentInfo> sortedComponents) {
+ int N;
+ if (sortedComponents != null && (N = sortedComponents.size()) != 0) {
// First put the initial items at the top.
if (mInitialIntents != null) {
- for (int i=0; i<mInitialIntents.length; i++) {
+ for (int i = 0; i < mInitialIntents.length; i++) {
Intent ii = mInitialIntents[i];
if (ii == null) {
continue;
@@ -1405,7 +1411,7 @@
UserManager userManager =
(UserManager) getSystemService(Context.USER_SERVICE);
if (ii instanceof LabeledIntent) {
- LabeledIntent li = (LabeledIntent)ii;
+ LabeledIntent li = (LabeledIntent) ii;
ri.resolvePackageName = li.getSourcePackage();
ri.labelRes = li.getLabelResource();
ri.nonLocalizedLabel = li.getNonLocalizedLabel();
@@ -1423,16 +1429,16 @@
// Check for applications with same name and use application name or
// package name if necessary
- rci0 = currentResolveList.get(0);
- r0 = rci0.getResolveInfoAt(0);
+ ResolvedComponentInfo rci0 = sortedComponents.get(0);
+ ResolveInfo r0 = rci0.getResolveInfoAt(0);
int start = 0;
- CharSequence r0Label = r0.loadLabel(mPm);
+ CharSequence r0Label = r0.loadLabel(mPm);
mHasExtendedInfo = false;
for (int i = 1; i < N; i++) {
if (r0Label == null) {
r0Label = r0.activityInfo.packageName;
}
- ResolvedComponentInfo rci = currentResolveList.get(i);
+ ResolvedComponentInfo rci = sortedComponents.get(i);
ResolveInfo ri = rci.getResolveInfoAt(0);
CharSequence riLabel = ri.loadLabel(mPm);
if (riLabel == null) {
@@ -1441,59 +1447,19 @@
if (riLabel.equals(r0Label)) {
continue;
}
- processGroup(currentResolveList, start, (i-1), rci0, r0Label);
+ processGroup(sortedComponents, start, (i - 1), rci0, r0Label);
rci0 = rci;
r0 = ri;
r0Label = riLabel;
start = i;
}
// Process last group
- processGroup(currentResolveList, start, (N-1), rci0, r0Label);
+ processGroup(sortedComponents, start, (N - 1), rci0, r0Label);
}
-
- // Layout doesn't handle both profile button and last chosen
- // so disable last chosen if profile button is present.
- if (mOtherProfile != null && mLastChosenPosition >= 0) {
- mLastChosenPosition = -1;
- mFilterLastUsed = false;
- }
-
+ disableLastChosenIfNeeded();
onListRebuilt();
}
- private void addResolveListDedupe(List<ResolvedComponentInfo> into, Intent intent,
- List<ResolveInfo> from) {
- final int fromCount = from.size();
- final int intoCount = into.size();
- for (int i = 0; i < fromCount; i++) {
- final ResolveInfo newInfo = from.get(i);
- boolean found = false;
- // Only loop to the end of into as it was before we started; no dupes in from.
- for (int j = 0; j < intoCount; j++) {
- final ResolvedComponentInfo rci = into.get(j);
- if (isSameResolvedComponent(newInfo, rci)) {
- found = true;
- rci.add(intent, newInfo);
- break;
- }
- }
- if (!found) {
- final ComponentName name = new ComponentName(
- newInfo.activityInfo.packageName, newInfo.activityInfo.name);
- final ResolvedComponentInfo rci = new ResolvedComponentInfo(name,
- intent, newInfo);
- rci.setPinned(isComponentPinned(name));
- into.add(rci);
- }
- }
- }
-
- private boolean isSameResolvedComponent(ResolveInfo a, ResolvedComponentInfo b) {
- final ActivityInfo ai = a.activityInfo;
- return ai.packageName.equals(b.name.getPackageName())
- && ai.name.equals(b.name.getClassName());
- }
-
public void onListRebuilt() {
// This space for rent
}
@@ -1715,7 +1681,8 @@
}
}
- static final class ResolvedComponentInfo {
+ @VisibleForTesting
+ public static final class ResolvedComponentInfo {
public final ComponentName name;
private boolean mPinned;
private final List<Intent> mIntents = new ArrayList<>();
diff --git a/core/java/com/android/internal/app/ResolverComparator.java b/core/java/com/android/internal/app/ResolverComparator.java
index 75be906..45fad97f 100644
--- a/core/java/com/android/internal/app/ResolverComparator.java
+++ b/core/java/com/android/internal/app/ResolverComparator.java
@@ -27,11 +27,16 @@
import android.content.pm.ComponentInfo;
import android.content.pm.PackageManager;
import android.content.pm.ResolveInfo;
+import android.content.SharedPreferences;
+import android.os.Environment;
+import android.os.storage.StorageManager;
import android.os.UserHandle;
import android.text.TextUtils;
+import android.util.ArrayMap;
import android.util.Log;
import com.android.internal.app.ResolverActivity.ResolvedComponentInfo;
+import java.io.File;
import java.text.Collator;
import java.util.ArrayList;
import java.util.Comparator;
@@ -54,6 +59,12 @@
private static final float RECENCY_MULTIPLIER = 2.f;
+ // feature names used in ranking.
+ private static final String LAUNCH_SCORE = "launch";
+ private static final String TIME_SPENT_SCORE = "timeSpent";
+ private static final String RECENCY_SCORE = "recency";
+ private static final String CHOOSER_SCORE = "chooser";
+
private final Collator mCollator;
private final boolean mHttp;
private final PackageManager mPm;
@@ -65,6 +76,7 @@
private final String mReferrerPackage;
public String mContentType;
private String mAction;
+ private LogisticRegressionAppRanker mRanker;
public ResolverComparator(Context context, Intent intent, String referrerPackage) {
mCollator = Collator.getInstance(context.getResources().getConfiguration().locale);
@@ -80,6 +92,7 @@
mStats = mUsm.queryAndAggregateUsageStats(mSinceTime, mCurrentTime);
mContentType = intent.getType();
mAction = intent.getAction();
+ mRanker = new LogisticRegressionAppRanker(context);
}
public void compute(List<ResolvedComponentInfo> targets) {
@@ -152,16 +165,13 @@
for (ScoredTarget target : mScoredTargets.values()) {
final float recency = (float) Math.max(target.lastTimeUsed - recentSinceTime, 0)
/ (mostRecentlyUsedTime - recentSinceTime);
- final float recencyScore = recency * recency * RECENCY_MULTIPLIER;
- final float usageTimeScore = (float) target.timeSpent / mostTimeSpent;
- final float launchCountScore = (float) target.launchCount / mostLaunched;
-
- target.score = recencyScore + usageTimeScore + launchCountScore;
+ target.setFeatures((float) target.launchCount / mostLaunched,
+ (float) target.timeSpent / mostTimeSpent,
+ recency * recency * RECENCY_MULTIPLIER,
+ (float) target.chooserCount / mostSelected);
+ target.selectProb = mRanker.predict(target.getFeatures());
if (DEBUG) {
- Log.d(TAG, "Scores: recencyScore: " + recencyScore
- + " usageTimeScore: " + usageTimeScore
- + " launchCountScore: " + launchCountScore
- + " - " + target);
+ Log.d(TAG, "Scores: " + target);
}
}
}
@@ -215,17 +225,11 @@
final ScoredTarget rhsTarget = mScoredTargets.get(new ComponentName(
rhs.activityInfo.packageName, rhs.activityInfo.name));
- final int chooserCountDiff = Long.compare(
- rhsTarget.chooserCount, lhsTarget.chooserCount);
+ final int selectProbDiff = Float.compare(
+ rhsTarget.selectProb, lhsTarget.selectProb);
- if (chooserCountDiff != 0) {
- return chooserCountDiff > 0 ? 1 : -1;
- }
-
- final int diff = Float.compare(rhsTarget.score, lhsTarget.score);
-
- if (diff != 0) {
- return diff > 0 ? 1 : -1;
+ if (selectProbDiff != 0) {
+ return selectProbDiff > 0 ? 1 : -1;
}
}
}
@@ -241,32 +245,160 @@
public float getScore(ComponentName name) {
final ScoredTarget target = mScoredTargets.get(name);
if (target != null) {
- return target.score;
+ return target.selectProb;
}
return 0;
}
static class ScoredTarget {
public final ComponentInfo componentInfo;
- public float score;
public long lastTimeUsed;
public long timeSpent;
public long launchCount;
public long chooserCount;
+ public ArrayMap<String, Float> features;
+ public float selectProb;
public ScoredTarget(ComponentInfo ci) {
componentInfo = ci;
+ features = new ArrayMap<>(5);
}
@Override
public String toString() {
return "ScoredTarget{" + componentInfo
- + " score: " + score
+ " lastTimeUsed: " + lastTimeUsed
+ " timeSpent: " + timeSpent
+ " launchCount: " + launchCount
+ " chooserCount: " + chooserCount
+ + " selectProb: " + selectProb
+ "}";
}
+
+ public void setFeatures(float launchCountScore, float usageTimeScore, float recencyScore,
+ float chooserCountScore) {
+ features.put(LAUNCH_SCORE, launchCountScore);
+ features.put(TIME_SPENT_SCORE, usageTimeScore);
+ features.put(RECENCY_SCORE, recencyScore);
+ features.put(CHOOSER_SCORE, chooserCountScore);
+ }
+
+ public ArrayMap<String, Float> getFeatures() {
+ return features;
+ }
+ }
+
+ public void updateModel(ComponentName componentName) {
+ if (mScoredTargets == null || componentName == null ||
+ !mScoredTargets.containsKey(componentName)) {
+ return;
+ }
+ ScoredTarget selected = mScoredTargets.get(componentName);
+ for (ComponentName targetComponent : mScoredTargets.keySet()) {
+ if (targetComponent.equals(componentName)) {
+ continue;
+ }
+ ScoredTarget target = mScoredTargets.get(targetComponent);
+ // A potential point of optimization. Save updates or derive a closed form for the
+ // positive case, to avoid calculating them repeatedly.
+ if (target.selectProb >= selected.selectProb) {
+ mRanker.update(target.getFeatures(), target.selectProb, false);
+ mRanker.update(selected.getFeatures(), selected.selectProb, true);
+ }
+ }
+ mRanker.commitUpdate();
+ }
+
+ class LogisticRegressionAppRanker {
+ private static final String PARAM_SHARED_PREF_NAME = "resolver_ranker_params";
+ private static final String BIAS_PREF_KEY = "bias";
+ private static final float LEARNING_RATE = 0.02f;
+ private static final float REGULARIZER_PARAM = 0.1f;
+ private SharedPreferences mParamSharedPref;
+ private ArrayMap<String, Float> mFeatureWeights;
+ private float mBias;
+
+ public LogisticRegressionAppRanker(Context context) {
+ mParamSharedPref = getParamSharedPref(context);
+ }
+
+ public float predict(ArrayMap<String, Float> target) {
+ if (target == null || mParamSharedPref == null) {
+ return 0.0f;
+ }
+ final int featureSize = target.size();
+ if (featureSize == 0) {
+ return 0.0f;
+ }
+ float sum = 0.0f;
+ if (mFeatureWeights == null) {
+ mBias = mParamSharedPref.getFloat(BIAS_PREF_KEY, 0.0f);
+ mFeatureWeights = new ArrayMap<>(featureSize);
+ for (int i = 0; i < featureSize; i++) {
+ String featureName = target.keyAt(i);
+ float weight = mParamSharedPref.getFloat(featureName, 0.0f);
+ sum += weight * target.valueAt(i);
+ mFeatureWeights.put(featureName, weight);
+ }
+ } else {
+ for (int i = 0; i < featureSize; i++) {
+ String featureName = target.keyAt(i);
+ float weight = mFeatureWeights.getOrDefault(featureName, 0.0f);
+ sum += weight * target.valueAt(i);
+ }
+ }
+ return (float) (1.0 / (1.0 + Math.exp(-mBias - sum)));
+ }
+
+ public void update(ArrayMap<String, Float> target, float predict, boolean isSelected) {
+ if (target == null || target.size() == 0) {
+ return;
+ }
+ final int featureSize = target.size();
+ if (mFeatureWeights == null) {
+ mBias = 0.0f;
+ mFeatureWeights = new ArrayMap<>(featureSize);
+ }
+ float error = isSelected ? 1.0f - predict : -predict;
+ for (int i = 0; i < featureSize; i++) {
+ String featureName = target.keyAt(i);
+ float currentWeight = mFeatureWeights.getOrDefault(featureName, 0.0f);
+ mBias += LEARNING_RATE * error;
+ currentWeight = currentWeight - LEARNING_RATE * REGULARIZER_PARAM * currentWeight +
+ LEARNING_RATE * error * target.valueAt(i);
+ mFeatureWeights.put(featureName, currentWeight);
+ }
+ if (DEBUG) {
+ Log.d(TAG, "Weights: " + mFeatureWeights + " Bias: " + mBias);
+ }
+ }
+
+ public void commitUpdate() {
+ if (mFeatureWeights == null || mFeatureWeights.size() == 0) {
+ return;
+ }
+ SharedPreferences.Editor editor = mParamSharedPref.edit();
+ editor.putFloat(BIAS_PREF_KEY, mBias);
+ final int size = mFeatureWeights.size();
+ for (int i = 0; i < size; i++) {
+ editor.putFloat(mFeatureWeights.keyAt(i), mFeatureWeights.valueAt(i));
+ }
+ editor.apply();
+ }
+
+ private SharedPreferences getParamSharedPref(Context context) {
+ // The package info in the context isn't initialized in the way it is for normal apps,
+ // so the standard, name-based context.getSharedPreferences doesn't work. Instead, we
+ // build the path manually below using the same policy that appears in ContextImpl.
+ if (DEBUG) {
+ Log.d(TAG, "Context Package Name: " + context.getPackageName());
+ }
+ final File prefsFile = new File(new File(
+ Environment.getDataUserCePackageDirectory(StorageManager.UUID_PRIVATE_INTERNAL,
+ context.getUserId(), context.getPackageName()),
+ "shared_prefs"),
+ PARAM_SHARED_PREF_NAME + ".xml");
+ return context.getSharedPreferences(prefsFile, Context.MODE_PRIVATE);
+ }
}
}
diff --git a/core/java/com/android/internal/app/ResolverListController.java b/core/java/com/android/internal/app/ResolverListController.java
new file mode 100644
index 0000000..d864a31
--- /dev/null
+++ b/core/java/com/android/internal/app/ResolverListController.java
@@ -0,0 +1,227 @@
+/*
+ * Copyright (C) 2016 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.annotation.WorkerThread;
+import android.app.ActivityManager;
+import android.content.ComponentName;
+import android.content.Context;
+import android.content.Intent;
+import android.content.pm.ActivityInfo;
+import android.content.pm.ApplicationInfo;
+import android.content.pm.PackageManager;
+import android.content.pm.ResolveInfo;
+import android.util.Log;
+import com.android.internal.annotations.VisibleForTesting;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+
+/**
+ * A helper for the ResolverActivity that exposes methods to retrieve, filter and sort its list of
+ * resolvers.
+ */
+public class ResolverListController {
+
+ private final Context mContext;
+ private final PackageManager mpm;
+ private final int mLaunchedFromUid;
+
+ // Needed for sorting resolvers.
+ private final Intent mTargetIntent;
+ private final String mReferrerPackage;
+
+ private static final String TAG = "ResolverListController";
+ private static final boolean DEBUG = false;
+
+ private ResolverComparator mResolverComparator;
+
+ public ResolverListController(
+ Context context,
+ PackageManager pm,
+ Intent targetIntent,
+ String referrerPackage,
+ int launchedFromUid) {
+ mContext = context;
+ mpm = pm;
+ mLaunchedFromUid = launchedFromUid;
+ mTargetIntent = targetIntent;
+ mReferrerPackage = referrerPackage;
+ }
+
+ @VisibleForTesting
+ public List<ResolverActivity.ResolvedComponentInfo> getResolversForIntent(
+ boolean shouldGetResolvedFilter,
+ boolean shouldGetActivityMetadata,
+ List<Intent> intents) {
+ List<ResolverActivity.ResolvedComponentInfo> resolvedComponents = null;
+ for (int i = 0, N = intents.size(); i < N; i++) {
+ final Intent intent = intents.get(i);
+ final List<ResolveInfo> infos = mpm.queryIntentActivities(intent,
+ PackageManager.MATCH_DEFAULT_ONLY
+ | (shouldGetResolvedFilter ? PackageManager.GET_RESOLVED_FILTER : 0)
+ | (shouldGetActivityMetadata ? PackageManager.GET_META_DATA : 0));
+ if (infos != null) {
+ if (resolvedComponents == null) {
+ resolvedComponents = new ArrayList<>();
+ }
+ addResolveListDedupe(resolvedComponents, intent, infos);
+ }
+ }
+ return resolvedComponents;
+ }
+
+ @VisibleForTesting
+ public void addResolveListDedupe(List<ResolverActivity.ResolvedComponentInfo> into,
+ Intent intent,
+ List<ResolveInfo> from) {
+ final int fromCount = from.size();
+ final int intoCount = into.size();
+ for (int i = 0; i < fromCount; i++) {
+ final ResolveInfo newInfo = from.get(i);
+ boolean found = false;
+ // Only loop to the end of into as it was before we started; no dupes in from.
+ for (int j = 0; j < intoCount; j++) {
+ final ResolverActivity.ResolvedComponentInfo rci = into.get(j);
+ if (isSameResolvedComponent(newInfo, rci)) {
+ found = true;
+ rci.add(intent, newInfo);
+ break;
+ }
+ }
+ if (!found) {
+ final ComponentName name = new ComponentName(
+ newInfo.activityInfo.packageName, newInfo.activityInfo.name);
+ final ResolverActivity.ResolvedComponentInfo rci =
+ new ResolverActivity.ResolvedComponentInfo(name, intent, newInfo);
+ rci.setPinned(isComponentPinned(name));
+ into.add(rci);
+ }
+ }
+ }
+
+ // Filter out any activities that the launched uid does not have permission for.
+ //
+ // Also filter out those that are suspended because they couldn't be started. We don't do this
+ // when we have an explicit list of resolved activities, because that only happens when
+ // we are being subclassed, so we can safely launch whatever they gave us.
+ //
+ // To preserve the inputList, optionally will return the original list if any modification has
+ // been made.
+ @VisibleForTesting
+ public ArrayList<ResolverActivity.ResolvedComponentInfo> filterIneligibleActivities(
+ List<ResolverActivity.ResolvedComponentInfo> inputList,
+ boolean returnCopyOfOriginalListIfModified) {
+ ArrayList<ResolverActivity.ResolvedComponentInfo> listToReturn = null;
+ for (int i = inputList.size()-1; i >= 0; i--) {
+ ActivityInfo ai = inputList.get(i)
+ .getResolveInfoAt(0).activityInfo;
+ int granted = ActivityManager.checkComponentPermission(
+ ai.permission, mLaunchedFromUid,
+ ai.applicationInfo.uid, ai.exported);
+ boolean suspended = (ai.applicationInfo.flags
+ & ApplicationInfo.FLAG_SUSPENDED) != 0;
+ if (granted != PackageManager.PERMISSION_GRANTED || suspended
+ || isComponentFiltered(ai.getComponentName())) {
+ // Access not allowed! We're about to filter an item,
+ // so modify the unfiltered version if it hasn't already been modified.
+ if (returnCopyOfOriginalListIfModified && listToReturn == null) {
+ listToReturn = new ArrayList<>(inputList);
+ }
+ inputList.remove(i);
+ }
+ }
+ return listToReturn;
+ }
+
+ // Filter out any low priority items.
+ //
+ // To preserve the inputList, optionally will return the original list if any modification has
+ // been made.
+ @VisibleForTesting
+ public ArrayList<ResolverActivity.ResolvedComponentInfo> filterLowPriority(
+ List<ResolverActivity.ResolvedComponentInfo> inputList,
+ boolean returnCopyOfOriginalListIfModified) {
+ ArrayList<ResolverActivity.ResolvedComponentInfo> listToReturn = null;
+ // Only display the first matches that are either of equal
+ // priority or have asked to be default options.
+ ResolverActivity.ResolvedComponentInfo rci0 = inputList.get(0);
+ ResolveInfo r0 = rci0.getResolveInfoAt(0);
+ int N = inputList.size();
+ for (int i = 1; i < N; i++) {
+ ResolveInfo ri = inputList.get(i).getResolveInfoAt(0);
+ if (DEBUG) Log.v(
+ TAG,
+ r0.activityInfo.name + "=" +
+ r0.priority + "/" + r0.isDefault + " vs " +
+ ri.activityInfo.name + "=" +
+ ri.priority + "/" + ri.isDefault);
+ if (r0.priority != ri.priority ||
+ r0.isDefault != ri.isDefault) {
+ while (i < N) {
+ if (returnCopyOfOriginalListIfModified && listToReturn == null) {
+ listToReturn = new ArrayList<>(inputList);
+ }
+ inputList.remove(i);
+ N--;
+ }
+ }
+ }
+ return listToReturn;
+ }
+
+ @VisibleForTesting
+ @WorkerThread
+ public void sort(List<ResolverActivity.ResolvedComponentInfo> inputList) {
+ if (mResolverComparator == null) {
+ mResolverComparator = new ResolverComparator(mContext, mTargetIntent, mReferrerPackage);
+ }
+ mResolverComparator.compute(inputList);
+ Collections.sort(inputList, mResolverComparator);
+ }
+
+ private static boolean isSameResolvedComponent(ResolveInfo a,
+ ResolverActivity.ResolvedComponentInfo b) {
+ final ActivityInfo ai = a.activityInfo;
+ return ai.packageName.equals(b.name.getPackageName())
+ && ai.name.equals(b.name.getClassName());
+ }
+
+ boolean isComponentPinned(ComponentName name) {
+ return false;
+ }
+
+ boolean isComponentFiltered(ComponentName componentName) {
+ return false;
+ }
+
+ @VisibleForTesting
+ public float getScore(ResolverActivity.DisplayResolveInfo target) {
+ if (mResolverComparator == null) {
+ mResolverComparator = new ResolverComparator(mContext, mTargetIntent, mReferrerPackage);
+ }
+ return mResolverComparator.getScore(target.getResolvedComponentName());
+ }
+
+ public void updateModel(ComponentName componentName) {
+ if (mResolverComparator != null) {
+ mResolverComparator.updateModel(componentName);
+ }
+ }
+}
diff --git a/core/java/com/android/internal/appwidget/IAppWidgetService.aidl b/core/java/com/android/internal/appwidget/IAppWidgetService.aidl
index 951a45a..a1eac36 100644
--- a/core/java/com/android/internal/appwidget/IAppWidgetService.aidl
+++ b/core/java/com/android/internal/appwidget/IAppWidgetService.aidl
@@ -67,5 +67,7 @@
void unbindRemoteViewsService(String callingPackage, int appWidgetId, in Intent intent);
int[] getAppWidgetIds(in ComponentName providerComponent);
boolean isBoundWidgetPackage(String packageName, int userId);
+ boolean requestPinAppWidget(String packageName, in ComponentName providerComponent,
+ in IntentSender resultIntent);
}
diff --git a/core/java/com/android/internal/logging/EventLogTags.logtags b/core/java/com/android/internal/logging/EventLogTags.logtags
index 4364cc3..93d5a03 100644
--- a/core/java/com/android/internal/logging/EventLogTags.logtags
+++ b/core/java/com/android/internal/logging/EventLogTags.logtags
@@ -5,5 +5,6 @@
# interaction logs
524287 sysui_view_visibility (category|1|5),(visible|1|6)
524288 sysui_action (category|1|5),(pkg|3)
+524292 sysui_multi_action (content|4)
524290 sysui_count (name|3),(increment|1)
524291 sysui_histogram (name|3),(bucket|1)
diff --git a/core/java/com/android/internal/logging/LogBuilder.java b/core/java/com/android/internal/logging/LogBuilder.java
new file mode 100644
index 0000000..634d061
--- /dev/null
+++ b/core/java/com/android/internal/logging/LogBuilder.java
@@ -0,0 +1,67 @@
+package com.android.internal.logging;
+
+import android.util.EventLog;
+import android.util.SparseArray;
+import android.view.View;
+
+import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
+
+
+/**
+ * Helper class to assemble more complex logs.
+ *
+ * @hide
+ */
+
+public class LogBuilder {
+
+ private SparseArray<Object> entries = new SparseArray();
+
+ public LogBuilder() {}
+
+
+ public LogBuilder setView(View view) {
+ entries.put(MetricsEvent.RESERVED_FOR_LOGBUILDER_VIEW, view.getId());
+ return this;
+ }
+
+ public LogBuilder setCategory(int category) {
+ entries.put(MetricsEvent.RESERVED_FOR_LOGBUILDER_CATEGORY, category);
+ return this;
+ }
+
+ public LogBuilder setType(int type) {
+ entries.put(MetricsEvent.RESERVED_FOR_LOGBUILDER_TYPE, type);
+ return this;
+ }
+
+ /**
+ * @param tag From your MetricsEvent enum.
+ * @param value One of Integer, Long, Float, String
+ * @return
+ */
+ public LogBuilder addTaggedData(int tag, Object value) {
+ if (!(value instanceof Integer ||
+ value instanceof String ||
+ value instanceof Long ||
+ value instanceof Float)) {
+ throw new IllegalArgumentException(
+ "Value must be loggable type - int, long, float, String");
+ }
+ entries.put(tag, value);
+ return this;
+ }
+
+ /**
+ * Assemble logs into structure suitable for EventLog.
+ */
+ public Object[] serialize() {
+ Object[] out = new Object[entries.size() * 2];
+ for (int i = 0; i < entries.size(); i++) {
+ out[i * 2] = entries.keyAt(i);
+ out[i * 2 + 1] = entries.valueAt(i);
+ }
+ return out;
+ }
+}
+
diff --git a/core/java/com/android/internal/logging/MetricsLogger.java b/core/java/com/android/internal/logging/MetricsLogger.java
index a94f308..5eb39ae 100644
--- a/core/java/com/android/internal/logging/MetricsLogger.java
+++ b/core/java/com/android/internal/logging/MetricsLogger.java
@@ -17,10 +17,12 @@
import android.content.Context;
import android.os.Build;
+import android.util.EventLog;
import android.view.View;
import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
+
/**
* Log all the things.
*
@@ -71,6 +73,14 @@
action(context, category, Boolean.toString(value));
}
+ public static void action(LogBuilder content) {
+ //EventLog.writeEvent(524292, content.serialize());
+ // Below would be the *right* way to do this, using the generated
+ // EventLogTags method, but that doesn't work.
+ EventLogTags.writeSysuiMultiAction(content.serialize());
+ }
+
+
public static void action(Context context, int category, String pkg) {
if (Build.IS_DEBUGGABLE && category == VIEW_UNKNOWN) {
throw new IllegalArgumentException("Must define metric category");
diff --git a/core/java/com/android/internal/os/BatteryStatsImpl.java b/core/java/com/android/internal/os/BatteryStatsImpl.java
index 6a5bbcc..5fd68e6 100644
--- a/core/java/com/android/internal/os/BatteryStatsImpl.java
+++ b/core/java/com/android/internal/os/BatteryStatsImpl.java
@@ -559,6 +559,10 @@
private int mEstimatedBatteryCapacity = -1;
+ // Last learned capacity reported by BatteryService in
+ // setBatteryState().
+ private int mLastChargeFullUAh = 0;
+
private final NetworkStats.Entry mTmpNetworkStatsEntry = new NetworkStats.Entry();
private PowerProfile mPowerProfile;
@@ -6912,6 +6916,8 @@
final int mHandle;
StopwatchTimer mTimer;
+ Counter mBgCounter;
+
public Sensor(BatteryStatsImpl bsi, Uid uid, int handle) {
mBsi = bsi;
mUid = uid;
@@ -6931,7 +6937,17 @@
return new StopwatchTimer(mBsi.mClocks, mUid, 0, pool, timeBase, in);
}
+ private Counter readCounterFromParcel(TimeBase timeBase, Parcel in) {
+ if (in.readInt() == 0) {
+ return null;
+ }
+ return new Counter(timeBase, in);
+ }
+
boolean reset() {
+ if (mBgCounter != null) {
+ mBgCounter.reset(true);
+ }
if (mTimer.reset(true)) {
mTimer = null;
return true;
@@ -6941,10 +6957,12 @@
void readFromParcelLocked(TimeBase timeBase, Parcel in) {
mTimer = readTimerFromParcel(timeBase, in);
+ mBgCounter = readCounterFromParcel(timeBase, in);
}
void writeToParcelLocked(Parcel out, long elapsedRealtimeUs) {
Timer.writeTimerToParcel(out, mTimer, elapsedRealtimeUs);
+ Counter.writeCounterToParcel(out, mBgCounter);
}
@Override
@@ -6953,6 +6971,11 @@
}
@Override
+ public Counter getSensorBgCount() {
+ return mBgCounter;
+ }
+
+ @Override
public int getHandle() {
return mHandle;
}
@@ -7795,6 +7818,22 @@
return t;
}
+ public Counter getSensorBgCounterLocked(int sensor, boolean create) {
+ Sensor se = mSensorStats.get(sensor);
+ if (se == null) {
+ if (!create) {
+ return null;
+ }
+ se = new Sensor(mBsi, this, sensor);
+ mSensorStats.put(sensor, se);
+ }
+ Counter c = se.mBgCounter;
+ if (c != null) return c;
+ c = new Counter(mBsi.mOnBatteryTimeBase);
+ se.mBgCounter = c;
+ return c;
+ }
+
public void noteStartSyncLocked(String name, long elapsedRealtimeMs) {
StopwatchTimer t = mSyncStats.startObject(name);
if (t != null) {
@@ -7871,6 +7910,10 @@
if (t != null) {
t.startRunningLocked(elapsedRealtimeMs);
}
+ Counter c = getSensorBgCounterLocked(sensor, true);
+ if (c != null && mProcessState >= PROCESS_STATE_BACKGROUND) {
+ c.stepAtomic();
+ }
}
public void noteStopSensor(int sensor, long elapsedRealtimeMs) {
@@ -7886,6 +7929,10 @@
if (t != null) {
t.startRunningLocked(elapsedRealtimeMs);
}
+ Counter c = getSensorBgCounterLocked(Sensor.GPS, true);
+ if (c != null && mProcessState >= PROCESS_STATE_BACKGROUND) {
+ c.stepAtomic();
+ }
}
public void noteStopGps(long elapsedRealtimeMs) {
@@ -9775,7 +9822,7 @@
public static final int BATTERY_PLUGGED_NONE = 0;
public void setBatteryStateLocked(int status, int health, int plugType, int level,
- int temp, int volt, int chargeUAh) {
+ int temp, int volt, int chargeUAh, int chargeFullUAh) {
final boolean onBattery = plugType == BATTERY_PLUGGED_NONE;
final long uptime = mClocks.uptimeMillis();
final long elapsedRealtime = mClocks.elapsedRealtime();
@@ -9937,6 +9984,16 @@
// The next time we are unplugged, history will be cleared.
mRecordingHistory = DEBUG;
}
+
+ if (differsByMoreThan(chargeFullUAh, mLastChargeFullUAh, 100)) {
+ mLastChargeFullUAh = chargeFullUAh;
+ addHistoryEventLocked(elapsedRealtime, uptime, HistoryItem.EVENT_ESTIMATED_BATTERY_CAP,
+ "", chargeFullUAh / 1000);
+ }
+ }
+
+ private static boolean differsByMoreThan(int left, int right, int diff) {
+ return Math.abs(left - right) > diff;
}
public long getAwakeTimeBattery() {
diff --git a/core/java/com/android/internal/os/WebViewZygoteInit.java b/core/java/com/android/internal/os/WebViewZygoteInit.java
index a8a5549..12d699d 100644
--- a/core/java/com/android/internal/os/WebViewZygoteInit.java
+++ b/core/java/com/android/internal/os/WebViewZygoteInit.java
@@ -54,6 +54,11 @@
}
@Override
+ protected void maybePreload() {
+ // Do nothing, we don't need to call ZygoteInit.maybePreload() for the WebView zygote.
+ }
+
+ @Override
protected boolean handlePreloadPackage(String packagePath, String libsPath) {
// Ask ApplicationLoaders to create and cache a classloader for the WebView APK so that
// our children will reuse the same classloader instead of creating their own.
diff --git a/core/java/com/android/internal/os/ZygoteConnection.java b/core/java/com/android/internal/os/ZygoteConnection.java
index e9e642a..345350c 100644
--- a/core/java/com/android/internal/os/ZygoteConnection.java
+++ b/core/java/com/android/internal/os/ZygoteConnection.java
@@ -171,7 +171,7 @@
return handleAbiListQuery();
}
- ZygoteInit.maybePreload();
+ maybePreload();
if (parsedArgs.preloadPackage != null) {
return handlePreloadPackage(parsedArgs.preloadPackage,
@@ -279,6 +279,10 @@
}
}
+ protected void maybePreload() {
+ ZygoteInit.maybePreload();
+ }
+
protected boolean handlePreloadPackage(String packagePath, String libsPath) {
throw new RuntimeException("Zyogte does not support package preloading");
}
diff --git a/core/java/com/android/internal/os/ZygoteInit.java b/core/java/com/android/internal/os/ZygoteInit.java
index f47784e..8eb75c0 100644
--- a/core/java/com/android/internal/os/ZygoteInit.java
+++ b/core/java/com/android/internal/os/ZygoteInit.java
@@ -657,8 +657,11 @@
}
try {
- // Report Zygote start time to tron
- MetricsLogger.histogram(null, "boot_zygote_init", (int) SystemClock.uptimeMillis());
+ // Report Zygote start time to tron unless it is a runtime restart
+ if (!"1".equals(SystemProperties.get("sys.boot_completed"))) {
+ MetricsLogger.histogram(null, "boot_zygote_init",
+ (int) SystemClock.elapsedRealtime());
+ }
String bootTimeTag = Process.is64Bit() ? "Zygote64Timing" : "Zygote32Timing";
BootTimingsTraceLog bootTimingsTraceLog = new BootTimingsTraceLog(bootTimeTag,
diff --git a/core/java/com/android/internal/policy/DecorView.java b/core/java/com/android/internal/policy/DecorView.java
index eb143e8..789e9d4 100644
--- a/core/java/com/android/internal/policy/DecorView.java
+++ b/core/java/com/android/internal/policy/DecorView.java
@@ -96,6 +96,7 @@
import static android.view.WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS;
import static android.view.WindowManager.LayoutParams.FLAG_FULLSCREEN;
import static android.view.WindowManager.LayoutParams.FLAG_LAYOUT_INSET_DECOR;
+import static android.view.WindowManager.LayoutParams.FLAG_LAYOUT_IN_OVERSCAN;
import static android.view.WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN;
import static android.view.WindowManager.LayoutParams.FLAG_TRANSLUCENT_NAVIGATION;
import static android.view.WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS;
@@ -969,7 +970,7 @@
mFrameOffsets.set(insets.getSystemWindowInsets());
insets = updateColorViews(insets, true /* animate */);
insets = updateStatusGuard(insets);
- updateNavigationGuard(insets);
+ insets = updateNavigationGuard(insets);
if (getForeground() != null) {
drawableChanged();
}
@@ -1329,9 +1330,11 @@
return insets;
}
- private void updateNavigationGuard(WindowInsets insets) {
- // IMEs lay out below the nav bar, but the content view must not (for back compat)
- if (mWindow.getAttributes().type == WindowManager.LayoutParams.TYPE_INPUT_METHOD) {
+ private WindowInsets updateNavigationGuard(WindowInsets insets) {
+ // IME windows lay out below the nav bar, but the content view must not (for back compat)
+ // Only make this adjustment if the window is not requesting layout in overscan
+ if (mWindow.getAttributes().type == WindowManager.LayoutParams.TYPE_INPUT_METHOD
+ && (mWindow.getAttributes().flags & FLAG_LAYOUT_IN_OVERSCAN) == 0) {
// prevent the content view from including the nav bar height
if (mWindow.mContentParent != null) {
if (mWindow.mContentParent.getLayoutParams() instanceof MarginLayoutParams) {
@@ -1356,7 +1359,10 @@
mNavigationGuard.setLayoutParams(lp);
}
updateNavigationGuardColor();
+ insets = insets.consumeSystemWindowInsets(
+ false, false, false, true /* bottom */);
}
+ return insets;
}
void updateNavigationGuardColor() {
diff --git a/core/java/com/android/internal/policy/PipSnapAlgorithm.java b/core/java/com/android/internal/policy/PipSnapAlgorithm.java
index 62d506f..4dd3360 100644
--- a/core/java/com/android/internal/policy/PipSnapAlgorithm.java
+++ b/core/java/com/android/internal/policy/PipSnapAlgorithm.java
@@ -21,7 +21,6 @@
import android.graphics.Point;
import android.graphics.PointF;
import android.graphics.Rect;
-import android.hardware.display.DisplayManager;
import android.view.Gravity;
import android.view.ViewConfiguration;
import android.widget.Scroller;
@@ -44,9 +43,6 @@
// The friction multiplier to control how slippery the PIP is when flung
private static final float SCROLL_FRICTION_MULTIPLIER = 8f;
- // The fraction of the stack width to show when minimized
- private static final float MINIMIZED_VISIBLE_FRACTION = 0.25f;
-
private final Context mContext;
private final ArrayList<Integer> mSnapGravities = new ArrayList<>();
@@ -56,8 +52,12 @@
private Scroller mScroller;
private int mOrientation = Configuration.ORIENTATION_UNDEFINED;
+ private final int mMinimizedVisibleSize;
+
public PipSnapAlgorithm(Context context) {
mContext = context;
+ mMinimizedVisibleSize = context.getResources().getDimensionPixelSize(
+ com.android.internal.R.dimen.pip_minimized_visible_size);
onConfigurationChanged();
}
@@ -129,11 +129,10 @@
* Applies the offset to the {@param stackBounds} to adjust it to a minimized state.
*/
public void applyMinimizedOffset(Rect stackBounds, Rect movementBounds, Point displaySize) {
- int visibleWidth = (int) (MINIMIZED_VISIBLE_FRACTION * stackBounds.width());
if (stackBounds.left <= movementBounds.centerX()) {
- stackBounds.offsetTo(-stackBounds.width() + visibleWidth, stackBounds.top);
+ stackBounds.offsetTo(-stackBounds.width() + mMinimizedVisibleSize, stackBounds.top);
} else {
- stackBounds.offsetTo(displaySize.x - visibleWidth, stackBounds.top);
+ stackBounds.offsetTo(displaySize.x - mMinimizedVisibleSize, stackBounds.top);
}
}
@@ -220,15 +219,23 @@
* the new bounds out to {@param boundsOut}.
*/
private void snapRectToClosestEdge(Rect stackBounds, Rect movementBounds, Rect boundsOut) {
- final int fromLeft = Math.abs(stackBounds.left - movementBounds.left);
- final int fromTop = Math.abs(stackBounds.top - movementBounds.top);
- final int fromRight = Math.abs(movementBounds.right - stackBounds.left);
- final int fromBottom = Math.abs(movementBounds.bottom - stackBounds.top);
+ // If the stackBounds are minimized, then it should only be snapped back horizontally
final int boundedLeft = Math.max(movementBounds.left, Math.min(movementBounds.right,
stackBounds.left));
final int boundedTop = Math.max(movementBounds.top, Math.min(movementBounds.bottom,
stackBounds.top));
boundsOut.set(stackBounds);
+ if (stackBounds.left < movementBounds.left ||
+ stackBounds.left > movementBounds.right) {
+ boundsOut.offsetTo(boundedLeft, boundsOut.top);
+ return;
+ }
+
+ // Otherwise, just find the closest edge
+ final int fromLeft = Math.abs(stackBounds.left - movementBounds.left);
+ final int fromTop = Math.abs(stackBounds.top - movementBounds.top);
+ final int fromRight = Math.abs(movementBounds.right - stackBounds.left);
+ final int fromBottom = Math.abs(movementBounds.bottom - stackBounds.top);
if (fromLeft <= fromTop && fromLeft <= fromRight && fromLeft <= fromBottom) {
boundsOut.offsetTo(movementBounds.left, boundedTop);
} else if (fromTop <= fromLeft && fromTop <= fromRight && fromTop <= fromBottom) {
diff --git a/core/java/com/android/internal/util/ConcurrentUtils.java b/core/java/com/android/internal/util/ConcurrentUtils.java
new file mode 100644
index 0000000..e35f9f4
--- /dev/null
+++ b/core/java/com/android/internal/util/ConcurrentUtils.java
@@ -0,0 +1,89 @@
+/*
+ * Copyright (C) 2016 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.util;
+
+import android.os.Process;
+
+import java.util.concurrent.ExecutionException;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Executors;
+import java.util.concurrent.Future;
+import java.util.concurrent.ThreadFactory;
+import java.util.concurrent.atomic.AtomicInteger;
+
+/**
+ * Utility methods for common functionality using java.util.concurrent package
+ *
+ * @hide
+ */
+public class ConcurrentUtils {
+
+ private ConcurrentUtils() {
+ }
+
+ /**
+ * Creates a thread pool using
+ * {@link java.util.concurrent.Executors#newFixedThreadPool(int, ThreadFactory)}
+ *
+ * @param nThreads the number of threads in the pool
+ * @param poolName base name of the threads in the pool
+ * @param linuxThreadPriority a Linux priority level. see {@link Process#setThreadPriority(int)}
+ * @return the newly created thread pool
+ */
+ public static ExecutorService newFixedThreadPool(int nThreads, String poolName,
+ int linuxThreadPriority) {
+ return Executors.newFixedThreadPool(nThreads,
+ new ThreadFactory() {
+ private final AtomicInteger threadNum = new AtomicInteger(0);
+
+ @Override
+ public Thread newThread(final Runnable r) {
+ return new Thread(poolName + threadNum.incrementAndGet()) {
+ @Override
+ public void run() {
+ Process.setThreadPriority(linuxThreadPriority);
+ r.run();
+ }
+ };
+ }
+ });
+ }
+
+ /**
+ * Waits if necessary for the computation to complete, and then retrieves its result.
+ * <p>If {@code InterruptedException} occurs, this method will interrupt the current thread
+ * and throw {@code IllegalStateException}</p>
+ *
+ * @param future future to wait for result
+ * @param description short description of the operation
+ * @return the computed result
+ * @throws IllegalStateException if interrupted during wait
+ * @throws RuntimeException if an error occurs while waiting for {@link Future#get()}
+ * @see Future#get()
+ */
+ public static <T> T waitForFutureNoInterrupt(Future<T> future, String description) {
+ try {
+ return future.get();
+ } catch (InterruptedException e) {
+ Thread.currentThread().interrupt();
+ throw new IllegalStateException(description + " interrupted");
+ } catch (ExecutionException e) {
+ throw new RuntimeException(description + " failed", e);
+ }
+ }
+
+}
diff --git a/core/java/com/android/internal/view/TooltipPopup.java b/core/java/com/android/internal/view/TooltipPopup.java
index c5f6356..ebbbdbb 100644
--- a/core/java/com/android/internal/view/TooltipPopup.java
+++ b/core/java/com/android/internal/view/TooltipPopup.java
@@ -19,13 +19,17 @@
import android.content.Context;
import android.graphics.PixelFormat;
import android.graphics.Rect;
+import android.util.Slog;
import android.view.Gravity;
import android.view.LayoutInflater;
import android.view.View;
import android.view.WindowManager;
+import android.view.WindowManagerGlobal;
import android.widget.TextView;
public class TooltipPopup {
+ private static final String TAG = "TooltipPopup";
+
private final Context mContext;
private final View mContentView;
@@ -34,6 +38,7 @@
private final WindowManager.LayoutParams mLayoutParams = new WindowManager.LayoutParams();
private final Rect mTmpDisplayFrame = new Rect();
private final int[] mTmpAnchorPos = new int[2];
+ private final int[] mTmpAppPos = new int[2];
public TooltipPopup(Context context) {
mContext = context;
@@ -124,8 +129,21 @@
fromTouch ? com.android.internal.R.dimen.tooltip_y_offset_touch
: com.android.internal.R.dimen.tooltip_y_offset_non_touch);
- anchorView.getWindowVisibleDisplayFrame(mTmpDisplayFrame);
- anchorView.getLocationInWindow(mTmpAnchorPos);
+ // Find the main app window. The popup window will be positioned relative to it.
+ final View appView = WindowManagerGlobal.getInstance().getWindowView(
+ anchorView.getApplicationWindowToken());
+ if (appView == null) {
+ Slog.e(TAG, "Cannot find app view");
+ return;
+ }
+ appView.getWindowVisibleDisplayFrame(mTmpDisplayFrame);
+ appView.getLocationOnScreen(mTmpAppPos);
+
+ anchorView.getLocationOnScreen(mTmpAnchorPos);
+ mTmpAnchorPos[0] -= mTmpAppPos[0];
+ mTmpAnchorPos[1] -= mTmpAppPos[1];
+ // mTmpAnchorPos is now relative to the main app window.
+
outParams.x = mTmpAnchorPos[0] + offsetX - mTmpDisplayFrame.width() / 2;
final int spec = View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED);
diff --git a/core/java/com/android/internal/view/menu/ActionMenuItem.java b/core/java/com/android/internal/view/menu/ActionMenuItem.java
index ed676bb..c8697dd 100644
--- a/core/java/com/android/internal/view/menu/ActionMenuItem.java
+++ b/core/java/com/android/internal/view/menu/ActionMenuItem.java
@@ -39,23 +39,26 @@
private Intent mIntent;
private char mShortcutNumericChar;
private char mShortcutAlphabeticChar;
-
+
private Drawable mIconDrawable;
private int mIconResId = NO_ICON;
-
+
private Context mContext;
-
+
private MenuItem.OnMenuItemClickListener mClickListener;
-
+
+ private CharSequence mContentDescription;
+ private CharSequence mTooltip;
+
private static final int NO_ICON = 0;
-
+
private int mFlags = ENABLED;
private static final int CHECKABLE = 0x00000001;
private static final int CHECKED = 0x00000002;
private static final int EXCLUSIVE = 0x00000004;
private static final int HIDDEN = 0x00000008;
private static final int ENABLED = 0x00000010;
-
+
public ActionMenuItem(Context context, int group, int id, int categoryOrder, int ordering,
CharSequence title) {
mContext = context;
@@ -65,7 +68,7 @@
mOrdering = ordering;
mTitle = title;
}
-
+
public char getAlphabeticShortcut() {
return mShortcutAlphabeticChar;
}
@@ -274,4 +277,26 @@
// No need to save the listener; ActionMenuItem does not support collapsing items.
return this;
}
+
+ @Override
+ public MenuItem setContentDescription(CharSequence contentDescription) {
+ mContentDescription = contentDescription;
+ return this;
+ }
+
+ @Override
+ public CharSequence getContentDescription() {
+ return mContentDescription;
+ }
+
+ @Override
+ public MenuItem setTooltip(CharSequence tooltip) {
+ mTooltip = tooltip;
+ return this;
+ }
+
+ @Override
+ public CharSequence getTooltip() {
+ return mTooltip;
+ }
}
diff --git a/core/java/com/android/internal/view/menu/ActionMenuItemView.java b/core/java/com/android/internal/view/menu/ActionMenuItemView.java
index af4f777..4ee5993 100644
--- a/core/java/com/android/internal/view/menu/ActionMenuItemView.java
+++ b/core/java/com/android/internal/view/menu/ActionMenuItemView.java
@@ -119,7 +119,7 @@
mItemData = itemData;
setIcon(itemData.getIcon());
- setTitle(itemData.getTitleForItemView(this)); // Title only takes effect if there is no icon
+ setTitle(itemData.getTitleForItemView(this)); // Title is only displayed if there is no icon
setId(itemData.getItemId());
setVisibility(itemData.isVisible() ? View.VISIBLE : View.GONE);
@@ -184,8 +184,22 @@
setText(visible ? mTitle : null);
- // Show the tooltip for items that do not already show text.
- setTooltip(visible ? null : mTitle);
+ final CharSequence contentDescription = mItemData.getContentDescription();
+ if (TextUtils.isEmpty(contentDescription)) {
+ // Use the uncondensed title for content description, but only if the title is not
+ // shown already.
+ setContentDescription(visible ? null : mItemData.getTitle());
+ } else {
+ setContentDescription(contentDescription);
+ }
+
+ final CharSequence tooltip = mItemData.getTooltip();
+ if (TextUtils.isEmpty(tooltip)) {
+ // Use the uncondensed title for tooltip, but only if the title is not shown already.
+ setTooltip(visible ? null : mItemData.getTitle());
+ } else {
+ setTooltip(tooltip);
+ }
}
public void setIcon(Drawable icon) {
@@ -221,7 +235,6 @@
public void setTitle(CharSequence title) {
mTitle = title;
- setContentDescription(mTitle);
updateTextButtonVisibility();
}
diff --git a/core/java/com/android/internal/view/menu/IconMenuItemView.java b/core/java/com/android/internal/view/menu/IconMenuItemView.java
index 0e0c9b0..f9ebdbc 100644
--- a/core/java/com/android/internal/view/menu/IconMenuItemView.java
+++ b/core/java/com/android/internal/view/menu/IconMenuItemView.java
@@ -22,6 +22,7 @@
import android.content.res.TypedArray;
import android.graphics.Rect;
import android.graphics.drawable.Drawable;
+import android.text.TextUtils;
import android.util.AttributeSet;
import android.view.Gravity;
import android.view.SoundEffectConstants;
@@ -31,7 +32,7 @@
import android.text.Layout;
/**
- * The item view for each item in the {@link IconMenuView}.
+ * The item view for each item in the {@link IconMenuView}.
*/
public final class IconMenuItemView extends TextView implements MenuView.ItemView {
@@ -104,13 +105,23 @@
setTitle(title);
setIcon(icon);
+
+ if (mItemData != null) {
+ final CharSequence contentDescription = mItemData.getContentDescription();
+ if (TextUtils.isEmpty(contentDescription)) {
+ setContentDescription(title);
+ } else {
+ setContentDescription(contentDescription);
+ }
+ setTooltip(mItemData.getTooltip());
+ }
}
-
+
public void initialize(MenuItemImpl itemData, int menuType) {
mItemData = itemData;
initialize(itemData.getTitleForItemView(this), itemData.getIcon());
-
+
setVisibility(itemData.isVisible() ? View.VISIBLE : View.GONE);
setEnabled(itemData.isEnabled());
}
diff --git a/core/java/com/android/internal/view/menu/ListMenuItemView.java b/core/java/com/android/internal/view/menu/ListMenuItemView.java
index 2526393..7c9f709 100644
--- a/core/java/com/android/internal/view/menu/ListMenuItemView.java
+++ b/core/java/com/android/internal/view/menu/ListMenuItemView.java
@@ -107,13 +107,15 @@
mMenuType = menuType;
setVisibility(itemData.isVisible() ? View.VISIBLE : View.GONE);
-
+
setTitle(itemData.getTitleForItemView(this));
setCheckable(itemData.isCheckable());
setShortcut(itemData.shouldShowShortcut(), itemData.getShortcut());
setIcon(itemData.getIcon());
setEnabled(itemData.isEnabled());
setSubMenuArrowVisible(itemData.hasSubMenu());
+ setContentDescription(itemData.getContentDescription());
+ setTooltip(itemData.getTooltip());
}
public void setForceShowIcon(boolean forceShow) {
diff --git a/core/java/com/android/internal/view/menu/MenuItemImpl.java b/core/java/com/android/internal/view/menu/MenuItemImpl.java
index 624c9e2..cad0276 100644
--- a/core/java/com/android/internal/view/menu/MenuItemImpl.java
+++ b/core/java/com/android/internal/view/menu/MenuItemImpl.java
@@ -90,16 +90,19 @@
/**
* Current use case is for context menu: Extra information linked to the
* View that added this item to the context menu.
- */
+ */
private ContextMenuInfo mMenuInfo;
-
+
+ private CharSequence mContentDescription;
+ private CharSequence mTooltip;
+
private static String sLanguage;
private static String sPrependShortcutLabel;
private static String sEnterShortcutLabel;
private static String sDeleteShortcutLabel;
private static String sSpaceShortcutLabel;
-
-
+
+
/**
* Instantiates this menu item.
*
@@ -670,4 +673,32 @@
public boolean isActionViewExpanded() {
return mIsActionViewExpanded;
}
+
+ @Override
+ public MenuItem setContentDescription(CharSequence contentDescription) {
+ mContentDescription = contentDescription;
+
+ mMenu.onItemsChanged(false);
+
+ return this;
+ }
+
+ @Override
+ public CharSequence getContentDescription() {
+ return mContentDescription;
+ }
+
+ @Override
+ public MenuItem setTooltip(CharSequence tooltip) {
+ mTooltip = tooltip;
+
+ mMenu.onItemsChanged(false);
+
+ return this;
+ }
+
+ @Override
+ public CharSequence getTooltip() {
+ return mTooltip;
+ }
}
diff --git a/core/java/com/android/internal/widget/FloatingToolbar.java b/core/java/com/android/internal/widget/FloatingToolbar.java
index 6604208..04e09a8 100644
--- a/core/java/com/android/internal/widget/FloatingToolbar.java
+++ b/core/java/com/android/internal/widget/FloatingToolbar.java
@@ -1585,7 +1585,13 @@
}
if (menuItem != null) {
menuButton.setText(menuItem.getTitle());
- menuButton.setContentDescription(menuItem.getTitle());
+ final CharSequence contentDescription = menuItem.getContentDescription();
+ if (TextUtils.isEmpty(contentDescription)) {
+ menuButton.setContentDescription(menuItem.getTitle());
+ } else {
+ menuButton.setContentDescription(contentDescription);
+ }
+ menuButton.setTooltip(menuItem.getTooltip());
menuButton.setMinimumWidth(minimumWidth);
}
return menuButton;
@@ -1629,19 +1635,31 @@
* Creates and returns a menu button for the specified menu item.
*/
private static View createMenuItemButton(Context context, MenuItem menuItem) {
+ final View menuItemButton;
if (isIconOnlyMenuItem(menuItem)) {
- View imageMenuItemButton = LayoutInflater.from(context)
+ menuItemButton = LayoutInflater.from(context)
.inflate(R.layout.floating_popup_menu_image_button, null);
- ((ImageButton) imageMenuItemButton
+ ((ImageButton) menuItemButton
.findViewById(R.id.floating_toolbar_menu_item_image_button))
.setImageDrawable(menuItem.getIcon());
- return imageMenuItemButton;
+ final CharSequence tooltip = menuItem.getTooltip();
+ if (TextUtils.isEmpty(tooltip)) {
+ menuItemButton.setTooltip(menuItem.getTitle());
+ } else {
+ menuItemButton.setTooltip(tooltip);
+ }
+ } else {
+ menuItemButton = LayoutInflater.from(context)
+ .inflate(R.layout.floating_popup_menu_button, null);
+ ((Button) menuItemButton).setText(menuItem.getTitle());
+ menuItemButton.setTooltip(menuItem.getTooltip());
}
-
- Button menuItemButton = (Button) LayoutInflater.from(context)
- .inflate(R.layout.floating_popup_menu_button, null);
- menuItemButton.setText(menuItem.getTitle());
- menuItemButton.setContentDescription(menuItem.getTitle());
+ final CharSequence contentDescription = menuItem.getContentDescription();
+ if (TextUtils.isEmpty(contentDescription)) {
+ menuItemButton.setContentDescription(menuItem.getTitle());
+ } else {
+ menuItemButton.setContentDescription(contentDescription);
+ }
return menuItemButton;
}
diff --git a/core/java/com/android/internal/widget/LockPatternView.java b/core/java/com/android/internal/widget/LockPatternView.java
index 96492e2..4ba19f4 100644
--- a/core/java/com/android/internal/widget/LockPatternView.java
+++ b/core/java/com/android/internal/widget/LockPatternView.java
@@ -24,6 +24,7 @@
import android.content.res.TypedArray;
import android.graphics.Canvas;
import android.graphics.CanvasProperty;
+import android.graphics.drawable.Drawable;
import android.graphics.Paint;
import android.graphics.Path;
import android.graphics.Rect;
@@ -143,6 +144,10 @@
private PatternExploreByTouchHelper mExploreByTouchHelper;
private AudioManager mAudioManager;
+ private Drawable mSelectedDrawable;
+ private Drawable mNotSelectedDrawable;
+ private boolean mUseLockPatternDrawable;
+
/**
* Represents a cell in the 3 X 3 matrix of the unlock pattern view.
*/
@@ -314,6 +319,12 @@
mDotSizeActivated = getResources().getDimensionPixelSize(
R.dimen.lock_pattern_dot_size_activated);
+ mUseLockPatternDrawable = getResources().getBoolean(R.bool.use_lock_pattern_drawable);
+ if (mUseLockPatternDrawable) {
+ mSelectedDrawable = getResources().getDrawable(R.drawable.lockscreen_selected);
+ mNotSelectedDrawable = getResources().getDrawable(R.drawable.lockscreen_notselected);
+ }
+
mPaint.setAntiAlias(true);
mPaint.setDither(true);
@@ -621,6 +632,11 @@
final int height = h - mPaddingTop - mPaddingBottom;
mSquareHeight = height / 3.0f;
mExploreByTouchHelper.invalidateRoot();
+
+ if (mUseLockPatternDrawable) {
+ mNotSelectedDrawable.setBounds(mPaddingLeft, mPaddingTop, width, height);
+ mSelectedDrawable.setBounds(mPaddingLeft, mPaddingTop, width, height);
+ }
}
private int resolveMeasured(int measureSpec, int desired)
@@ -1095,14 +1111,18 @@
CellState cellState = mCellStates[i][j];
float centerX = getCenterXForColumn(j);
float translationY = cellState.translationY;
- if (isHardwareAccelerated() && cellState.hwAnimating) {
- DisplayListCanvas displayListCanvas = (DisplayListCanvas) canvas;
- displayListCanvas.drawCircle(cellState.hwCenterX, cellState.hwCenterY,
- cellState.hwRadius, cellState.hwPaint);
- } else {
- drawCircle(canvas, (int) centerX, (int) centerY + translationY,
- cellState.radius, drawLookup[i][j], cellState.alpha);
+ if (mUseLockPatternDrawable) {
+ drawCellDrawable(canvas, i, j, cellState.radius, drawLookup[i][j]);
+ } else {
+ if (isHardwareAccelerated() && cellState.hwAnimating) {
+ DisplayListCanvas displayListCanvas = (DisplayListCanvas) canvas;
+ displayListCanvas.drawCircle(cellState.hwCenterX, cellState.hwCenterY,
+ cellState.hwRadius, cellState.hwPaint);
+ } else {
+ drawCircle(canvas, (int) centerX, (int) centerY + translationY,
+ cellState.radius, drawLookup[i][j], cellState.alpha);
+ }
}
}
}
@@ -1193,6 +1213,30 @@
canvas.drawCircle(centerX, centerY, radius, mPaint);
}
+ /**
+ * @param partOfPattern Whether this circle is part of the pattern.
+ */
+ private void drawCellDrawable(Canvas canvas, int i, int j, float radius,
+ boolean partOfPattern) {
+ Rect dst = new Rect(
+ (int) (mPaddingLeft + j * mSquareWidth),
+ (int) (mPaddingTop + i * mSquareHeight),
+ (int) (mPaddingLeft + (j + 1) * mSquareWidth),
+ (int) (mPaddingTop + (i + 1) * mSquareHeight));
+ float scale = radius / (mDotSize / 2);
+
+ // Only draw on this square with the appropriate scale.
+ canvas.save();
+ canvas.clipRect(dst);
+ canvas.scale(scale, scale, dst.centerX(), dst.centerY());
+ if (!partOfPattern || scale > 1) {
+ mNotSelectedDrawable.draw(canvas);
+ } else {
+ mSelectedDrawable.draw(canvas);
+ }
+ canvas.restore();
+ }
+
@Override
protected Parcelable onSaveInstanceState() {
Parcelable superState = super.onSaveInstanceState();
diff --git a/core/java/com/android/internal/widget/SwipeDismissLayout.java b/core/java/com/android/internal/widget/SwipeDismissLayout.java
index b5d6268..2a5957c 100644
--- a/core/java/com/android/internal/widget/SwipeDismissLayout.java
+++ b/core/java/com/android/internal/widget/SwipeDismissLayout.java
@@ -23,6 +23,7 @@
import android.app.Activity;
import android.content.BroadcastReceiver;
import android.content.Context;
+import android.content.ContextWrapper;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.res.TypedArray;
@@ -33,7 +34,6 @@
import android.view.View;
import android.view.ViewConfiguration;
import android.view.ViewGroup;
-import android.view.ViewTreeObserver;
import android.view.animation.DecelerateInterpolator;
import android.widget.FrameLayout;
@@ -44,7 +44,6 @@
private static final String TAG = "SwipeDismissLayout";
private static final float DISMISS_MIN_DRAG_WIDTH_RATIO = .33f;
- private boolean mUseDynamicTranslucency = true;
public interface OnDismissedListener {
void onDismissed(SwipeDismissLayout layout);
@@ -64,6 +63,8 @@
void onSwipeCancelled(SwipeDismissLayout layout);
}
+ private boolean mIsWindowNativelyTranslucent;
+
// Cached ViewConfiguration and system-wide constant values
private int mSlop;
private int mMinFlingVelocity;
@@ -78,24 +79,12 @@
private VelocityTracker mVelocityTracker;
private float mTranslationX;
private boolean mBlockGesture = false;
+ private boolean mActivityTranslucencyConverted = false;
private final DismissAnimator mDismissAnimator = new DismissAnimator();
private OnDismissedListener mDismissedListener;
private OnSwipeProgressChangedListener mProgressListener;
- private ViewTreeObserver.OnEnterAnimationCompleteListener mOnEnterAnimationCompleteListener =
- new ViewTreeObserver.OnEnterAnimationCompleteListener() {
- @Override
- public void onEnterAnimationComplete() {
- // SwipeDismissLayout assumes that the host Activity is translucent
- // and temporarily disables translucency when it is fully visible.
- // As soon as the user starts swiping, we will re-enable
- // translucency.
- if (mUseDynamicTranslucency && getContext() instanceof Activity) {
- ((Activity) getContext()).convertFromTranslucent();
- }
- }
- };
private BroadcastReceiver mScreenOffReceiver = new BroadcastReceiver() {
private Runnable mRunnable = new Runnable() {
@Override
@@ -141,8 +130,8 @@
mMinFlingVelocity = vc.getScaledMinimumFlingVelocity();
TypedArray a = context.getTheme().obtainStyledAttributes(
com.android.internal.R.styleable.Theme);
- mUseDynamicTranslucency = !a.hasValue(
- com.android.internal.R.styleable.Window_windowIsTranslucent);
+ mIsWindowNativelyTranslucent = a.getBoolean(
+ com.android.internal.R.styleable.Window_windowIsTranslucent, false);
a.recycle();
}
@@ -157,20 +146,12 @@
@Override
protected void onAttachedToWindow() {
super.onAttachedToWindow();
- if (getContext() instanceof Activity) {
- getViewTreeObserver().addOnEnterAnimationCompleteListener(
- mOnEnterAnimationCompleteListener);
- }
getContext().registerReceiver(mScreenOffReceiver, mScreenOffFilter);
}
@Override
protected void onDetachedFromWindow() {
getContext().unregisterReceiver(mScreenOffReceiver);
- if (getContext() instanceof Activity) {
- getViewTreeObserver().removeOnEnterAnimationCompleteListener(
- mOnEnterAnimationCompleteListener);
- }
super.onDetachedFromWindow();
}
@@ -273,9 +254,6 @@
mLastX = ev.getRawX();
updateSwiping(ev);
if (mSwiping) {
- if (mUseDynamicTranslucency && getContext() instanceof Activity) {
- ((Activity) getContext()).convertToTranslucent(null, null);
- }
setProgress(ev.getRawX() - mDownX);
break;
}
@@ -298,8 +276,12 @@
}
protected void cancel() {
- if (mUseDynamicTranslucency && getContext() instanceof Activity) {
- ((Activity) getContext()).convertFromTranslucent();
+ if (!mIsWindowNativelyTranslucent) {
+ Activity activity = findActivity();
+ if (activity != null && mActivityTranslucencyConverted) {
+ activity.convertFromTranslucent();
+ mActivityTranslucencyConverted = false;
+ }
}
if (mProgressListener != null) {
mProgressListener.onSwipeCancelled(this);
@@ -323,6 +305,7 @@
}
private void updateSwiping(MotionEvent ev) {
+ boolean oldSwiping = mSwiping;
if (!mSwiping) {
float deltaX = ev.getRawX() - mDownX;
float deltaY = ev.getRawY() - mDownY;
@@ -332,6 +315,16 @@
mSwiping = false;
}
}
+
+ if (mSwiping && !oldSwiping) {
+ // Swiping has started
+ if (!mIsWindowNativelyTranslucent) {
+ Activity activity = findActivity();
+ if (activity != null) {
+ mActivityTranslucencyConverted = activity.convertToTranslucent(null, null);
+ }
+ }
+ }
}
private void updateDismiss(MotionEvent ev) {
@@ -404,6 +397,17 @@
return 1 - progress * progress * progress;
}
+ private Activity findActivity() {
+ Context context = getContext();
+ while (context instanceof ContextWrapper) {
+ if (context instanceof Activity) {
+ return (Activity) context;
+ }
+ context = ((ContextWrapper) context).getBaseContext();
+ }
+ return null;
+ }
+
private class DismissAnimator implements AnimatorUpdateListener, Animator.AnimatorListener {
private final TimeInterpolator DISMISS_INTERPOLATOR = new DecelerateInterpolator(1.5f);
private final long DISMISS_DURATION = 250;
diff --git a/core/jni/Android.mk b/core/jni/Android.mk
index a13ebaf..29483c7 100644
--- a/core/jni/Android.mk
+++ b/core/jni/Android.mk
@@ -60,7 +60,6 @@
android_graphics_drawable_VectorDrawable.cpp \
android_view_DisplayEventReceiver.cpp \
android_view_DisplayListCanvas.cpp \
- android_view_GraphicBuffer.cpp \
android_view_HardwareLayer.cpp \
android_view_InputChannel.cpp \
android_view_InputDevice.cpp \
@@ -120,6 +119,7 @@
android/graphics/FontFamily.cpp \
android/graphics/CreateJavaOutputStreamAdaptor.cpp \
android/graphics/GIFMovie.cpp \
+ android/graphics/GraphicBuffer.cpp \
android/graphics/Graphics.cpp \
android/graphics/HarfBuzzNGFaceSkia.cpp \
android/graphics/Interpolator.cpp \
@@ -215,6 +215,7 @@
external/skia/src/effects \
external/skia/src/image \
external/skia/src/images \
+ external/skia/src/utils \
external/sqlite/dist \
external/sqlite/android \
external/tremor/Tremor \
diff --git a/core/jni/AndroidRuntime.cpp b/core/jni/AndroidRuntime.cpp
index 6c9a764..c195cfe 100644
--- a/core/jni/AndroidRuntime.cpp
+++ b/core/jni/AndroidRuntime.cpp
@@ -57,6 +57,7 @@
extern int register_android_graphics_BitmapRegionDecoder(JNIEnv*);
extern int register_android_graphics_Camera(JNIEnv* env);
extern int register_android_graphics_CreateJavaOutputStreamAdaptor(JNIEnv* env);
+extern int register_android_graphics_GraphicBuffer(JNIEnv* env);
extern int register_android_graphics_Graphics(JNIEnv* env);
extern int register_android_graphics_Interpolator(JNIEnv* env);
extern int register_android_graphics_MaskFilter(JNIEnv* env);
@@ -134,7 +135,6 @@
extern int register_android_graphics_pdf_PdfRenderer(JNIEnv* env);
extern int register_android_view_DisplayEventReceiver(JNIEnv* env);
extern int register_android_view_DisplayListCanvas(JNIEnv* env);
-extern int register_android_view_GraphicBuffer(JNIEnv* env);
extern int register_android_view_HardwareLayer(JNIEnv* env);
extern int register_android_view_RenderNode(JNIEnv* env);
extern int register_android_view_RenderNodeAnimator(JNIEnv* env);
@@ -1296,7 +1296,6 @@
REG_JNI(register_android_view_DisplayEventReceiver),
REG_JNI(register_android_view_RenderNode),
REG_JNI(register_android_view_RenderNodeAnimator),
- REG_JNI(register_android_view_GraphicBuffer),
REG_JNI(register_android_view_DisplayListCanvas),
REG_JNI(register_android_view_HardwareLayer),
REG_JNI(register_android_view_ThreadedRenderer),
@@ -1328,6 +1327,7 @@
REG_JNI(register_android_graphics_ColorFilter),
REG_JNI(register_android_graphics_DrawFilter),
REG_JNI(register_android_graphics_FontFamily),
+ REG_JNI(register_android_graphics_GraphicBuffer),
REG_JNI(register_android_graphics_Interpolator),
REG_JNI(register_android_graphics_MaskFilter),
REG_JNI(register_android_graphics_Matrix),
diff --git a/core/jni/android/graphics/Bitmap.cpp b/core/jni/android/graphics/Bitmap.cpp
index 8f74bf8..2bde991 100755
--- a/core/jni/android/graphics/Bitmap.cpp
+++ b/core/jni/android/graphics/Bitmap.cpp
@@ -1,6 +1,7 @@
#define LOG_TAG "Bitmap"
#include "Bitmap.h"
+#include "GraphicBuffer.h"
#include "SkBitmap.h"
#include "SkPixelRef.h"
#include "SkImageEncoder.h"
@@ -52,6 +53,7 @@
mAllocationSize = mBitmap->getAllocationByteCount();
mRowBytes = mBitmap->rowBytes();
mGenerationId = mBitmap->getGenerationID();
+ mIsHardware = mBitmap->isHardware();
mBitmap.reset();
}
@@ -118,6 +120,13 @@
return mGenerationId;
}
+ bool isHardware() {
+ if (mBitmap) {
+ return mBitmap->isHardware();
+ }
+ return mIsHardware;
+ }
+
~BitmapWrapper() { }
private:
@@ -127,6 +136,7 @@
size_t mAllocationSize;
size_t mRowBytes;
uint32_t mGenerationId;
+ bool mIsHardware;
};
// Convenience class that does not take a global ref on the pixels, relying
@@ -775,7 +785,7 @@
static jint Bitmap_config(JNIEnv* env, jobject, jlong bitmapHandle) {
LocalScopedBitmap bitmap(bitmapHandle);
- if (bitmap->bitmap().isHardware()) {
+ if (bitmap->isHardware()) {
return GraphicsJNI::hardwareLegacyBitmapConfig();
}
return GraphicsJNI::colorTypeToLegacyBitmapConfig(bitmap->info().colorType());
@@ -1208,7 +1218,7 @@
// Paying the price for making Hardware Bitmap as Config:
// later check for colorType will pass successfully,
// because Hardware Config internally may be RGBA8888 or smth like that.
- if (bitmap0->bitmap().isHardware() != bitmap1->bitmap().isHardware()) {
+ if (bitmap0->isHardware() != bitmap1->isHardware()) {
return JNI_FALSE;
}
@@ -1282,6 +1292,43 @@
return static_cast<jint>(bitmapHandle->getAllocationByteCount());
}
+static jobject Bitmap_copyPreserveInternalConfig(JNIEnv* env, jobject, jlong bitmapPtr) {
+ LocalScopedBitmap bitmapHandle(bitmapPtr);
+ LOG_ALWAYS_FATAL_IF(!bitmapHandle->isHardware(),
+ "Hardware config is only supported config in Bitmap_nativeCopyPreserveInternalConfig");
+ Bitmap& hwuiBitmap = bitmapHandle->bitmap();
+ SkBitmap src;
+ hwuiBitmap.getSkBitmap(&src);
+
+ SkBitmap result;
+ HeapAllocator allocator;
+ if (!src.copyTo(&result, hwuiBitmap.info().colorType(), &allocator)) {
+ doThrowRE(env, "Could not copy a hardware bitmap.");
+ return NULL;
+ }
+ return createBitmap(env, allocator.getStorageObjAndReset(), kBitmapCreateFlag_None);
+}
+
+static jobject Bitmap_createHardwareBitmap(JNIEnv* env, jobject, jobject graphicBuffer) {
+ sp<GraphicBuffer> buffer(graphicBufferForJavaObject(env, graphicBuffer));
+ sk_sp<Bitmap> bitmap = Bitmap::createFrom(buffer);
+ if (!bitmap.get()) {
+ ALOGW("failed to create hardware bitmap from graphic buffer");
+ return NULL;
+ }
+ return bitmap::createBitmap(env, bitmap.release(), android::bitmap::kBitmapCreateFlag_None);
+}
+
+static jobject Bitmap_createGraphicBufferHandle(JNIEnv* env, jobject, jlong bitmapPtr) {
+ LocalScopedBitmap bitmapHandle(bitmapPtr);
+ LOG_ALWAYS_FATAL_IF(!bitmapHandle->isHardware(),
+ "Hardware config is only supported config in Bitmap_getGraphicBuffer");
+
+ Bitmap& hwuiBitmap = bitmapHandle->bitmap();
+ sp<GraphicBuffer> buffer(hwuiBitmap.graphicBuffer());
+ return createJavaGraphicBuffer(env, buffer);
+}
+
///////////////////////////////////////////////////////////////////////////////
static jclass make_globalref(JNIEnv* env, const char classname[])
{
@@ -1340,6 +1387,12 @@
{ "nativeSameAs", "(JJ)Z", (void*)Bitmap_sameAs },
{ "nativePrepareToDraw", "(J)V", (void*)Bitmap_prepareToDraw },
{ "nativeGetAllocationByteCount", "(J)I", (void*)Bitmap_getAllocationByteCount },
+ { "nativeCopyPreserveInternalConfig", "(J)Landroid/graphics/Bitmap;",
+ (void*)Bitmap_copyPreserveInternalConfig },
+ { "nativeCreateHardwareBitmap", "(Landroid/graphics/GraphicBuffer;)Landroid/graphics/Bitmap;",
+ (void*) Bitmap_createHardwareBitmap },
+ { "nativeCreateGraphicBufferHandle", "(J)Landroid/graphics/GraphicBuffer;",
+ (void*) Bitmap_createGraphicBufferHandle }
};
int register_android_graphics_Bitmap(JNIEnv* env)
diff --git a/core/jni/android/graphics/BitmapFactory.cpp b/core/jni/android/graphics/BitmapFactory.cpp
index 1165a45..19d4848 100644
--- a/core/jni/android/graphics/BitmapFactory.cpp
+++ b/core/jni/android/graphics/BitmapFactory.cpp
@@ -8,6 +8,7 @@
#include "SkBRDAllocator.h"
#include "SkFrontBufferedStream.h"
#include "SkMath.h"
+#include "SkOpts.h"
#include "SkPixelRef.h"
#include "SkStream.h"
#include "SkUtils.h"
@@ -224,6 +225,45 @@
needsFineScale(fullSize.height(), decodedSize.height(), sampleSize);
}
+static inline SkAlphaType computeDecodeAlphaType(SkColorType colorType, SkAlphaType alphaType) {
+#ifndef ANDROID_ENABLE_LINEAR_BLENDING
+ // Skia premultiplies linearly. Until the framework enables linear blending,
+ // it expects a legacy premultiply.
+ if (kPremul_SkAlphaType == alphaType && kRGBA_F16_SkColorType != colorType) {
+ return kUnpremul_SkAlphaType;
+ }
+#endif
+
+ return alphaType;
+}
+
+static inline void premultiplyIfNecessary(SkBitmap* bitmap, SkPMColor* colorPtr, int* colorCount,
+ SkAlphaType alphaType, bool requireUnpremultiplied) {
+#ifndef ANDROID_ENABLE_LINEAR_BLENDING
+ if (kUnpremul_SkAlphaType != alphaType || requireUnpremultiplied) {
+ return;
+ }
+
+ switch (bitmap->colorType()) {
+ case kN32_SkColorType:
+ for (int y = 0; y < bitmap->height(); y++) {
+ SkOpts::RGBA_to_rgbA(bitmap->getAddr32(0, y), bitmap->getAddr32(0, y),
+ bitmap->width());
+ }
+
+ return;
+ case kIndex_8_SkColorType:
+ SkOpts::RGBA_to_rgbA(colorPtr, colorPtr, *colorCount);
+ return;
+ default:
+ // kRGBA_F16 will be premultiplied by the codec if necessary.
+ // kGray_8 (alias kAlpha_8) and k565 are opaque.
+ LOG_ALWAYS_FATAL("Should be unreachable - no need for legacy premultiply.");
+ return;
+ }
+#endif
+}
+
static jobject doDecode(JNIEnv* env, SkStreamRewindable* stream, jobject padding, jobject options) {
// This function takes ownership of the input stream. Since the SkAndroidCodec
// will take ownership of the stream, we don't necessarily need to take ownership
@@ -391,13 +431,17 @@
colorCount = &maxColors;
}
- // Set the alpha type for the decode.
SkAlphaType alphaType = codec->computeOutputAlphaType(requireUnpremultiplied);
+ SkAlphaType decodeAlphaType = computeDecodeAlphaType(decodeColorType, alphaType);
const SkImageInfo decodeInfo = SkImageInfo::Make(size.width(), size.height(),
- decodeColorType, alphaType, GraphicsJNI::colorSpaceForType(decodeColorType));
+ decodeColorType, decodeAlphaType, codec->computeOutputColorSpace(decodeColorType));
- SkImageInfo bitmapInfo = decodeInfo;
+ // When supported by the colorType, we will decode to sRGB (or linear sRGB). However,
+ // we only want to mark the bitmap as sRGB when linear blending is enabled.
+ SkImageInfo bitmapInfo = decodeInfo.makeAlphaType(alphaType)
+ .makeColorSpace(GraphicsJNI::colorSpaceForType(decodeColorType));
+
if (decodeColorType == kGray_8_SkColorType) {
// The legacy implementation of BitmapFactory used kAlpha8 for
// grayscale images (before kGray8 existed). While the codec
@@ -433,6 +477,8 @@
default:
return nullObjectReturn("codec->getAndroidPixels() failed.");
}
+ premultiplyIfNecessary(&decodingBitmap, colorPtr, colorCount, decodeAlphaType,
+ requireUnpremultiplied);
jbyteArray ninePatchChunk = NULL;
if (peeker.mPatch != NULL) {
diff --git a/core/jni/android_view_GraphicBuffer.cpp b/core/jni/android/graphics/GraphicBuffer.cpp
similarity index 81%
rename from core/jni/android_view_GraphicBuffer.cpp
rename to core/jni/android/graphics/GraphicBuffer.cpp
index f18837f..c61b53e 100644
--- a/core/jni/android_view_GraphicBuffer.cpp
+++ b/core/jni/android/graphics/GraphicBuffer.cpp
@@ -20,9 +20,8 @@
#include "JNIHelp.h"
#include "android_os_Parcel.h"
-#include "android_view_GraphicBuffer.h"
-#include "android/graphics/GraphicsJNI.h"
-#include "Bitmap.h"
+#include "GraphicBuffer.h"
+#include "GraphicsJNI.h"
#include <android_runtime/AndroidRuntime.h>
@@ -59,6 +58,8 @@
static struct {
jfieldID mNativeObject;
+ jclass mClass;
+ jmethodID mConstructorMethodID;
} gGraphicBufferClassInfo;
static struct {
@@ -100,7 +101,7 @@
// GraphicBuffer lifecycle
// ----------------------------------------------------------------------------
-static jlong android_view_GraphiceBuffer_create(JNIEnv* env, jobject clazz,
+static jlong android_graphics_GraphicBuffer_create(JNIEnv* env, jobject clazz,
jint width, jint height, jint format, jint usage) {
sp<ISurfaceComposer> composer(ComposerService::getComposerService());
@@ -125,7 +126,7 @@
return reinterpret_cast<jlong>(wrapper);
}
-static void android_view_GraphiceBuffer_destroy(JNIEnv* env, jobject clazz,
+static void android_graphics_GraphicBuffer_destroy(JNIEnv* env, jobject clazz,
jlong wrapperHandle) {
GraphicBufferWrapper* wrapper =
reinterpret_cast<GraphicBufferWrapper*>(wrapperHandle);
@@ -151,7 +152,7 @@
}
}
-static jboolean android_view_GraphicBuffer_lockCanvas(JNIEnv* env, jobject,
+static jboolean android_graphics_GraphicBuffer_lockCanvas(JNIEnv* env, jobject,
jlong wrapperHandle, jobject canvas, jobject dirtyRect) {
GraphicBufferWrapper* wrapper =
@@ -209,7 +210,7 @@
return JNI_TRUE;
}
-static jboolean android_view_GraphicBuffer_unlockCanvasAndPost(JNIEnv* env, jobject,
+static jboolean android_graphics_GraphicBuffer_unlockCanvasAndPost(JNIEnv* env, jobject,
jlong wrapperHandle, jobject canvas) {
GraphicBufferWrapper* wrapper =
@@ -229,7 +230,7 @@
// Serialization
// ----------------------------------------------------------------------------
-static void android_view_GraphiceBuffer_write(JNIEnv* env, jobject clazz,
+static void android_graphics_GraphicBuffer_write(JNIEnv* env, jobject clazz,
jlong wrapperHandle, jobject dest) {
GraphicBufferWrapper* wrapper =
reinterpret_cast<GraphicBufferWrapper*>(wrapperHandle);
@@ -239,7 +240,7 @@
}
}
-static jlong android_view_GraphiceBuffer_read(JNIEnv* env, jobject clazz,
+static jlong android_graphics_GraphicBuffer_read(JNIEnv* env, jobject clazz,
jobject in) {
Parcel* parcel = parcelForJavaObject(env, in);
@@ -252,17 +253,6 @@
return NULL;
}
-static jobject android_view_GraphicBuffer_createHardwareBitmap(JNIEnv* env, jobject,
- jlong wrapperHandle) {
- GraphicBufferWrapper* wrapper = reinterpret_cast<GraphicBufferWrapper*>(wrapperHandle);
- sk_sp<Bitmap> bitmap = Bitmap::createFrom(wrapper->buffer);
- if (!bitmap.get()) {
- ALOGW("failed to create hardware bitmap from graphic buffer");
- return NULL;
- }
- return bitmap::createBitmap(env, bitmap.release(), android::bitmap::kBitmapCreateFlag_None);
-}
-
// ----------------------------------------------------------------------------
// External helpers
// ----------------------------------------------------------------------------
@@ -279,35 +269,46 @@
return NULL;
}
+jobject createJavaGraphicBuffer(JNIEnv* env, const sp<GraphicBuffer>& buffer) {
+ GraphicBufferWrapper* wrapper = new GraphicBufferWrapper(buffer);
+ jobject obj = env->NewObject(gGraphicBufferClassInfo.mClass,
+ gGraphicBufferClassInfo.mConstructorMethodID, buffer->getWidth(), buffer->getHeight(),
+ buffer->getPixelFormat(), buffer->getUsage(), reinterpret_cast<jlong>(wrapper));
+ return obj;
+}
+
+};
+
+using namespace android;
// ----------------------------------------------------------------------------
// JNI Glue
// ----------------------------------------------------------------------------
-const char* const kClassPathName = "android/view/GraphicBuffer";
+const char* const kClassPathName = "android/graphics/GraphicBuffer";
static const JNINativeMethod gMethods[] = {
- { "nCreateGraphicBuffer", "(IIII)J", (void*) android_view_GraphiceBuffer_create },
- { "nDestroyGraphicBuffer", "(J)V", (void*) android_view_GraphiceBuffer_destroy },
+ { "nCreateGraphicBuffer", "(IIII)J", (void*) android_graphics_GraphicBuffer_create },
+ { "nDestroyGraphicBuffer", "(J)V", (void*) android_graphics_GraphicBuffer_destroy },
{ "nWriteGraphicBufferToParcel", "(JLandroid/os/Parcel;)V",
- (void*) android_view_GraphiceBuffer_write },
+ (void*) android_graphics_GraphicBuffer_write },
{ "nReadGraphicBufferFromParcel", "(Landroid/os/Parcel;)J",
- (void*) android_view_GraphiceBuffer_read },
+ (void*) android_graphics_GraphicBuffer_read },
{ "nLockCanvas", "(JLandroid/graphics/Canvas;Landroid/graphics/Rect;)Z",
- (void*) android_view_GraphicBuffer_lockCanvas },
+ (void*) android_graphics_GraphicBuffer_lockCanvas },
{ "nUnlockCanvasAndPost", "(JLandroid/graphics/Canvas;)Z",
- (void*) android_view_GraphicBuffer_unlockCanvasAndPost },
- { "nCreateHardwareBitmap", "(J)Landroid/graphics/Bitmap;",
- (void*) android_view_GraphicBuffer_createHardwareBitmap
- }
+ (void*) android_graphics_GraphicBuffer_unlockCanvasAndPost }
};
-int register_android_view_GraphicBuffer(JNIEnv* env) {
- jclass clazz = FindClassOrDie(env, "android/view/GraphicBuffer");
- gGraphicBufferClassInfo.mNativeObject = GetFieldIDOrDie(env, clazz, "mNativeObject", "J");
+int register_android_graphics_GraphicBuffer(JNIEnv* env) {
+ gGraphicBufferClassInfo.mClass = MakeGlobalRefOrDie(env, FindClassOrDie(env, kClassPathName));
+ gGraphicBufferClassInfo.mNativeObject = GetFieldIDOrDie(env, gGraphicBufferClassInfo.mClass,
+ "mNativeObject", "J");
+ gGraphicBufferClassInfo.mConstructorMethodID = env->GetMethodID(gGraphicBufferClassInfo.mClass,
+ "<init>", "(IIIIJ)V");
- clazz = FindClassOrDie(env, "android/graphics/Rect");
+ jclass clazz = FindClassOrDie(env, "android/graphics/Rect");
gRectClassInfo.set = GetMethodIDOrDie(env, clazz, "set", "(IIII)V");
gRectClassInfo.left = GetFieldIDOrDie(env, clazz, "left", "I");
gRectClassInfo.top = GetFieldIDOrDie(env, clazz, "top", "I");
@@ -315,6 +316,4 @@
gRectClassInfo.bottom = GetFieldIDOrDie(env, clazz, "bottom", "I");
return RegisterMethodsOrDie(env, kClassPathName, gMethods, NELEM(gMethods));
-}
-
-};
+}
\ No newline at end of file
diff --git a/core/jni/android_view_GraphicBuffer.h b/core/jni/android/graphics/GraphicBuffer.h
similarity index 91%
rename from core/jni/android_view_GraphicBuffer.h
rename to core/jni/android/graphics/GraphicBuffer.h
index 509587c..0d72669 100644
--- a/core/jni/android_view_GraphicBuffer.h
+++ b/core/jni/android/graphics/GraphicBuffer.h
@@ -24,4 +24,6 @@
// object must be an instance of android.view.GraphicBuffer
extern sp<GraphicBuffer> graphicBufferForJavaObject(JNIEnv* env, jobject obj);
+jobject createJavaGraphicBuffer(JNIEnv* env, const sp<GraphicBuffer>& buffer);
+
}
diff --git a/core/jni/android_graphics_Canvas.cpp b/core/jni/android_graphics_Canvas.cpp
index be9449b..9ce5670 100644
--- a/core/jni/android_graphics_Canvas.cpp
+++ b/core/jni/android_graphics_Canvas.cpp
@@ -219,13 +219,6 @@
return nonEmptyClip ? JNI_TRUE : JNI_FALSE;
}
-static jboolean clipRegion(JNIEnv* env, jobject, jlong canvasHandle, jlong deviceRgnHandle,
- jint opHandle) {
- SkRegion* deviceRgn = reinterpret_cast<SkRegion*>(deviceRgnHandle);
- bool nonEmptyClip = get_canvas(canvasHandle)->clipRegion(deviceRgn, opHandleToClipOp(opHandle));
- return nonEmptyClip ? JNI_TRUE : JNI_FALSE;
-}
-
static void drawColor(JNIEnv* env, jobject, jlong canvasHandle, jint color, jint modeHandle) {
SkBlendMode mode = static_cast<SkBlendMode>(modeHandle);
get_canvas(canvasHandle)->drawColor(color, mode);
@@ -616,7 +609,6 @@
{"nQuickReject","(JFFFF)Z", (void*)CanvasJNI::quickRejectRect},
{"nClipRect","(JFFFFI)Z", (void*) CanvasJNI::clipRect},
{"nClipPath","(JJI)Z", (void*) CanvasJNI::clipPath},
- {"nClipRegion","(JJI)Z", (void*) CanvasJNI::clipRegion},
{"nSetDrawFilter", "(JJ)V", (void*) CanvasJNI::setDrawFilter},
};
diff --git a/core/jni/android_hardware_Radio.cpp b/core/jni/android_hardware_Radio.cpp
index 42ceec4..397e67b 100644
--- a/core/jni/android_hardware_Radio.cpp
+++ b/core/jni/android_hardware_Radio.cpp
@@ -313,12 +313,14 @@
ALOGV("%s", __FUNCTION__);
int jStatus;
jobject jMetadata = NULL;
- if (nProgramInfo->metadata != NULL) {
- ALOGV("%s metadata %p", __FUNCTION__, nProgramInfo->metadata);
- jStatus = convertMetadataFromNative(env, &jMetadata, nProgramInfo->metadata);
- if (jStatus < 0) {
- return jStatus;
- }
+
+ if (nProgramInfo == nullptr || nProgramInfo->metadata == nullptr) {
+ return (jint)RADIO_STATUS_BAD_VALUE;
+ }
+
+ jStatus = convertMetadataFromNative(env, &jMetadata, nProgramInfo->metadata);
+ if (jStatus < 0) {
+ return jStatus;
}
ALOGV("%s channel %d tuned %d", __FUNCTION__, nProgramInfo->channel, nProgramInfo->tuned);
diff --git a/core/jni/android_media_AudioSystem.cpp b/core/jni/android_media_AudioSystem.cpp
index 664c7ea..226e9e3 100644
--- a/core/jni/android_media_AudioSystem.cpp
+++ b/core/jni/android_media_AudioSystem.cpp
@@ -463,6 +463,18 @@
}
static jint
+android_media_AudioSystem_handleDeviceConfigChange(JNIEnv *env, jobject thiz, jint device, jstring device_address, jstring device_name)
+{
+ const char *c_address = env->GetStringUTFChars(device_address, NULL);
+ const char *c_name = env->GetStringUTFChars(device_name, NULL);
+ int status = check_AudioSystem_Command(AudioSystem::handleDeviceConfigChange(static_cast <audio_devices_t>(device),
+ c_address, c_name));
+ env->ReleaseStringUTFChars(device_address, c_address);
+ env->ReleaseStringUTFChars(device_name, c_name);
+ return (jint) status;
+}
+
+static jint
android_media_AudioSystem_setPhoneState(JNIEnv *env, jobject thiz, jint state)
{
return (jint) check_AudioSystem_Command(AudioSystem::setPhoneState((audio_mode_t) state));
@@ -1764,6 +1776,7 @@
{"newAudioPlayerId", "()I", (void *)android_media_AudioSystem_newAudioPlayerId},
{"setDeviceConnectionState", "(IILjava/lang/String;Ljava/lang/String;)I", (void *)android_media_AudioSystem_setDeviceConnectionState},
{"getDeviceConnectionState", "(ILjava/lang/String;)I", (void *)android_media_AudioSystem_getDeviceConnectionState},
+ {"handleDeviceConfigChange", "(ILjava/lang/String;Ljava/lang/String;)I", (void *)android_media_AudioSystem_handleDeviceConfigChange},
{"setPhoneState", "(I)I", (void *)android_media_AudioSystem_setPhoneState},
{"setForceUse", "(II)I", (void *)android_media_AudioSystem_setForceUse},
{"getForceUse", "(I)I", (void *)android_media_AudioSystem_getForceUse},
diff --git a/core/jni/android_os_HwBinder.cpp b/core/jni/android_os_HwBinder.cpp
index 95e031b..20bb885 100644
--- a/core/jni/android_os_HwBinder.cpp
+++ b/core/jni/android_os_HwBinder.cpp
@@ -39,6 +39,8 @@
using android::AndroidRuntime;
using android::hardware::hidl_vec;
using android::hardware::hidl_string;
+template<typename T>
+using Return = android::hardware::Return<T>;
#define PACKAGE_PATH "android/os"
#define CLASS_NAME "HwBinder"
@@ -52,6 +54,8 @@
jmethodID get;
} gArrayListMethods;
+static jclass gErrorClass;
+
static struct fields_t {
jfieldID contextID;
jmethodID onTransactID;
@@ -144,6 +148,22 @@
replyObj.get(),
flags);
+ if (env->ExceptionCheck()) {
+ jthrowable excep = env->ExceptionOccurred();
+ env->ExceptionDescribe();
+
+ if (env->IsInstanceOf(excep, gErrorClass)) {
+ /* It's an error */
+ LOG(ERROR) << "Forcefully exiting";
+ exit(1);
+ } else {
+ env->ExceptionClear();
+ LOG(ERROR) << "Uncaught exception!";
+ }
+
+ env->DeleteLocalRef(excep);
+ }
+
status_t err = OK;
if (!replyContext->wasSent()) {
@@ -239,8 +259,6 @@
hidl_vec<hidl_string> interfaceChain;
interfaceChain.setToExternal(strings, numInterfaces, true /* shouldOwn */);
- using android::hidl::manager::V1_0::IServiceManager;
-
sp<hardware::IBinder> binder = JHwBinder::GetNativeContext(env, thiz);
/* TODO(b/33440494) this is not right */
@@ -250,24 +268,23 @@
if (manager == nullptr) {
LOG(ERROR) << "Could not get hwservicemanager.";
- signalExceptionForError(env, UNKNOWN_ERROR);
+ signalExceptionForError(env, UNKNOWN_ERROR, true /* canThrowRemoteException */);
return;
}
- bool ok = manager->add(
- interfaceChain,
- serviceName,
- base);
+ Return<bool> ret = manager->add(interfaceChain, serviceName, base);
env->ReleaseStringUTFChars(serviceNameObj, serviceName);
serviceName = NULL;
+ bool ok = ret.isOk() && ret;
+
if (ok) {
LOG(INFO) << "Starting thread pool.";
::android::hardware::ProcessState::self()->startThreadPool();
}
- signalExceptionForError(env, (ok ? OK : UNKNOWN_ERROR));
+ signalExceptionForError(env, (ok ? OK : UNKNOWN_ERROR), true /* canThrowRemoteException */);
}
static jobject JHwBinder_native_getService(
@@ -303,19 +320,18 @@
if (manager == nullptr) {
LOG(ERROR) << "Could not get hwservicemanager.";
- signalExceptionForError(env, UNKNOWN_ERROR);
+ signalExceptionForError(env, UNKNOWN_ERROR, true /* canThrowRemoteException */);
return NULL;
}
- sp<hardware::IBinder> service;
- manager->get(
- ifaceName,
- serviceName,
- [&service](sp<hidl::base::V1_0::IBase> out) {
- service = hardware::toBinder<
- hidl::base::V1_0::IBase, hidl::base::V1_0::BpBase
- >(out);
- });
+ Return<sp<hidl::base::V1_0::IBase>> ret = manager->get(ifaceName, serviceName);
+
+ if (!ret.isOk()) {
+ signalExceptionForError(env, UNKNOWN_ERROR, true /* canThrowRemoteException */);
+ }
+
+ sp<hardware::IBinder> service = hardware::toBinder<
+ hidl::base::V1_0::IBase, hidl::base::V1_0::BpBase>(ret);
env->ReleaseStringUTFChars(ifaceNameObj, ifaceName);
ifaceName = NULL;
@@ -356,6 +372,9 @@
gArrayListMethods.size = GetMethodIDOrDie(env, arrayListClass, "size", "()I");
gArrayListMethods.get = GetMethodIDOrDie(env, arrayListClass, "get", "(I)Ljava/lang/Object;");
+ jclass errorClass = FindClassOrDie(env, "java/lang/Error");
+ gErrorClass = MakeGlobalRefOrDie(env, errorClass);
+
return RegisterMethodsOrDie(env, CLASS_PATH, gMethods, NELEM(gMethods));
}
diff --git a/core/jni/android_os_HwParcel.cpp b/core/jni/android_os_HwParcel.cpp
index a10d807..b9d810a 100644
--- a/core/jni/android_os_HwParcel.cpp
+++ b/core/jni/android_os_HwParcel.cpp
@@ -49,7 +49,7 @@
} gFields;
-void signalExceptionForError(JNIEnv *env, status_t err) {
+void signalExceptionForError(JNIEnv *env, status_t err, bool canThrowRemoteException) {
switch (err) {
case OK:
break;
@@ -114,8 +114,13 @@
default:
{
+ std::stringstream ss;
+ ss << "HwBinder Error: (" << err << ")";
+
jniThrowException(
- env, "java/lang/RuntimeException", "Unknown error");
+ env,
+ canThrowRemoteException ? "android/os/RemoteException" : "java/lang/RuntimeException",
+ ss.str().c_str());
break;
}
diff --git a/core/jni/android_os_HwParcel.h b/core/jni/android_os_HwParcel.h
index 708bbba..f81de9b 100644
--- a/core/jni/android_os_HwParcel.h
+++ b/core/jni/android_os_HwParcel.h
@@ -67,7 +67,7 @@
DISALLOW_COPY_AND_ASSIGN(JHwParcel);
};
-void signalExceptionForError(JNIEnv *env, status_t err);
+void signalExceptionForError(JNIEnv *env, status_t err, bool canThrowRemoteException = false);
int register_android_os_HwParcel(JNIEnv *env);
} // namespace android
diff --git a/core/jni/android_os_HwRemoteBinder.cpp b/core/jni/android_os_HwRemoteBinder.cpp
index 0a7d84d..f2f8e52 100644
--- a/core/jni/android_os_HwRemoteBinder.cpp
+++ b/core/jni/android_os_HwRemoteBinder.cpp
@@ -347,7 +347,7 @@
JHwParcel::GetNativeContext(env, replyObj)->getParcel();
status_t err = binder->transact(code, *request, reply, flags);
- signalExceptionForError(env, err);
+ signalExceptionForError(env, err, true /* canThrowRemoteException */);
}
static jboolean JHwRemoteBinder_linkToDeath(JNIEnv* env, jobject thiz,
diff --git a/core/jni/android_view_ThreadedRenderer.cpp b/core/jni/android_view_ThreadedRenderer.cpp
index 14dcb3f..c00bcd4 100644
--- a/core/jni/android_view_ThreadedRenderer.cpp
+++ b/core/jni/android_view_ThreadedRenderer.cpp
@@ -36,7 +36,6 @@
#include <android_runtime/android_view_Surface.h>
#include <system/window.h>
-#include "android_view_GraphicBuffer.h"
#include "android_os_MessageQueue.h"
#include <Animator.h>
diff --git a/core/res/AndroidManifest.xml b/core/res/AndroidManifest.xml
index 68d8c55..a77a9cd 100644
--- a/core/res/AndroidManifest.xml
+++ b/core/res/AndroidManifest.xml
@@ -168,6 +168,8 @@
<protected-broadcast
android:name="android.bluetooth.a2dp.profile.action.PLAYING_STATE_CHANGED" />
<protected-broadcast
+ android:name="android.bluetooth.a2dp.profile.action.CODEC_CONFIG_CHANGED" />
+ <protected-broadcast
android:name="android.bluetooth.a2dp-sink.profile.action.CONNECTION_STATE_CHANGED" />
<protected-broadcast
android:name="android.bluetooth.a2dp-sink.profile.action.PLAYING_STATE_CHANGED" />
@@ -1253,6 +1255,12 @@
<permission android:name="android.permission.SCORE_NETWORKS"
android:protectionLevel="signature|privileged" />
+ <!-- @SystemApi Allows applications to request network
+ recommendations and scores from the NetworkScoreService.
+ <p>Not for use by third-party applications. @hide -->
+ <permission android:name="android.permission.REQUEST_NETWORK_SCORES"
+ android:protectionLevel="signature" />
+
<!-- ======================================= -->
<!-- Permissions for short range, peripheral networks -->
<!-- ======================================= -->
@@ -2075,6 +2083,7 @@
@SystemApi @hide -->
<permission android:name="android.permission.BIND_NETWORK_RECOMMENDATION_SERVICE"
android:protectionLevel="signature" />
+ <uses-permission android:name="android.permission.BIND_NETWORK_RECOMMENDATION_SERVICE"/>
<!-- ========================================= -->
<!-- Permissions for special development tools -->
@@ -2671,7 +2680,10 @@
android:protectionLevel="signature" />
<!-- @SystemApi Allows an application to broadcast privileged networking requests.
- <p>Not for use by third-party applications. @hide -->
+ <p>Not for use by third-party applications.
+ @hide
+ @deprecated Use {@link android.Manifest.permission#REQUEST_NETWORK_SCORES} instead
+ -->
<permission android:name="android.permission.BROADCAST_NETWORK_PRIVILEGED"
android:protectionLevel="signature|privileged" />
diff --git a/core/res/res/drawable/lockscreen_notselected.xml b/core/res/res/drawable/lockscreen_notselected.xml
new file mode 100644
index 0000000..eecea13
--- /dev/null
+++ b/core/res/res/drawable/lockscreen_notselected.xml
@@ -0,0 +1,50 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2016 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.
+-->
+
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:width="260dp"
+ android:height="260dp"
+ android:viewportWidth="260"
+ android:viewportHeight="260">
+
+ <path
+ android:fillColor="#ffffff"
+ android:pathData="M 43.3333 34.3333 C 48.3038627485 34.3333 52.3333 38.3627372515 52.3333 43.3333 C 52.3333 48.3038627485 48.3038627485 52.3333 43.3333 52.3333 C 38.3627372515 52.3333 34.3333 48.3038627485 34.3333 43.3333 C 34.3333 38.3627372515 38.3627372515 34.3333 43.3333 34.3333 Z" />
+ <path
+ android:fillColor="#ffffff"
+ android:pathData="M 43.3333 121 C 48.3038627485 121 52.3333 125.029437252 52.3333 130 C 52.3333 134.970562748 48.3038627485 139 43.3333 139 C 38.3627372515 139 34.3333 134.970562748 34.3333 130 C 34.3333 125.029437252 38.3627372515 121 43.3333 121 Z" />
+ <path
+ android:fillColor="#ffffff"
+ android:pathData="M 43.3333 207.6667 C 48.3038627485 207.6667 52.3333 211.696137252 52.3333 216.6667 C 52.3333 221.637262748 48.3038627485 225.6667 43.3333 225.6667 C 38.3627372515 225.6667 34.3333 221.637262748 34.3333 216.6667 C 34.3333 211.696137252 38.3627372515 207.6667 43.3333 207.6667 Z" />
+ <path
+ android:fillColor="#ffffff"
+ android:pathData="M 130 34.3333 C 134.970562748 34.3333 139 38.3627372515 139 43.3333 C 139 48.3038627485 134.970562748 52.3333 130 52.3333 C 125.029437252 52.3333 121 48.3038627485 121 43.3333 C 121 38.3627372515 125.029437252 34.3333 130 34.3333 Z" />
+ <path
+ android:fillColor="#ffffff"
+ android:pathData="M 130 121 C 134.970562748 121 139 125.029437252 139 130 C 139 134.970562748 134.970562748 139 130 139 C 125.029437252 139 121 134.970562748 121 130 C 121 125.029437252 125.029437252 121 130 121 Z" />
+ <path
+ android:fillColor="#ffffff"
+ android:pathData="M 130 207.6667 C 134.970562748 207.6667 139 211.696137252 139 216.6667 C 139 221.637262748 134.970562748 225.6667 130 225.6667 C 125.029437252 225.6667 121 221.637262748 121 216.6667 C 121 211.696137252 125.029437252 207.6667 130 207.6667 Z" />
+ <path
+ android:fillColor="#ffffff"
+ android:pathData="M 216.6667 34.3333 C 221.637262748 34.3333 225.6667 38.3627372515 225.6667 43.3333 C 225.6667 48.3038627485 221.637262748 52.3333 216.6667 52.3333 C 211.696137252 52.3333 207.6667 48.3038627485 207.6667 43.3333 C 207.6667 38.3627372515 211.696137252 34.3333 216.6667 34.3333 Z" />
+ <path
+ android:fillColor="#ffffff"
+ android:pathData="M 216.6667 121 C 221.637262748 121 225.6667 125.029437252 225.6667 130 C 225.6667 134.970562748 221.637262748 139 216.6667 139 C 211.696137252 139 207.6667 134.970562748 207.6667 130 C 207.6667 125.029437252 211.696137252 121 216.6667 121 Z" />
+ <path
+ android:fillColor="#ffffff"
+ android:pathData="M 216.6667 207.6667 C 221.637262748 207.6667 225.6667 211.696137252 225.6667 216.6667 C 225.6667 221.637262748 221.637262748 225.6667 216.6667 225.6667 C 211.696137252 225.6667 207.6667 221.637262748 207.6667 216.6667 C 207.6667 211.696137252 211.696137252 207.6667 216.6667 207.6667 Z" />
+</vector>
diff --git a/core/res/res/drawable/lockscreen_selected.xml b/core/res/res/drawable/lockscreen_selected.xml
new file mode 100644
index 0000000..eecea13
--- /dev/null
+++ b/core/res/res/drawable/lockscreen_selected.xml
@@ -0,0 +1,50 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2016 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.
+-->
+
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:width="260dp"
+ android:height="260dp"
+ android:viewportWidth="260"
+ android:viewportHeight="260">
+
+ <path
+ android:fillColor="#ffffff"
+ android:pathData="M 43.3333 34.3333 C 48.3038627485 34.3333 52.3333 38.3627372515 52.3333 43.3333 C 52.3333 48.3038627485 48.3038627485 52.3333 43.3333 52.3333 C 38.3627372515 52.3333 34.3333 48.3038627485 34.3333 43.3333 C 34.3333 38.3627372515 38.3627372515 34.3333 43.3333 34.3333 Z" />
+ <path
+ android:fillColor="#ffffff"
+ android:pathData="M 43.3333 121 C 48.3038627485 121 52.3333 125.029437252 52.3333 130 C 52.3333 134.970562748 48.3038627485 139 43.3333 139 C 38.3627372515 139 34.3333 134.970562748 34.3333 130 C 34.3333 125.029437252 38.3627372515 121 43.3333 121 Z" />
+ <path
+ android:fillColor="#ffffff"
+ android:pathData="M 43.3333 207.6667 C 48.3038627485 207.6667 52.3333 211.696137252 52.3333 216.6667 C 52.3333 221.637262748 48.3038627485 225.6667 43.3333 225.6667 C 38.3627372515 225.6667 34.3333 221.637262748 34.3333 216.6667 C 34.3333 211.696137252 38.3627372515 207.6667 43.3333 207.6667 Z" />
+ <path
+ android:fillColor="#ffffff"
+ android:pathData="M 130 34.3333 C 134.970562748 34.3333 139 38.3627372515 139 43.3333 C 139 48.3038627485 134.970562748 52.3333 130 52.3333 C 125.029437252 52.3333 121 48.3038627485 121 43.3333 C 121 38.3627372515 125.029437252 34.3333 130 34.3333 Z" />
+ <path
+ android:fillColor="#ffffff"
+ android:pathData="M 130 121 C 134.970562748 121 139 125.029437252 139 130 C 139 134.970562748 134.970562748 139 130 139 C 125.029437252 139 121 134.970562748 121 130 C 121 125.029437252 125.029437252 121 130 121 Z" />
+ <path
+ android:fillColor="#ffffff"
+ android:pathData="M 130 207.6667 C 134.970562748 207.6667 139 211.696137252 139 216.6667 C 139 221.637262748 134.970562748 225.6667 130 225.6667 C 125.029437252 225.6667 121 221.637262748 121 216.6667 C 121 211.696137252 125.029437252 207.6667 130 207.6667 Z" />
+ <path
+ android:fillColor="#ffffff"
+ android:pathData="M 216.6667 34.3333 C 221.637262748 34.3333 225.6667 38.3627372515 225.6667 43.3333 C 225.6667 48.3038627485 221.637262748 52.3333 216.6667 52.3333 C 211.696137252 52.3333 207.6667 48.3038627485 207.6667 43.3333 C 207.6667 38.3627372515 211.696137252 34.3333 216.6667 34.3333 Z" />
+ <path
+ android:fillColor="#ffffff"
+ android:pathData="M 216.6667 121 C 221.637262748 121 225.6667 125.029437252 225.6667 130 C 225.6667 134.970562748 221.637262748 139 216.6667 139 C 211.696137252 139 207.6667 134.970562748 207.6667 130 C 207.6667 125.029437252 211.696137252 121 216.6667 121 Z" />
+ <path
+ android:fillColor="#ffffff"
+ android:pathData="M 216.6667 207.6667 C 221.637262748 207.6667 225.6667 211.696137252 225.6667 216.6667 C 225.6667 221.637262748 221.637262748 225.6667 216.6667 225.6667 C 211.696137252 225.6667 207.6667 221.637262748 207.6667 216.6667 C 207.6667 211.696137252 211.696137252 207.6667 216.6667 207.6667 Z" />
+</vector>
diff --git a/core/res/res/values-af/strings.xml b/core/res/res/values-af/strings.xml
index 5393d1a..8baf252 100644
--- a/core/res/res/values-af/strings.xml
+++ b/core/res/res/values-af/strings.xml
@@ -1559,7 +1559,8 @@
<string name="managed_profile_label_badge" msgid="2355652472854327647">"Werk-<xliff:g id="LABEL">%1$s</xliff:g>"</string>
<string name="managed_profile_label_badge_2" msgid="5048136430082124036">"2e werk-<xliff:g id="LABEL">%1$s</xliff:g>"</string>
<string name="managed_profile_label_badge_3" msgid="2808305070321719040">"3e werk-<xliff:g id="LABEL">%1$s</xliff:g>"</string>
- <string name="lock_to_app_toast" msgid="1420543809500606964">"Raak en hou Terug om hierdie skerm te ontspeld."</string>
+ <!-- no translation found for lock_to_app_toast (7693684144593484) -->
+ <skip />
<string name="lock_to_app_toast_locked" msgid="9125176335701699164">"Program is vasgespeld: Dit mag nie op hierdie toestel ontspeld word nie."</string>
<string name="lock_to_app_start" msgid="6643342070839862795">"Skerm vasgespeld"</string>
<string name="lock_to_app_exit" msgid="8598219838213787430">"Skerm ontspeld"</string>
diff --git a/core/res/res/values-am/strings.xml b/core/res/res/values-am/strings.xml
index feac09c..3ef6831 100644
--- a/core/res/res/values-am/strings.xml
+++ b/core/res/res/values-am/strings.xml
@@ -1559,7 +1559,8 @@
<string name="managed_profile_label_badge" msgid="2355652472854327647">"ስራ <xliff:g id="LABEL">%1$s</xliff:g>"</string>
<string name="managed_profile_label_badge_2" msgid="5048136430082124036">"2ኛ ስራ <xliff:g id="LABEL">%1$s</xliff:g>"</string>
<string name="managed_profile_label_badge_3" msgid="2808305070321719040">"3ኛ ስራ <xliff:g id="LABEL">%1$s</xliff:g>"</string>
- <string name="lock_to_app_toast" msgid="1420543809500606964">"ይህን ማያ ገጽ ለመንቀል ተመለስን ይንኩትና ያዙት።"</string>
+ <!-- no translation found for lock_to_app_toast (7693684144593484) -->
+ <skip />
<string name="lock_to_app_toast_locked" msgid="9125176335701699164">"መተግበሪያ ተሰክቷል፦ በዚህ መሣሪያ ላይ ማላቀቅ አይፈቀድም።"</string>
<string name="lock_to_app_start" msgid="6643342070839862795">"ማያ ገጽ ተሰክቷል"</string>
<string name="lock_to_app_exit" msgid="8598219838213787430">"ማያ ገጽ ተነቅሏል"</string>
diff --git a/core/res/res/values-ar/strings.xml b/core/res/res/values-ar/strings.xml
index 6f58ee4..8d9d504 100644
--- a/core/res/res/values-ar/strings.xml
+++ b/core/res/res/values-ar/strings.xml
@@ -1655,7 +1655,8 @@
<string name="managed_profile_label_badge" msgid="2355652472854327647">"<xliff:g id="LABEL">%1$s</xliff:g> المخصص للعمل"</string>
<string name="managed_profile_label_badge_2" msgid="5048136430082124036">"العمل الثاني <xliff:g id="LABEL">%1$s</xliff:g>"</string>
<string name="managed_profile_label_badge_3" msgid="2808305070321719040">"العمل الثالث <xliff:g id="LABEL">%1$s</xliff:g>"</string>
- <string name="lock_to_app_toast" msgid="1420543809500606964">"لإزالة تثبيت هذه الشاشة، يمكنك لمس زر الرجوع مع الاستمرار."</string>
+ <!-- no translation found for lock_to_app_toast (7693684144593484) -->
+ <skip />
<string name="lock_to_app_toast_locked" msgid="9125176335701699164">"التطبيق مقيد: ولا يسمح بإلغاء التقييد على هذا الجهاز."</string>
<string name="lock_to_app_start" msgid="6643342070839862795">"تم تثبيت الشاشة"</string>
<string name="lock_to_app_exit" msgid="8598219838213787430">"تم إلغاء تثبيت الشاشة"</string>
diff --git a/core/res/res/values-az-rAZ/strings.xml b/core/res/res/values-az-rAZ/strings.xml
index 7c71be2..dd62c70 100644
--- a/core/res/res/values-az-rAZ/strings.xml
+++ b/core/res/res/values-az-rAZ/strings.xml
@@ -1559,7 +1559,8 @@
<string name="managed_profile_label_badge" msgid="2355652472854327647">"İş <xliff:g id="LABEL">%1$s</xliff:g>"</string>
<string name="managed_profile_label_badge_2" msgid="5048136430082124036">"2-ci İş <xliff:g id="LABEL">%1$s</xliff:g>"</string>
<string name="managed_profile_label_badge_3" msgid="2808305070321719040">"3-cü İş <xliff:g id="LABEL">%1$s</xliff:g>"</string>
- <string name="lock_to_app_toast" msgid="1420543809500606964">"Sancağı götürmək üçün Geri düyməsinə toxunun və saxlayın."</string>
+ <!-- no translation found for lock_to_app_toast (7693684144593484) -->
+ <skip />
<string name="lock_to_app_toast_locked" msgid="9125176335701699164">"Tətbiq sancılıb: Açmağa bu cihazda icazə verilmir."</string>
<string name="lock_to_app_start" msgid="6643342070839862795">"Screen pinned"</string>
<string name="lock_to_app_exit" msgid="8598219838213787430">"Screen unpinned"</string>
diff --git a/core/res/res/values-b+sr+Latn/strings.xml b/core/res/res/values-b+sr+Latn/strings.xml
index 6d31e32..d25cb67 100644
--- a/core/res/res/values-b+sr+Latn/strings.xml
+++ b/core/res/res/values-b+sr+Latn/strings.xml
@@ -1583,7 +1583,8 @@
<string name="managed_profile_label_badge" msgid="2355652472854327647">"<xliff:g id="LABEL">%1$s</xliff:g> na poslu"</string>
<string name="managed_profile_label_badge_2" msgid="5048136430082124036">"2. poslovni <xliff:g id="LABEL">%1$s</xliff:g>"</string>
<string name="managed_profile_label_badge_3" msgid="2808305070321719040">"3. poslovni imejl <xliff:g id="LABEL">%1$s</xliff:g>"</string>
- <string name="lock_to_app_toast" msgid="1420543809500606964">"Da biste otkačili ovaj ekran, dodirnite i zadržite Nazad."</string>
+ <!-- no translation found for lock_to_app_toast (7693684144593484) -->
+ <skip />
<string name="lock_to_app_toast_locked" msgid="9125176335701699164">"Aplikacija je zakačena: otkačinjanje nije dozvoljeno na ovom uređaju."</string>
<string name="lock_to_app_start" msgid="6643342070839862795">"Ekran je zakačen"</string>
<string name="lock_to_app_exit" msgid="8598219838213787430">"Ekran je otkačen"</string>
diff --git a/core/res/res/values-be-rBY/strings.xml b/core/res/res/values-be-rBY/strings.xml
index a5ad1e5..4c9227a 100644
--- a/core/res/res/values-be-rBY/strings.xml
+++ b/core/res/res/values-be-rBY/strings.xml
@@ -1607,7 +1607,8 @@
<string name="managed_profile_label_badge" msgid="2355652472854327647">"<xliff:g id="LABEL">%1$s</xliff:g> (праца)"</string>
<string name="managed_profile_label_badge_2" msgid="5048136430082124036">"Другая праца <xliff:g id="LABEL">%1$s</xliff:g>"</string>
<string name="managed_profile_label_badge_3" msgid="2808305070321719040">"Трэцяя праца <xliff:g id="LABEL">%1$s</xliff:g>"</string>
- <string name="lock_to_app_toast" msgid="1420543809500606964">"Каб адмацаваць гэты экран, дакраніцеся і ўтрымлівайце кнопку \"Назад\"."</string>
+ <!-- no translation found for lock_to_app_toast (7693684144593484) -->
+ <skip />
<string name="lock_to_app_toast_locked" msgid="9125176335701699164">"Праграма замацавана: адмацаванне на гэтай прыладзе не дапускаецца."</string>
<string name="lock_to_app_start" msgid="6643342070839862795">"Экран замацаваны"</string>
<string name="lock_to_app_exit" msgid="8598219838213787430">"Экран адмацаваны"</string>
diff --git a/core/res/res/values-bg/strings.xml b/core/res/res/values-bg/strings.xml
index 5770142..e50d178 100644
--- a/core/res/res/values-bg/strings.xml
+++ b/core/res/res/values-bg/strings.xml
@@ -1559,7 +1559,8 @@
<string name="managed_profile_label_badge" msgid="2355652472854327647">"<xliff:g id="LABEL">%1$s</xliff:g> за работа"</string>
<string name="managed_profile_label_badge_2" msgid="5048136430082124036">"Втори служебен профил (<xliff:g id="LABEL">%1$s</xliff:g>)"</string>
<string name="managed_profile_label_badge_3" msgid="2808305070321719040">"Трети служебен профил (<xliff:g id="LABEL">%1$s</xliff:g>)"</string>
- <string name="lock_to_app_toast" msgid="1420543809500606964">"За да освободите този екран, докоснете и задръжте бутона за връщане назад."</string>
+ <!-- no translation found for lock_to_app_toast (7693684144593484) -->
+ <skip />
<string name="lock_to_app_toast_locked" msgid="9125176335701699164">"Приложението е фиксирано. Освобождаването му не е разрешено на това устройство."</string>
<string name="lock_to_app_start" msgid="6643342070839862795">"Екранът е фиксиран"</string>
<string name="lock_to_app_exit" msgid="8598219838213787430">"Екранът е освободен"</string>
diff --git a/core/res/res/values-bn-rBD/strings.xml b/core/res/res/values-bn-rBD/strings.xml
index 8355209..ccb39b4 100644
--- a/core/res/res/values-bn-rBD/strings.xml
+++ b/core/res/res/values-bn-rBD/strings.xml
@@ -1559,7 +1559,8 @@
<string name="managed_profile_label_badge" msgid="2355652472854327647">"কর্মক্ষেত্র <xliff:g id="LABEL">%1$s</xliff:g>"</string>
<string name="managed_profile_label_badge_2" msgid="5048136430082124036">"দ্বিতীয় কার্যক্ষেত্র <xliff:g id="LABEL">%1$s</xliff:g>"</string>
<string name="managed_profile_label_badge_3" msgid="2808305070321719040">"তৃতীয় কার্যক্ষেত্র <xliff:g id="LABEL">%1$s</xliff:g>"</string>
- <string name="lock_to_app_toast" msgid="1420543809500606964">"এই স্ক্রীনটিকে আনপিন করতে, \'ফিরুন\' স্পর্শ করুন এবং ধরে রাখুন৷"</string>
+ <!-- no translation found for lock_to_app_toast (7693684144593484) -->
+ <skip />
<string name="lock_to_app_toast_locked" msgid="9125176335701699164">"অ্যাপ্লিকেশান পিন করা আছে: এই ডিভাইস এটিকে পিনমুক্ত করা মঞ্জুরিপ্রাপ্ত নয়৷"</string>
<string name="lock_to_app_start" msgid="6643342070839862795">"স্ক্রীন পিন করা হয়েছে"</string>
<string name="lock_to_app_exit" msgid="8598219838213787430">"পিন না করা স্ক্রীন"</string>
diff --git a/core/res/res/values-bs-rBA/strings.xml b/core/res/res/values-bs-rBA/strings.xml
index 5936d3a..4cf2bb0 100644
--- a/core/res/res/values-bs-rBA/strings.xml
+++ b/core/res/res/values-bs-rBA/strings.xml
@@ -1585,7 +1585,8 @@
<string name="managed_profile_label_badge" msgid="2355652472854327647">"Poslovni <xliff:g id="LABEL">%1$s</xliff:g>"</string>
<string name="managed_profile_label_badge_2" msgid="5048136430082124036">"2. poslovni <xliff:g id="LABEL">%1$s</xliff:g>"</string>
<string name="managed_profile_label_badge_3" msgid="2808305070321719040">"3. poslovni <xliff:g id="LABEL">%1$s</xliff:g>"</string>
- <string name="lock_to_app_toast" msgid="1420543809500606964">"Da biste otkačili ovaj ekran, dodirnite i držite dugme Nazad."</string>
+ <!-- no translation found for lock_to_app_toast (7693684144593484) -->
+ <skip />
<string name="lock_to_app_toast_locked" msgid="9125176335701699164">"Aplikacija je prikačena. Na ovom uređaju nije dozvoljeno otkačivanje."</string>
<string name="lock_to_app_start" msgid="6643342070839862795">"Ekran je zakačen"</string>
<string name="lock_to_app_exit" msgid="8598219838213787430">"Ekran je otkačen"</string>
diff --git a/core/res/res/values-ca/strings.xml b/core/res/res/values-ca/strings.xml
index 4a61fc1..db40015 100644
--- a/core/res/res/values-ca/strings.xml
+++ b/core/res/res/values-ca/strings.xml
@@ -1559,7 +1559,8 @@
<string name="managed_profile_label_badge" msgid="2355652472854327647">"<xliff:g id="LABEL">%1$s</xliff:g> de la feina"</string>
<string name="managed_profile_label_badge_2" msgid="5048136430082124036">"2n <xliff:g id="LABEL">%1$s</xliff:g> de la feina"</string>
<string name="managed_profile_label_badge_3" msgid="2808305070321719040">"3r <xliff:g id="LABEL">%1$s</xliff:g> de la feina"</string>
- <string name="lock_to_app_toast" msgid="1420543809500606964">"Toca i mantén premuda l\'opció Enrere per deixar de fixar aquesta pantalla."</string>
+ <!-- no translation found for lock_to_app_toast (7693684144593484) -->
+ <skip />
<string name="lock_to_app_toast_locked" msgid="9125176335701699164">"S\'ha fixat l\'aplicació. En aquest dispositiu no es permet anul·lar-ne la fixació."</string>
<string name="lock_to_app_start" msgid="6643342070839862795">"Pantalla fixada"</string>
<string name="lock_to_app_exit" msgid="8598219838213787430">"Fixació de la pantalla anul·lada"</string>
diff --git a/core/res/res/values-cs/strings.xml b/core/res/res/values-cs/strings.xml
index d5619f9..05b0914 100644
--- a/core/res/res/values-cs/strings.xml
+++ b/core/res/res/values-cs/strings.xml
@@ -1607,7 +1607,8 @@
<string name="managed_profile_label_badge" msgid="2355652472854327647">"Pracovní <xliff:g id="LABEL">%1$s</xliff:g>"</string>
<string name="managed_profile_label_badge_2" msgid="5048136430082124036">"2. <xliff:g id="LABEL">%1$s</xliff:g> do práce"</string>
<string name="managed_profile_label_badge_3" msgid="2808305070321719040">"3. <xliff:g id="LABEL">%1$s</xliff:g> do práce"</string>
- <string name="lock_to_app_toast" msgid="1420543809500606964">"Chcete-li tuto obrazovku uvolnit, klepněte na tlačítko Zpět a podržte jej."</string>
+ <!-- no translation found for lock_to_app_toast (7693684144593484) -->
+ <skip />
<string name="lock_to_app_toast_locked" msgid="9125176335701699164">"Aplikace je připnutá: Odepnutí v tomto zařízení není povoleno."</string>
<string name="lock_to_app_start" msgid="6643342070839862795">"Obrazovka připnuta"</string>
<string name="lock_to_app_exit" msgid="8598219838213787430">"Obrazovka uvolněna"</string>
diff --git a/core/res/res/values-da/strings.xml b/core/res/res/values-da/strings.xml
index 89b546f..498ba46 100644
--- a/core/res/res/values-da/strings.xml
+++ b/core/res/res/values-da/strings.xml
@@ -228,8 +228,8 @@
<string name="bugreport_option_full_title" msgid="6354382025840076439">"Fuld rapport"</string>
<string name="bugreport_option_full_summary" msgid="7210859858969115745">"Brug denne mulighed for at gribe mindst muligt ind, når enheden ikke reagerer eller er for langsom, eller når du har brug for alle rapportsektioner. Du har ikke mulighed for at angive flere oplysninger eller tage yderligere skærmbilleder."</string>
<plurals name="bugreport_countdown" formatted="false" msgid="6878900193900090368">
- <item quantity="one">Der tages et skærmbillede til fejlrapporten om <xliff:g id="NUMBER_1">%d</xliff:g> sekund.</item>
- <item quantity="other">Der tages et skærmbillede til fejlrapporten om <xliff:g id="NUMBER_1">%d</xliff:g> sekunder.</item>
+ <item quantity="one">Der tages et screenshot til fejlrapporten om <xliff:g id="NUMBER_1">%d</xliff:g> sekund.</item>
+ <item quantity="other">Der tages et screenshot til fejlrapporten om <xliff:g id="NUMBER_1">%d</xliff:g> sekunder.</item>
</plurals>
<string name="global_action_toggle_silent_mode" msgid="8219525344246810925">"Lydløs"</string>
<string name="global_action_silent_mode_on_status" msgid="3289841937003758806">"Lyden er slået FRA"</string>
@@ -1559,7 +1559,8 @@
<string name="managed_profile_label_badge" msgid="2355652472854327647">"<xliff:g id="LABEL">%1$s</xliff:g> – arbejde"</string>
<string name="managed_profile_label_badge_2" msgid="5048136430082124036">"2. <xliff:g id="LABEL">%1$s</xliff:g> til arbejde"</string>
<string name="managed_profile_label_badge_3" msgid="2808305070321719040">"3. <xliff:g id="LABEL">%1$s</xliff:g> til arbejde"</string>
- <string name="lock_to_app_toast" msgid="1420543809500606964">"Hvis du vil frigøre dette skærmbillede, skal du trykke på Tilbage og holde fingeren nede."</string>
+ <!-- no translation found for lock_to_app_toast (7693684144593484) -->
+ <skip />
<string name="lock_to_app_toast_locked" msgid="9125176335701699164">"Appen er fastgjort: Det er ikke tilladt at frigøre den på denne enhed."</string>
<string name="lock_to_app_start" msgid="6643342070839862795">"Skærmen blev fastgjort"</string>
<string name="lock_to_app_exit" msgid="8598219838213787430">"Skærmen blev frigjort"</string>
diff --git a/core/res/res/values-de/strings.xml b/core/res/res/values-de/strings.xml
index 79152fa..fda4c1b 100644
--- a/core/res/res/values-de/strings.xml
+++ b/core/res/res/values-de/strings.xml
@@ -1559,7 +1559,8 @@
<string name="managed_profile_label_badge" msgid="2355652472854327647">"<xliff:g id="LABEL">%1$s</xliff:g> (geschäftlich)"</string>
<string name="managed_profile_label_badge_2" msgid="5048136430082124036">"2. <xliff:g id="LABEL">%1$s</xliff:g> (geschäftlich)"</string>
<string name="managed_profile_label_badge_3" msgid="2808305070321719040">"3. <xliff:g id="LABEL">%1$s</xliff:g> (geschäftlich)"</string>
- <string name="lock_to_app_toast" msgid="1420543809500606964">"Um die Fixierung dieses Bildschirms aufzuheben, \"Zurück\" berühren und halten."</string>
+ <!-- no translation found for lock_to_app_toast (7693684144593484) -->
+ <skip />
<string name="lock_to_app_toast_locked" msgid="9125176335701699164">"Die App ist fixiert. Das Aufheben der Fixierung ist auf diesem Gerät nicht zulässig."</string>
<string name="lock_to_app_start" msgid="6643342070839862795">"Bildschirm fixiert"</string>
<string name="lock_to_app_exit" msgid="8598219838213787430">"Bildschirm gelöst"</string>
diff --git a/core/res/res/values-el/strings.xml b/core/res/res/values-el/strings.xml
index d89932d..6e01478 100644
--- a/core/res/res/values-el/strings.xml
+++ b/core/res/res/values-el/strings.xml
@@ -1559,7 +1559,8 @@
<string name="managed_profile_label_badge" msgid="2355652472854327647">"Εργασία <xliff:g id="LABEL">%1$s</xliff:g>"</string>
<string name="managed_profile_label_badge_2" msgid="5048136430082124036">"<xliff:g id="LABEL">%1$s</xliff:g> εργασίας 2"</string>
<string name="managed_profile_label_badge_3" msgid="2808305070321719040">"<xliff:g id="LABEL">%1$s</xliff:g> εργασίας 3"</string>
- <string name="lock_to_app_toast" msgid="1420543809500606964">"Για να ξεκαρφιτσώσετε αυτήν την οθόνη, αγγίξτε παρατεταμένα \"Επιστροφή\"."</string>
+ <!-- no translation found for lock_to_app_toast (7693684144593484) -->
+ <skip />
<string name="lock_to_app_toast_locked" msgid="9125176335701699164">"Η εφαρμογή καρφιτσώθηκε: Το ξεκαρφίτσωμα δεν επιτρέπεται σε αυτήν τη συσκευή."</string>
<string name="lock_to_app_start" msgid="6643342070839862795">"Η οθόνη καρφιτσώθηκε"</string>
<string name="lock_to_app_exit" msgid="8598219838213787430">"Η οθόνη ξεκαρφιτσώθηκε"</string>
diff --git a/core/res/res/values-en-rAU/strings.xml b/core/res/res/values-en-rAU/strings.xml
index 071a302..b5d2d50 100644
--- a/core/res/res/values-en-rAU/strings.xml
+++ b/core/res/res/values-en-rAU/strings.xml
@@ -1559,7 +1559,8 @@
<string name="managed_profile_label_badge" msgid="2355652472854327647">"Work <xliff:g id="LABEL">%1$s</xliff:g>"</string>
<string name="managed_profile_label_badge_2" msgid="5048136430082124036">"2nd Work <xliff:g id="LABEL">%1$s</xliff:g>"</string>
<string name="managed_profile_label_badge_3" msgid="2808305070321719040">"3rd Work <xliff:g id="LABEL">%1$s</xliff:g>"</string>
- <string name="lock_to_app_toast" msgid="1420543809500606964">"To unpin this screen, touch & hold Back."</string>
+ <!-- no translation found for lock_to_app_toast (7693684144593484) -->
+ <skip />
<string name="lock_to_app_toast_locked" msgid="9125176335701699164">"App is pinned: unpinning isn\'t allowed on this device."</string>
<string name="lock_to_app_start" msgid="6643342070839862795">"Screen pinned"</string>
<string name="lock_to_app_exit" msgid="8598219838213787430">"Screen unpinned"</string>
diff --git a/core/res/res/values-en-rGB/strings.xml b/core/res/res/values-en-rGB/strings.xml
index 071a302..b5d2d50 100644
--- a/core/res/res/values-en-rGB/strings.xml
+++ b/core/res/res/values-en-rGB/strings.xml
@@ -1559,7 +1559,8 @@
<string name="managed_profile_label_badge" msgid="2355652472854327647">"Work <xliff:g id="LABEL">%1$s</xliff:g>"</string>
<string name="managed_profile_label_badge_2" msgid="5048136430082124036">"2nd Work <xliff:g id="LABEL">%1$s</xliff:g>"</string>
<string name="managed_profile_label_badge_3" msgid="2808305070321719040">"3rd Work <xliff:g id="LABEL">%1$s</xliff:g>"</string>
- <string name="lock_to_app_toast" msgid="1420543809500606964">"To unpin this screen, touch & hold Back."</string>
+ <!-- no translation found for lock_to_app_toast (7693684144593484) -->
+ <skip />
<string name="lock_to_app_toast_locked" msgid="9125176335701699164">"App is pinned: unpinning isn\'t allowed on this device."</string>
<string name="lock_to_app_start" msgid="6643342070839862795">"Screen pinned"</string>
<string name="lock_to_app_exit" msgid="8598219838213787430">"Screen unpinned"</string>
diff --git a/core/res/res/values-en-rIN/strings.xml b/core/res/res/values-en-rIN/strings.xml
index 071a302..b5d2d50 100644
--- a/core/res/res/values-en-rIN/strings.xml
+++ b/core/res/res/values-en-rIN/strings.xml
@@ -1559,7 +1559,8 @@
<string name="managed_profile_label_badge" msgid="2355652472854327647">"Work <xliff:g id="LABEL">%1$s</xliff:g>"</string>
<string name="managed_profile_label_badge_2" msgid="5048136430082124036">"2nd Work <xliff:g id="LABEL">%1$s</xliff:g>"</string>
<string name="managed_profile_label_badge_3" msgid="2808305070321719040">"3rd Work <xliff:g id="LABEL">%1$s</xliff:g>"</string>
- <string name="lock_to_app_toast" msgid="1420543809500606964">"To unpin this screen, touch & hold Back."</string>
+ <!-- no translation found for lock_to_app_toast (7693684144593484) -->
+ <skip />
<string name="lock_to_app_toast_locked" msgid="9125176335701699164">"App is pinned: unpinning isn\'t allowed on this device."</string>
<string name="lock_to_app_start" msgid="6643342070839862795">"Screen pinned"</string>
<string name="lock_to_app_exit" msgid="8598219838213787430">"Screen unpinned"</string>
diff --git a/core/res/res/values-es-rUS/strings.xml b/core/res/res/values-es-rUS/strings.xml
index cbff5bb..14c2850 100644
--- a/core/res/res/values-es-rUS/strings.xml
+++ b/core/res/res/values-es-rUS/strings.xml
@@ -1559,7 +1559,8 @@
<string name="managed_profile_label_badge" msgid="2355652472854327647">"<xliff:g id="LABEL">%1$s</xliff:g> de trabajo"</string>
<string name="managed_profile_label_badge_2" msgid="5048136430082124036">"<xliff:g id="LABEL">%1$s</xliff:g> de trabajo 2"</string>
<string name="managed_profile_label_badge_3" msgid="2808305070321719040">"<xliff:g id="LABEL">%1$s</xliff:g> de trabajo 3"</string>
- <string name="lock_to_app_toast" msgid="1420543809500606964">"Para dejar de fijar esta pantalla, mantén presionado Atrás."</string>
+ <!-- no translation found for lock_to_app_toast (7693684144593484) -->
+ <skip />
<string name="lock_to_app_toast_locked" msgid="9125176335701699164">"La aplicación está fijada, no se puede anular la fijación en este dispositivo."</string>
<string name="lock_to_app_start" msgid="6643342070839862795">"Pantalla fija"</string>
<string name="lock_to_app_exit" msgid="8598219838213787430">"Pantalla no fija"</string>
diff --git a/core/res/res/values-es/strings.xml b/core/res/res/values-es/strings.xml
index 93c3079..26b8bb4 100644
--- a/core/res/res/values-es/strings.xml
+++ b/core/res/res/values-es/strings.xml
@@ -1559,7 +1559,8 @@
<string name="managed_profile_label_badge" msgid="2355652472854327647">"<xliff:g id="LABEL">%1$s</xliff:g> de trabajo"</string>
<string name="managed_profile_label_badge_2" msgid="5048136430082124036">"<xliff:g id="LABEL">%1$s</xliff:g> de trabajo 2"</string>
<string name="managed_profile_label_badge_3" msgid="2808305070321719040">"<xliff:g id="LABEL">%1$s</xliff:g> de trabajo 3"</string>
- <string name="lock_to_app_toast" msgid="1420543809500606964">"Mantén pulsado el botón Atrás para dejar de fijar esta pantalla."</string>
+ <!-- no translation found for lock_to_app_toast (7693684144593484) -->
+ <skip />
<string name="lock_to_app_toast_locked" msgid="9125176335701699164">"La aplicación está fijada: no se puede deshacer la fijación en este dispositivo."</string>
<string name="lock_to_app_start" msgid="6643342070839862795">"Pantalla fijada"</string>
<string name="lock_to_app_exit" msgid="8598219838213787430">"La pantalla ya no está fija"</string>
diff --git a/core/res/res/values-et-rEE/strings.xml b/core/res/res/values-et-rEE/strings.xml
index 7c6c562..4b06f58 100644
--- a/core/res/res/values-et-rEE/strings.xml
+++ b/core/res/res/values-et-rEE/strings.xml
@@ -1559,7 +1559,8 @@
<string name="managed_profile_label_badge" msgid="2355652472854327647">"Töö <xliff:g id="LABEL">%1$s</xliff:g>"</string>
<string name="managed_profile_label_badge_2" msgid="5048136430082124036">"2. töö <xliff:g id="LABEL">%1$s</xliff:g>"</string>
<string name="managed_profile_label_badge_3" msgid="2808305070321719040">"3. töö <xliff:g id="LABEL">%1$s</xliff:g>"</string>
- <string name="lock_to_app_toast" msgid="1420543809500606964">"Ekraani vabastamiseks puudutage pikalt nuppu Tagasi."</string>
+ <!-- no translation found for lock_to_app_toast (7693684144593484) -->
+ <skip />
<string name="lock_to_app_toast_locked" msgid="9125176335701699164">"Rakendus on kinnitatud: vabastamine pole selles seadmes lubatud."</string>
<string name="lock_to_app_start" msgid="6643342070839862795">"Ekraan on kinnitatud"</string>
<string name="lock_to_app_exit" msgid="8598219838213787430">"Ekraan on vabastatud"</string>
diff --git a/core/res/res/values-eu-rES/strings.xml b/core/res/res/values-eu-rES/strings.xml
index 98f0072..89d6549 100644
--- a/core/res/res/values-eu-rES/strings.xml
+++ b/core/res/res/values-eu-rES/strings.xml
@@ -1559,7 +1559,8 @@
<string name="managed_profile_label_badge" msgid="2355652472854327647">"Laneko <xliff:g id="LABEL">%1$s</xliff:g>"</string>
<string name="managed_profile_label_badge_2" msgid="5048136430082124036">"Laneko 2. <xliff:g id="LABEL">%1$s</xliff:g>"</string>
<string name="managed_profile_label_badge_3" msgid="2808305070321719040">"Laneko 3. <xliff:g id="LABEL">%1$s</xliff:g>"</string>
- <string name="lock_to_app_toast" msgid="1420543809500606964">"Pantailari aingura kentzeko, eduki sakatuta Atzera botoia."</string>
+ <!-- no translation found for lock_to_app_toast (7693684144593484) -->
+ <skip />
<string name="lock_to_app_toast_locked" msgid="9125176335701699164">"Aplikazioa ainguratuta dago. Gailu honetan ezin da aingura kendu."</string>
<string name="lock_to_app_start" msgid="6643342070839862795">"Pantaila ainguratu da"</string>
<string name="lock_to_app_exit" msgid="8598219838213787430">"Aingura kendu zaio pantailari"</string>
diff --git a/core/res/res/values-fa/strings.xml b/core/res/res/values-fa/strings.xml
index 0e6a982..ef9ef07 100644
--- a/core/res/res/values-fa/strings.xml
+++ b/core/res/res/values-fa/strings.xml
@@ -1559,7 +1559,8 @@
<string name="managed_profile_label_badge" msgid="2355652472854327647">"<xliff:g id="LABEL">%1$s</xliff:g> محل کار"</string>
<string name="managed_profile_label_badge_2" msgid="5048136430082124036">"کار دوم <xliff:g id="LABEL">%1$s</xliff:g>"</string>
<string name="managed_profile_label_badge_3" msgid="2808305070321719040">"کار سوم <xliff:g id="LABEL">%1$s</xliff:g>"</string>
- <string name="lock_to_app_toast" msgid="1420543809500606964">"برای برداشتن پین این صفحه، «برگشت» را لمس کنید و نگه دارید."</string>
+ <!-- no translation found for lock_to_app_toast (7693684144593484) -->
+ <skip />
<string name="lock_to_app_toast_locked" msgid="9125176335701699164">"برنامه پین شده است: برداشتن پین در این دستگاه مجاز نیست."</string>
<string name="lock_to_app_start" msgid="6643342070839862795">"صفحه پین شد"</string>
<string name="lock_to_app_exit" msgid="8598219838213787430">"پین صفحه برداشته شد"</string>
diff --git a/core/res/res/values-fi/strings.xml b/core/res/res/values-fi/strings.xml
index 74b4c8b..0cddf14 100644
--- a/core/res/res/values-fi/strings.xml
+++ b/core/res/res/values-fi/strings.xml
@@ -1559,7 +1559,8 @@
<string name="managed_profile_label_badge" msgid="2355652472854327647">"<xliff:g id="LABEL">%1$s</xliff:g> (työ)"</string>
<string name="managed_profile_label_badge_2" msgid="5048136430082124036">"Toinen <xliff:g id="LABEL">%1$s</xliff:g>, työ"</string>
<string name="managed_profile_label_badge_3" msgid="2808305070321719040">"Kolmas <xliff:g id="LABEL">%1$s</xliff:g>, työ"</string>
- <string name="lock_to_app_toast" msgid="1420543809500606964">"Irrota näyttö koskettamalla Takaisin-painiketta pitkään."</string>
+ <!-- no translation found for lock_to_app_toast (7693684144593484) -->
+ <skip />
<string name="lock_to_app_toast_locked" msgid="9125176335701699164">"Sovellus on kiinnitetty. Irrottaminen ei ole sallittua tällä laitteella."</string>
<string name="lock_to_app_start" msgid="6643342070839862795">"Näyttö kiinnitetty"</string>
<string name="lock_to_app_exit" msgid="8598219838213787430">"Näyttö irrotettu"</string>
diff --git a/core/res/res/values-fr-rCA/strings.xml b/core/res/res/values-fr-rCA/strings.xml
index cd23762..3957343 100644
--- a/core/res/res/values-fr-rCA/strings.xml
+++ b/core/res/res/values-fr-rCA/strings.xml
@@ -1559,7 +1559,8 @@
<string name="managed_profile_label_badge" msgid="2355652472854327647">"<xliff:g id="LABEL">%1$s</xliff:g> (travail)"</string>
<string name="managed_profile_label_badge_2" msgid="5048136430082124036">"2e <xliff:g id="LABEL">%1$s</xliff:g> professionnel(le)"</string>
<string name="managed_profile_label_badge_3" msgid="2808305070321719040">"3e <xliff:g id="LABEL">%1$s</xliff:g> professionnel(le)"</string>
- <string name="lock_to_app_toast" msgid="1420543809500606964">"Pour annuler l\'épinglage de cet écran, maintenez enfoncée la touche Retour."</string>
+ <!-- no translation found for lock_to_app_toast (7693684144593484) -->
+ <skip />
<string name="lock_to_app_toast_locked" msgid="9125176335701699164">"L\'application est épinglée : l\'annulation de l\'épinglage n\'est pas autorisée sur cet appareil."</string>
<string name="lock_to_app_start" msgid="6643342070839862795">"Écran épinglé"</string>
<string name="lock_to_app_exit" msgid="8598219838213787430">"Épinglage d\'écran annulé"</string>
diff --git a/core/res/res/values-fr/strings.xml b/core/res/res/values-fr/strings.xml
index 1e96137..71eb8c2 100644
--- a/core/res/res/values-fr/strings.xml
+++ b/core/res/res/values-fr/strings.xml
@@ -1559,7 +1559,8 @@
<string name="managed_profile_label_badge" msgid="2355652472854327647">"<xliff:g id="LABEL">%1$s</xliff:g> (travail)"</string>
<string name="managed_profile_label_badge_2" msgid="5048136430082124036">"2e <xliff:g id="LABEL">%1$s</xliff:g> professionnelle"</string>
<string name="managed_profile_label_badge_3" msgid="2808305070321719040">"3e <xliff:g id="LABEL">%1$s</xliff:g> professionnelle"</string>
- <string name="lock_to_app_toast" msgid="1420543809500606964">"Pour annuler l\'épinglage, appuyez de manière prolongée sur \"Retour\"."</string>
+ <!-- no translation found for lock_to_app_toast (7693684144593484) -->
+ <skip />
<string name="lock_to_app_toast_locked" msgid="9125176335701699164">"L\'application est épinglée. L\'annulation de l\'épinglage n\'est pas autorisée sur cet appareil."</string>
<string name="lock_to_app_start" msgid="6643342070839862795">"Écran épinglé."</string>
<string name="lock_to_app_exit" msgid="8598219838213787430">"Épinglage d\'écran annulé."</string>
diff --git a/core/res/res/values-gl-rES/strings.xml b/core/res/res/values-gl-rES/strings.xml
index b59057f..65e90e4 100644
--- a/core/res/res/values-gl-rES/strings.xml
+++ b/core/res/res/values-gl-rES/strings.xml
@@ -1559,7 +1559,8 @@
<string name="managed_profile_label_badge" msgid="2355652472854327647">"<xliff:g id="LABEL">%1$s</xliff:g> do traballo"</string>
<string name="managed_profile_label_badge_2" msgid="5048136430082124036">"2.º <xliff:g id="LABEL">%1$s</xliff:g> do traballo"</string>
<string name="managed_profile_label_badge_3" msgid="2808305070321719040">"3.º <xliff:g id="LABEL">%1$s</xliff:g> do traballo"</string>
- <string name="lock_to_app_toast" msgid="1420543809500606964">"Para soltar a pantalla, mantén premido Volver."</string>
+ <!-- no translation found for lock_to_app_toast (7693684144593484) -->
+ <skip />
<string name="lock_to_app_toast_locked" msgid="9125176335701699164">"A aplicación está fixada: non se permite soltala neste dispositivo."</string>
<string name="lock_to_app_start" msgid="6643342070839862795">"Pantalla fixada"</string>
<string name="lock_to_app_exit" msgid="8598219838213787430">"Pantalla desactivada"</string>
diff --git a/core/res/res/values-gu-rIN/strings.xml b/core/res/res/values-gu-rIN/strings.xml
index f114028..bfb84b3 100644
--- a/core/res/res/values-gu-rIN/strings.xml
+++ b/core/res/res/values-gu-rIN/strings.xml
@@ -1559,7 +1559,8 @@
<string name="managed_profile_label_badge" msgid="2355652472854327647">"કાર્યાલય <xliff:g id="LABEL">%1$s</xliff:g>"</string>
<string name="managed_profile_label_badge_2" msgid="5048136430082124036">"2જું કાર્ય <xliff:g id="LABEL">%1$s</xliff:g>"</string>
<string name="managed_profile_label_badge_3" msgid="2808305070321719040">"3જું કાર્ય <xliff:g id="LABEL">%1$s</xliff:g>"</string>
- <string name="lock_to_app_toast" msgid="1420543809500606964">"આ સ્ક્રીનને અનપિન કરવા માટે, પાછળને ટચ કરીને પકડી રાખો."</string>
+ <!-- no translation found for lock_to_app_toast (7693684144593484) -->
+ <skip />
<string name="lock_to_app_toast_locked" msgid="9125176335701699164">"ઍપ્લિકેશન પિન કરેલ છે. આ ઉપકરણ પર અનપિન કરવાની મંજૂરી નથી."</string>
<string name="lock_to_app_start" msgid="6643342070839862795">"સ્ક્રીન પિન કરી"</string>
<string name="lock_to_app_exit" msgid="8598219838213787430">"સ્ક્રીન અનપિન કરી"</string>
diff --git a/core/res/res/values-hi/strings.xml b/core/res/res/values-hi/strings.xml
index e291552..05f8bd2 100644
--- a/core/res/res/values-hi/strings.xml
+++ b/core/res/res/values-hi/strings.xml
@@ -417,7 +417,7 @@
<string name="permlab_accessWifiState" msgid="5202012949247040011">"वाई-फ़ाई कनेक्शन देखें"</string>
<string name="permdesc_accessWifiState" msgid="5002798077387803726">"ऐप्स को वाई-फ़ाई नेटवर्क के बारे में जानकारी, जैसे WI-Fi सक्षम है या नहीं और कनेक्ट किए गए वाई-फ़ाई डिवाइस के नाम, देखने देता है."</string>
<string name="permlab_changeWifiState" msgid="6550641188749128035">"वाई-फ़ाई से कनेक्ट और डिस्कनेक्ट करें"</string>
- <string name="permdesc_changeWifiState" msgid="7137950297386127533">"ऐप्स को वाई-फ़ाई पहुंच बिंदुओं से कनेक्ट और डिस्कनेक्ट करने और वाई-फ़ाई नेटवर्क के लिए डिवाइस कॉन्फ़िगरेशन में परिवर्तन करने देता है."</string>
+ <string name="permdesc_changeWifiState" msgid="7137950297386127533">"ऐप्स को वाई-फ़ाई पहुंच बिंदुओं से कनेक्ट और डिसकनेक्ट करने और वाई-फ़ाई नेटवर्क के लिए डिवाइस कॉन्फ़िगरेशन में परिवर्तन करने देता है."</string>
<string name="permlab_changeWifiMulticastState" msgid="1368253871483254784">"वाई-फ़ाई मल्टीकास्ट प्राप्ति को अनुमति दें"</string>
<string name="permdesc_changeWifiMulticastState" product="tablet" msgid="7969774021256336548">"ऐप्स को वाई-फ़ाई नेटवर्क पर मल्टीकास्ट पते के उपयोग से केवल आपके टेबलेट पर ही नहीं, बल्कि सभी डिवाइस पर भेजे गए पैकेट प्राप्त करने देता है. यह गैर-मल्टीकास्ट मोड से अधिक पावर का उपयोग करता है."</string>
<string name="permdesc_changeWifiMulticastState" product="tv" msgid="9031975661145014160">"ऐप को मल्टीकास्ट पतों का उपयोग करके ना केवल आपके टीवी को, बल्कि वाई-फ़ाई पर मौजूद सभी डिवाइसों को पैकेट भेजने और प्राप्त करने देती है. इसमें गैर-मल्टीकास्ट मोड की अपेक्षा अधिक पावर का उपयोग होता है."</string>
@@ -426,7 +426,7 @@
<string name="permdesc_bluetoothAdmin" product="tablet" msgid="6921177471748882137">"किसी ऐप्स को स्थानीय ब्लूटूथ टेबलेट कॉन्फ़िगर करने की और रिमोट डिवाइस के साथ खोजने और युग्मित करने देता है."</string>
<string name="permdesc_bluetoothAdmin" product="tv" msgid="3373125682645601429">"ऐप को स्थानीय ब्लूटूथ टीवी कॉन्फ़िगर करने देती है और दूरस्थ डिवाइसों को खोजने और उनसे युग्मित करने देती है."</string>
<string name="permdesc_bluetoothAdmin" product="default" msgid="8931682159331542137">"ऐप्स को स्थानीय ब्लूटूथ फ़ोन कॉन्फ़िगर करने देता है, और रिमोट डिवाइस के साथ खोजने और युग्मित करने देता है."</string>
- <string name="permlab_accessWimaxState" msgid="4195907010610205703">"WiMAX से कनेक्ट और डिस्कनेक्ट करें"</string>
+ <string name="permlab_accessWimaxState" msgid="4195907010610205703">"WiMAX से कनेक्ट और डिसकनेक्ट करें"</string>
<string name="permdesc_accessWimaxState" msgid="6360102877261978887">"ऐप्स को WiMAX सक्षम है या नहीं और कनेक्ट किए गए किसी WiMAX नेटवर्क के बारे में जानकारी निर्धारित करने देता है."</string>
<string name="permlab_changeWimaxState" msgid="340465839241528618">"WiMAX स्थिति बदलें"</string>
<string name="permdesc_changeWimaxState" product="tablet" msgid="3156456504084201805">"ऐप्स को WiMAX नेटवर्क से टेबलेट को कनेक्ट और डिस्कनेक्ट करने देता है."</string>
@@ -1103,9 +1103,9 @@
<string name="wifi_p2p_to_message" msgid="248968974522044099">"प्रति:"</string>
<string name="wifi_p2p_enter_pin_message" msgid="5920929550367828970">"आवश्यक पिन लिखें:"</string>
<string name="wifi_p2p_show_pin_message" msgid="8530563323880921094">"पिन:"</string>
- <string name="wifi_p2p_frequency_conflict_message" product="tablet" msgid="8012981257742232475">"<xliff:g id="DEVICE_NAME">%1$s</xliff:g> से कनेक्ट रहने पर टेबलेट वाई-फ़ाई से अस्थायी रूप से डिस्कनेक्ट हो जाएगा"</string>
+ <string name="wifi_p2p_frequency_conflict_message" product="tablet" msgid="8012981257742232475">"<xliff:g id="DEVICE_NAME">%1$s</xliff:g> से कनेक्ट रहने पर टेबलेट वाई-फ़ाई से अस्थायी रूप से डिसकनेक्ट हो जाएगा"</string>
<string name="wifi_p2p_frequency_conflict_message" product="tv" msgid="3087858235069421128">"जब टीवी <xliff:g id="DEVICE_NAME">%1$s</xliff:g> से कनेक्ट होगा तब वह वाई-फ़ाई से अस्थायी रूप से डिस्कनेक्ट हो जाएगा"</string>
- <string name="wifi_p2p_frequency_conflict_message" product="default" msgid="7363907213787469151">"फ़ोन <xliff:g id="DEVICE_NAME">%1$s</xliff:g> से कनेक्ट रहते समय वाई-फ़ाई से अस्थायी रूप से डिस्कनेक्ट हो जाएगा"</string>
+ <string name="wifi_p2p_frequency_conflict_message" product="default" msgid="7363907213787469151">"फ़ोन <xliff:g id="DEVICE_NAME">%1$s</xliff:g> से कनेक्ट रहते समय वाई-फ़ाई से अस्थायी रूप से डिसकनेक्ट हो जाएगा"</string>
<string name="select_character" msgid="3365550120617701745">"वर्ण सम्मिलित करें"</string>
<string name="sms_control_title" msgid="7296612781128917719">"SMS संदेश भेज रहा है"</string>
<string name="sms_control_message" msgid="3867899169651496433">"<b><xliff:g id="APP_NAME">%1$s</xliff:g></b> बड़ी संख्या में SMS संदेश भेज रहा है. क्या आप इस ऐप्स को संदेश भेजना जारी रखने देना चाहते हैं?"</string>
@@ -1379,7 +1379,7 @@
<string name="media_route_chooser_title_for_remote_display" msgid="3395541745872017583">"स्क्रीन को डिवाइस में कास्ट करें"</string>
<string name="media_route_chooser_searching" msgid="4776236202610828706">"डिवाइस खोजे जा रहे हैं…"</string>
<string name="media_route_chooser_extended_settings" msgid="87015534236701604">"सेटिंग"</string>
- <string name="media_route_controller_disconnect" msgid="8966120286374158649">"डिस्कनेक्ट करें"</string>
+ <string name="media_route_controller_disconnect" msgid="8966120286374158649">"डिसकनेक्ट करें"</string>
<string name="media_route_status_scanning" msgid="7279908761758293783">"स्कैन कर रहा है..."</string>
<string name="media_route_status_connecting" msgid="6422571716007825440">"कनेक्ट हो रहा है..."</string>
<string name="media_route_status_available" msgid="6983258067194649391">"उपलब्ध"</string>
@@ -1559,7 +1559,8 @@
<string name="managed_profile_label_badge" msgid="2355652472854327647">"कार्यस्थल का <xliff:g id="LABEL">%1$s</xliff:g>"</string>
<string name="managed_profile_label_badge_2" msgid="5048136430082124036">"दूसरा कार्य <xliff:g id="LABEL">%1$s</xliff:g>"</string>
<string name="managed_profile_label_badge_3" msgid="2808305070321719040">"तीसरा कार्य <xliff:g id="LABEL">%1$s</xliff:g>"</string>
- <string name="lock_to_app_toast" msgid="1420543809500606964">"इस स्क्रीन को अनपिन करने के लिए, वापस जाएं को स्पर्श करके रखें."</string>
+ <!-- no translation found for lock_to_app_toast (7693684144593484) -->
+ <skip />
<string name="lock_to_app_toast_locked" msgid="9125176335701699164">"ऐप पिन किया गया है: इस डिवाइस पर अनपिन करने की अनुमति नहीं है."</string>
<string name="lock_to_app_start" msgid="6643342070839862795">"स्क्रीन पिन की गई"</string>
<string name="lock_to_app_exit" msgid="8598219838213787430">"स्क्रीन अनपिन की गई"</string>
diff --git a/core/res/res/values-hr/strings.xml b/core/res/res/values-hr/strings.xml
index a403769..9bd61c0 100644
--- a/core/res/res/values-hr/strings.xml
+++ b/core/res/res/values-hr/strings.xml
@@ -1583,7 +1583,8 @@
<string name="managed_profile_label_badge" msgid="2355652472854327647">"<xliff:g id="LABEL">%1$s</xliff:g> za posao"</string>
<string name="managed_profile_label_badge_2" msgid="5048136430082124036">"2. <xliff:g id="LABEL">%1$s</xliff:g> za posao"</string>
<string name="managed_profile_label_badge_3" msgid="2808305070321719040">"3. <xliff:g id="LABEL">%1$s</xliff:g> za posao"</string>
- <string name="lock_to_app_toast" msgid="1420543809500606964">"Da biste otkvačili ovaj zaslon, dodirnite i zadržite Natrag."</string>
+ <!-- no translation found for lock_to_app_toast (7693684144593484) -->
+ <skip />
<string name="lock_to_app_toast_locked" msgid="9125176335701699164">"Aplikacija je prikvačena: otkvačivanje nije dopušteno na tom uređaju."</string>
<string name="lock_to_app_start" msgid="6643342070839862795">"Zaslon je pričvršćen"</string>
<string name="lock_to_app_exit" msgid="8598219838213787430">"Zaslon je otkvačen"</string>
diff --git a/core/res/res/values-hu/strings.xml b/core/res/res/values-hu/strings.xml
index f29cced..814e4e2 100644
--- a/core/res/res/values-hu/strings.xml
+++ b/core/res/res/values-hu/strings.xml
@@ -1559,7 +1559,8 @@
<string name="managed_profile_label_badge" msgid="2355652472854327647">"Munkahelyi <xliff:g id="LABEL">%1$s</xliff:g>"</string>
<string name="managed_profile_label_badge_2" msgid="5048136430082124036">"2. munkahelyi <xliff:g id="LABEL">%1$s</xliff:g>"</string>
<string name="managed_profile_label_badge_3" msgid="2808305070321719040">"3. munkahelyi <xliff:g id="LABEL">%1$s</xliff:g>"</string>
- <string name="lock_to_app_toast" msgid="1420543809500606964">"A képernyő rögzítésének feloldásához tartsa lenyomva a Vissza lehetőséget."</string>
+ <!-- no translation found for lock_to_app_toast (7693684144593484) -->
+ <skip />
<string name="lock_to_app_toast_locked" msgid="9125176335701699164">"Az alkalmazás rögzítve van: a rögzítés feloldása nem engedélyezett ezen az eszközön."</string>
<string name="lock_to_app_start" msgid="6643342070839862795">"Képernyő rögzítve"</string>
<string name="lock_to_app_exit" msgid="8598219838213787430">"Képernyő rögzítése feloldva"</string>
diff --git a/core/res/res/values-hy-rAM/strings.xml b/core/res/res/values-hy-rAM/strings.xml
index 87b8d04..f803fd27 100644
--- a/core/res/res/values-hy-rAM/strings.xml
+++ b/core/res/res/values-hy-rAM/strings.xml
@@ -1272,7 +1272,7 @@
<string name="find_previous" msgid="2196723669388360506">"Գտնել նախորդը"</string>
<string name="gpsNotifTicker" msgid="5622683912616496172">"Տեղադրության հարցում <xliff:g id="NAME">%s</xliff:g>-ից"</string>
<string name="gpsNotifTitle" msgid="5446858717157416839">"Տեղադրության հարցում"</string>
- <string name="gpsNotifMessage" msgid="1374718023224000702">"<xliff:g id="NAME">%1$s</xliff:g> (<xliff:g id="SERVICE">%2$s</xliff:g>)-ի հարցմամբ"</string>
+ <string name="gpsNotifMessage" msgid="1374718023224000702">"<xliff:g id="NAME">%1$s</xliff:g> (<xliff:g id="SERVICE">%2$s</xliff:g>)-ի հարցումով"</string>
<string name="gpsVerifYes" msgid="2346566072867213563">"Այո"</string>
<string name="gpsVerifNo" msgid="1146564937346454865">"Ոչ"</string>
<string name="sync_too_many_deletes" msgid="5296321850662746890">"Ջնջելու սահմանը գերազանցվել է"</string>
@@ -1559,7 +1559,8 @@
<string name="managed_profile_label_badge" msgid="2355652472854327647">"Աշխատանքային <xliff:g id="LABEL">%1$s</xliff:g>"</string>
<string name="managed_profile_label_badge_2" msgid="5048136430082124036">"2-րդ աշխատանք <xliff:g id="LABEL">%1$s</xliff:g>"</string>
<string name="managed_profile_label_badge_3" msgid="2808305070321719040">"3-րդ աշխատանք <xliff:g id="LABEL">%1$s</xliff:g>"</string>
- <string name="lock_to_app_toast" msgid="1420543809500606964">"Այս էկրանն ապամրացնելու համար հպեք և պահեք Հետ կոճակը:"</string>
+ <!-- no translation found for lock_to_app_toast (7693684144593484) -->
+ <skip />
<string name="lock_to_app_toast_locked" msgid="9125176335701699164">"Հավելվածն ամրացված է: Ապամրացումն այս սարքում չի թույլատրվում:"</string>
<string name="lock_to_app_start" msgid="6643342070839862795">"Էկրանն ամրացված է"</string>
<string name="lock_to_app_exit" msgid="8598219838213787430">"Էկրանն ապամրացված է"</string>
diff --git a/core/res/res/values-in/strings.xml b/core/res/res/values-in/strings.xml
index 1f6f130..67f11c7 100644
--- a/core/res/res/values-in/strings.xml
+++ b/core/res/res/values-in/strings.xml
@@ -1559,7 +1559,8 @@
<string name="managed_profile_label_badge" msgid="2355652472854327647">"Kantor <xliff:g id="LABEL">%1$s</xliff:g>"</string>
<string name="managed_profile_label_badge_2" msgid="5048136430082124036">"Upaya ke-2 <xliff:g id="LABEL">%1$s</xliff:g>"</string>
<string name="managed_profile_label_badge_3" msgid="2808305070321719040">"Upaya ke-3 <xliff:g id="LABEL">%1$s</xliff:g>"</string>
- <string name="lock_to_app_toast" msgid="1420543809500606964">"Untuk melepas pin layar ini, sentuh & tahan tombol Kembali."</string>
+ <!-- no translation found for lock_to_app_toast (7693684144593484) -->
+ <skip />
<string name="lock_to_app_toast_locked" msgid="9125176335701699164">"Pin dipasang ke aplikasi. Melepas pin tidak diizinkan di perangkat ini."</string>
<string name="lock_to_app_start" msgid="6643342070839862795">"Layar disematkan"</string>
<string name="lock_to_app_exit" msgid="8598219838213787430">"Layar dicopot sematannya"</string>
diff --git a/core/res/res/values-is-rIS/strings.xml b/core/res/res/values-is-rIS/strings.xml
index 4222c22..8beada0 100644
--- a/core/res/res/values-is-rIS/strings.xml
+++ b/core/res/res/values-is-rIS/strings.xml
@@ -1559,7 +1559,8 @@
<string name="managed_profile_label_badge" msgid="2355652472854327647">"<xliff:g id="LABEL">%1$s</xliff:g> í vinnu"</string>
<string name="managed_profile_label_badge_2" msgid="5048136430082124036">"<xliff:g id="LABEL">%1$s</xliff:g> í vinnu (2)"</string>
<string name="managed_profile_label_badge_3" msgid="2808305070321719040">"<xliff:g id="LABEL">%1$s</xliff:g> í vinnu (3)"</string>
- <string name="lock_to_app_toast" msgid="1420543809500606964">"Til að taka lásinn af þessari skjámynd skaltu halda inni bakkhnappinum."</string>
+ <!-- no translation found for lock_to_app_toast (7693684144593484) -->
+ <skip />
<string name="lock_to_app_toast_locked" msgid="9125176335701699164">"Forritið er fest: Ekki er hægt að losa forrit í þessu tæki."</string>
<string name="lock_to_app_start" msgid="6643342070839862795">"Skjár festur"</string>
<string name="lock_to_app_exit" msgid="8598219838213787430">"Skjár opnaður"</string>
diff --git a/core/res/res/values-it/strings.xml b/core/res/res/values-it/strings.xml
index 472178f..fa67e12 100644
--- a/core/res/res/values-it/strings.xml
+++ b/core/res/res/values-it/strings.xml
@@ -1559,7 +1559,8 @@
<string name="managed_profile_label_badge" msgid="2355652472854327647">"<xliff:g id="LABEL">%1$s</xliff:g> lavoro"</string>
<string name="managed_profile_label_badge_2" msgid="5048136430082124036">"<xliff:g id="LABEL">%1$s</xliff:g> di lavoro (2°)"</string>
<string name="managed_profile_label_badge_3" msgid="2808305070321719040">"<xliff:g id="LABEL">%1$s</xliff:g> di lavoro (3°)"</string>
- <string name="lock_to_app_toast" msgid="1420543809500606964">"Per sbloccare questa schermata tieni premuta l\'opzione Indietro."</string>
+ <!-- no translation found for lock_to_app_toast (7693684144593484) -->
+ <skip />
<string name="lock_to_app_toast_locked" msgid="9125176335701699164">"L\'app è bloccata. Su questo dispositivo non è consentito lo sblocco."</string>
<string name="lock_to_app_start" msgid="6643342070839862795">"Schermata bloccata"</string>
<string name="lock_to_app_exit" msgid="8598219838213787430">"Schermata sbloccata"</string>
diff --git a/core/res/res/values-iw/strings.xml b/core/res/res/values-iw/strings.xml
index 7c908d9..9a04898 100644
--- a/core/res/res/values-iw/strings.xml
+++ b/core/res/res/values-iw/strings.xml
@@ -1607,7 +1607,8 @@
<string name="managed_profile_label_badge" msgid="2355652472854327647">"עבודה <xliff:g id="LABEL">%1$s</xliff:g>"</string>
<string name="managed_profile_label_badge_2" msgid="5048136430082124036">"<xliff:g id="LABEL">%1$s</xliff:g> שני בעבודה"</string>
<string name="managed_profile_label_badge_3" msgid="2808305070321719040">"<xliff:g id="LABEL">%1$s</xliff:g> שלישי בעבודה"</string>
- <string name="lock_to_app_toast" msgid="1420543809500606964">"כדי לבטל את הצמדת המסך הזה, לחץ לחיצה ממושכת על הלחצן \'הקודם\'."</string>
+ <!-- no translation found for lock_to_app_toast (7693684144593484) -->
+ <skip />
<string name="lock_to_app_toast_locked" msgid="9125176335701699164">"האפליקציה מוצמדת: ביטול ההצמדה אסור במכשיר הזה."</string>
<string name="lock_to_app_start" msgid="6643342070839862795">"המסך מוצמד"</string>
<string name="lock_to_app_exit" msgid="8598219838213787430">"הצמדת המסך בוטלה"</string>
diff --git a/core/res/res/values-ja/strings.xml b/core/res/res/values-ja/strings.xml
index 764e9cf..d203449 100644
--- a/core/res/res/values-ja/strings.xml
+++ b/core/res/res/values-ja/strings.xml
@@ -1559,7 +1559,8 @@
<string name="managed_profile_label_badge" msgid="2355652472854327647">"仕事の<xliff:g id="LABEL">%1$s</xliff:g>"</string>
<string name="managed_profile_label_badge_2" msgid="5048136430082124036">"2 番目の仕事用<xliff:g id="LABEL">%1$s</xliff:g>"</string>
<string name="managed_profile_label_badge_3" msgid="2808305070321719040">"3 番目の仕事用<xliff:g id="LABEL">%1$s</xliff:g>"</string>
- <string name="lock_to_app_toast" msgid="1420543809500606964">"この画面の固定を解除するには [戻る] を押し続けます。"</string>
+ <!-- no translation found for lock_to_app_toast (7693684144593484) -->
+ <skip />
<string name="lock_to_app_toast_locked" msgid="9125176335701699164">"アプリは固定されています。この端末では固定を解除できません。"</string>
<string name="lock_to_app_start" msgid="6643342070839862795">"画面を固定しました"</string>
<string name="lock_to_app_exit" msgid="8598219838213787430">"画面固定を解除しました"</string>
diff --git a/core/res/res/values-ka-rGE/strings.xml b/core/res/res/values-ka-rGE/strings.xml
index f0486fa..e657d9f 100644
--- a/core/res/res/values-ka-rGE/strings.xml
+++ b/core/res/res/values-ka-rGE/strings.xml
@@ -1559,7 +1559,8 @@
<string name="managed_profile_label_badge" msgid="2355652472854327647">"სამსახური <xliff:g id="LABEL">%1$s</xliff:g>"</string>
<string name="managed_profile_label_badge_2" msgid="5048136430082124036">"მე-2 სამსახური <xliff:g id="LABEL">%1$s</xliff:g>"</string>
<string name="managed_profile_label_badge_3" msgid="2808305070321719040">"მე-3 სამსახური <xliff:g id="LABEL">%1$s</xliff:g>"</string>
- <string name="lock_to_app_toast" msgid="1420543809500606964">"ამ ეკრანის ჩამაგრების მოსახსნელად, ხანგრძლივად შეეხეთ ღილაკს „უკან“."</string>
+ <!-- no translation found for lock_to_app_toast (7693684144593484) -->
+ <skip />
<string name="lock_to_app_toast_locked" msgid="9125176335701699164">"აპი მიმაგრებულია: მიმაგრების მოხსნა არ არის ნებადართული ამ მოწყობილობაზე."</string>
<string name="lock_to_app_start" msgid="6643342070839862795">"ეკრანი დაფიქსირდა"</string>
<string name="lock_to_app_exit" msgid="8598219838213787430">"ეკრანს ფიქსაცია მოეხსნა"</string>
diff --git a/core/res/res/values-kk-rKZ/strings.xml b/core/res/res/values-kk-rKZ/strings.xml
index 1e45115..d9c6d8c 100644
--- a/core/res/res/values-kk-rKZ/strings.xml
+++ b/core/res/res/values-kk-rKZ/strings.xml
@@ -1559,7 +1559,8 @@
<string name="managed_profile_label_badge" msgid="2355652472854327647">"Жұмыс <xliff:g id="LABEL">%1$s</xliff:g>"</string>
<string name="managed_profile_label_badge_2" msgid="5048136430082124036">"2-ші жұмыс профилі (<xliff:g id="LABEL">%1$s</xliff:g>)"</string>
<string name="managed_profile_label_badge_3" msgid="2808305070321719040">"3-ші жұмыс профилі (<xliff:g id="LABEL">%1$s</xliff:g>)"</string>
- <string name="lock_to_app_toast" msgid="1420543809500606964">"Осы экранды босату үшін \"Артқа\" түймесін басып тұрыңыз."</string>
+ <!-- no translation found for lock_to_app_toast (7693684144593484) -->
+ <skip />
<string name="lock_to_app_toast_locked" msgid="9125176335701699164">"Бағдарлама белгіленді: Бұл құрылғыда белгіні алуға рұқсат берілмейді."</string>
<string name="lock_to_app_start" msgid="6643342070839862795">"Экран түйрелді"</string>
<string name="lock_to_app_exit" msgid="8598219838213787430">"Экран босатылды"</string>
diff --git a/core/res/res/values-km-rKH/strings.xml b/core/res/res/values-km-rKH/strings.xml
index 1c9ec81..7c29a58 100644
--- a/core/res/res/values-km-rKH/strings.xml
+++ b/core/res/res/values-km-rKH/strings.xml
@@ -1561,7 +1561,8 @@
<string name="managed_profile_label_badge" msgid="2355652472854327647">"កន្លែងធ្វើការ <xliff:g id="LABEL">%1$s</xliff:g>"</string>
<string name="managed_profile_label_badge_2" msgid="5048136430082124036">"<xliff:g id="LABEL">%1$s</xliff:g> ការងារទី 2"</string>
<string name="managed_profile_label_badge_3" msgid="2808305070321719040">"<xliff:g id="LABEL">%1$s</xliff:g> ការងារទី 3"</string>
- <string name="lock_to_app_toast" msgid="1420543809500606964">"ដើម្បីផ្តាច់អេក្រង់នេះ សូមប៉ះ និងសង្កត់ប៊ូតុងថយក្រោយឲ្យជាប់។"</string>
+ <!-- no translation found for lock_to_app_toast (7693684144593484) -->
+ <skip />
<string name="lock_to_app_toast_locked" msgid="9125176335701699164">"កម្មវិធីនេះត្រូវបានខ្ទាស់។ មិនអនុញ្ញាតឲ្យដោះការខ្ទាស់នៅលើឧបករណ៍នេះទេ។"</string>
<string name="lock_to_app_start" msgid="6643342070839862795">"បានភ្ជាប់អេក្រង់"</string>
<string name="lock_to_app_exit" msgid="8598219838213787430">"មិនបានភ្ជាប់អេក្រង់"</string>
diff --git a/core/res/res/values-kn-rIN/strings.xml b/core/res/res/values-kn-rIN/strings.xml
index e79fd6f..e86c275 100644
--- a/core/res/res/values-kn-rIN/strings.xml
+++ b/core/res/res/values-kn-rIN/strings.xml
@@ -992,7 +992,7 @@
<string name="aerr_application_repeated" msgid="3146328699537439573">"<xliff:g id="APPLICATION">%1$s</xliff:g> ನಿಲ್ಲುತ್ತಲೇ ಇರುತ್ತದೆ"</string>
<string name="aerr_process_repeated" msgid="6235302956890402259">"<xliff:g id="PROCESS">%1$s</xliff:g> ನಿಲ್ಲುತ್ತಲೇ ಇರುತ್ತದೆ"</string>
<string name="aerr_restart" msgid="7581308074153624475">"ಅಪ್ಲಿಕೇಶನ್ ಮತ್ತೆ ತೆರೆಯಿರಿ"</string>
- <string name="aerr_report" msgid="5371800241488400617">"ಪ್ರತಿಕ್ರಿಯೆ ಕಳುಹಿಸು"</string>
+ <string name="aerr_report" msgid="5371800241488400617">"ಪ್ರತಿಕ್ರಿಯೆ ಕಳುಹಿಸಿ"</string>
<string name="aerr_close" msgid="2991640326563991340">"ಮುಚ್ಚು"</string>
<string name="aerr_mute" msgid="1974781923723235953">"ಸಾಧನವು ಮರುಪ್ರಾರಂಭವಾಗುವವರೆಗೂ ಮ್ಯೂಟ್ ಮಾಡಿ"</string>
<string name="aerr_wait" msgid="3199956902437040261">"ನಿರೀಕ್ಷಿಸು"</string>
@@ -1559,7 +1559,8 @@
<string name="managed_profile_label_badge" msgid="2355652472854327647">"ಕೆಲಸ <xliff:g id="LABEL">%1$s</xliff:g>"</string>
<string name="managed_profile_label_badge_2" msgid="5048136430082124036">"2 ನೇ ಕೆಲಸದ <xliff:g id="LABEL">%1$s</xliff:g>"</string>
<string name="managed_profile_label_badge_3" msgid="2808305070321719040">"3 ನೇ ಕೆಲಸದ <xliff:g id="LABEL">%1$s</xliff:g>"</string>
- <string name="lock_to_app_toast" msgid="1420543809500606964">"ಈ ಪರದೆಯನ್ನು ಅನ್ಪಿನ್ ಮಾಡಲು, ಸ್ಪರ್ಶಿಸಿ ಮತ್ತು ಹಿಂಂದೆ ಒತ್ತಿ ಹಿಡಿಯಿರಿ."</string>
+ <!-- no translation found for lock_to_app_toast (7693684144593484) -->
+ <skip />
<string name="lock_to_app_toast_locked" msgid="9125176335701699164">"ಅಪ್ಲಿಕೇಶನ್ ಪಿನ್ ಮಾಡಲಾಗಿದೆ: ಈ ಸಾಧನದಲ್ಲಿ ಅನ್ಪಿನ್ ಮಾಡುವುದನ್ನು ಅನುಮತಿಸಲಾಗುವುದಿಲ್ಲ."</string>
<string name="lock_to_app_start" msgid="6643342070839862795">"ಸ್ಕ್ರೀನ್ ಪಿನ್ ಮಾಡಲಾಗಿದೆ"</string>
<string name="lock_to_app_exit" msgid="8598219838213787430">"ಸ್ಕ್ರೀನ್ ಅನ್ಪಿನ್ ಮಾಡಲಾಗಿದೆ"</string>
diff --git a/core/res/res/values-ko/strings.xml b/core/res/res/values-ko/strings.xml
index b931bbb..f3badd1 100644
--- a/core/res/res/values-ko/strings.xml
+++ b/core/res/res/values-ko/strings.xml
@@ -1559,7 +1559,8 @@
<string name="managed_profile_label_badge" msgid="2355652472854327647">"업무용 <xliff:g id="LABEL">%1$s</xliff:g>"</string>
<string name="managed_profile_label_badge_2" msgid="5048136430082124036">"두 번째 업무용 <xliff:g id="LABEL">%1$s</xliff:g>"</string>
<string name="managed_profile_label_badge_3" msgid="2808305070321719040">"세 번째 업무용<xliff:g id="LABEL">%1$s</xliff:g>"</string>
- <string name="lock_to_app_toast" msgid="1420543809500606964">"이 화면을 고정 해제하려면 \'뒤로\'를 길게 터치합니다."</string>
+ <!-- no translation found for lock_to_app_toast (7693684144593484) -->
+ <skip />
<string name="lock_to_app_toast_locked" msgid="9125176335701699164">"앱이 고정되었습니다. 이 기기에서는 고정 해제를 허용하지 않습니다."</string>
<string name="lock_to_app_start" msgid="6643342070839862795">"화면 고정됨"</string>
<string name="lock_to_app_exit" msgid="8598219838213787430">"화면 고정 해제됨"</string>
diff --git a/core/res/res/values-ky-rKG/strings.xml b/core/res/res/values-ky-rKG/strings.xml
index c896180..9aaa147 100644
--- a/core/res/res/values-ky-rKG/strings.xml
+++ b/core/res/res/values-ky-rKG/strings.xml
@@ -1559,7 +1559,8 @@
<string name="managed_profile_label_badge" msgid="2355652472854327647">"Жумуш <xliff:g id="LABEL">%1$s</xliff:g>"</string>
<string name="managed_profile_label_badge_2" msgid="5048136430082124036">"2-жумуш <xliff:g id="LABEL">%1$s</xliff:g>"</string>
<string name="managed_profile_label_badge_3" msgid="2808305070321719040">"3-жумуш <xliff:g id="LABEL">%1$s</xliff:g>"</string>
- <string name="lock_to_app_toast" msgid="1420543809500606964">"Бул экранды бошотуу үчүн \"Артка\" баскычын басып, кармап туруңуз."</string>
+ <!-- no translation found for lock_to_app_toast (7693684144593484) -->
+ <skip />
<string name="lock_to_app_toast_locked" msgid="9125176335701699164">"Колдонмо кадалган: Бул түзмөктө бошотууга уруксат жок."</string>
<string name="lock_to_app_start" msgid="6643342070839862795">"Экран кадалды"</string>
<string name="lock_to_app_exit" msgid="8598219838213787430">"Экран бошотулду"</string>
diff --git a/core/res/res/values-lo-rLA/strings.xml b/core/res/res/values-lo-rLA/strings.xml
index 534ffe2..f6b5c96 100644
--- a/core/res/res/values-lo-rLA/strings.xml
+++ b/core/res/res/values-lo-rLA/strings.xml
@@ -1559,7 +1559,8 @@
<string name="managed_profile_label_badge" msgid="2355652472854327647">"ບ່ອນເຮັດວຽກ <xliff:g id="LABEL">%1$s</xliff:g>"</string>
<string name="managed_profile_label_badge_2" msgid="5048136430082124036">"ບ່ອນເຮັດວຽກທີ 2 <xliff:g id="LABEL">%1$s</xliff:g>"</string>
<string name="managed_profile_label_badge_3" msgid="2808305070321719040">"ບ່ອນເຮັດວຽກທີ 3 <xliff:g id="LABEL">%1$s</xliff:g>"</string>
- <string name="lock_to_app_toast" msgid="1420543809500606964">"ກົດປຸ່ມກັບຄືນຄ້າງໄວ້ເພື່ອເຊົາປັກໝຸດໜ້າຈໍນີ້."</string>
+ <!-- no translation found for lock_to_app_toast (7693684144593484) -->
+ <skip />
<string name="lock_to_app_toast_locked" msgid="9125176335701699164">"ແອັບຖືກປັກໝຸດແລ້ວ: ບໍ່ອະນຸຍາດໃຫ້ຖອນປັກໝຸດຢູ່ເທິງອຸປະກອນນີ້."</string>
<string name="lock_to_app_start" msgid="6643342070839862795">"ປັກໝຸດໜ້າຈໍແລ້ວ"</string>
<string name="lock_to_app_exit" msgid="8598219838213787430">"ຍົກເລີກການປັກໝຸນຫນ້າຈໍແລ້ວ"</string>
diff --git a/core/res/res/values-lt/strings.xml b/core/res/res/values-lt/strings.xml
index c9f781f..e2c4c2f 100644
--- a/core/res/res/values-lt/strings.xml
+++ b/core/res/res/values-lt/strings.xml
@@ -1607,7 +1607,8 @@
<string name="managed_profile_label_badge" msgid="2355652472854327647">"Darbo <xliff:g id="LABEL">%1$s</xliff:g>"</string>
<string name="managed_profile_label_badge_2" msgid="5048136430082124036">"2-asis darbo <xliff:g id="LABEL">%1$s</xliff:g>"</string>
<string name="managed_profile_label_badge_3" msgid="2808305070321719040">"3-iasis darbo <xliff:g id="LABEL">%1$s</xliff:g>"</string>
- <string name="lock_to_app_toast" msgid="1420543809500606964">"Kad atsegtumėte šį ekraną, palieskite ir palaikykite „Atgal“."</string>
+ <!-- no translation found for lock_to_app_toast (7693684144593484) -->
+ <skip />
<string name="lock_to_app_toast_locked" msgid="9125176335701699164">"Programa prisegta: šiame įrenginyje negalima atsegti."</string>
<string name="lock_to_app_start" msgid="6643342070839862795">"Ekrano prisegtas"</string>
<string name="lock_to_app_exit" msgid="8598219838213787430">"Ekranas atsegtas"</string>
diff --git a/core/res/res/values-lv/strings.xml b/core/res/res/values-lv/strings.xml
index df2c194..d3da07d 100644
--- a/core/res/res/values-lv/strings.xml
+++ b/core/res/res/values-lv/strings.xml
@@ -1583,7 +1583,8 @@
<string name="managed_profile_label_badge" msgid="2355652472854327647">"Darbā: <xliff:g id="LABEL">%1$s</xliff:g>"</string>
<string name="managed_profile_label_badge_2" msgid="5048136430082124036">"2. darba profils: <xliff:g id="LABEL">%1$s</xliff:g>"</string>
<string name="managed_profile_label_badge_3" msgid="2808305070321719040">"3. darba profils: <xliff:g id="LABEL">%1$s</xliff:g>"</string>
- <string name="lock_to_app_toast" msgid="1420543809500606964">"Lai atspraustu šo ekrānu, pieskarieties pogai “Atpakaļ” un turiet to."</string>
+ <!-- no translation found for lock_to_app_toast (7693684144593484) -->
+ <skip />
<string name="lock_to_app_toast_locked" msgid="9125176335701699164">"Lietotne ir piesprausta. Atspraušana šajā ierīcē nav atļauta."</string>
<string name="lock_to_app_start" msgid="6643342070839862795">"Ekrāns ir piesprausts"</string>
<string name="lock_to_app_exit" msgid="8598219838213787430">"Ekrāns ir atsprausts"</string>
diff --git a/core/res/res/values-mk-rMK/strings.xml b/core/res/res/values-mk-rMK/strings.xml
index 53b7ab7..ac5732d 100644
--- a/core/res/res/values-mk-rMK/strings.xml
+++ b/core/res/res/values-mk-rMK/strings.xml
@@ -201,9 +201,9 @@
<string name="reboot_to_update_title" msgid="6212636802536823850">"Системско ажурирање на Android"</string>
<string name="reboot_to_update_prepare" msgid="6305853831955310890">"Се подготвува ажурирањето…"</string>
<string name="reboot_to_update_package" msgid="3871302324500927291">"Пакетот за ажурирање се обработува..."</string>
- <string name="reboot_to_update_reboot" msgid="6428441000951565185">"Се престартува…"</string>
+ <string name="reboot_to_update_reboot" msgid="6428441000951565185">"Се рестартира…"</string>
<string name="reboot_to_reset_title" msgid="4142355915340627490">"Ресетирање фабрички податоци"</string>
- <string name="reboot_to_reset_message" msgid="2432077491101416345">"Се престартува…"</string>
+ <string name="reboot_to_reset_message" msgid="2432077491101416345">"Се рестартира…"</string>
<string name="shutdown_progress" msgid="2281079257329981203">"Се исклучува..."</string>
<string name="shutdown_confirm" product="tablet" msgid="3385745179555731470">"Вашиот таблет ќе се исклучи."</string>
<string name="shutdown_confirm" product="tv" msgid="476672373995075359">"Вашиот телевизор ќе се исклучи."</string>
@@ -1561,7 +1561,8 @@
<string name="managed_profile_label_badge" msgid="2355652472854327647">"Работа <xliff:g id="LABEL">%1$s</xliff:g>"</string>
<string name="managed_profile_label_badge_2" msgid="5048136430082124036">"Втора деловна <xliff:g id="LABEL">%1$s</xliff:g>"</string>
<string name="managed_profile_label_badge_3" msgid="2808305070321719040">"Трета деловна <xliff:g id="LABEL">%1$s</xliff:g>"</string>
- <string name="lock_to_app_toast" msgid="1420543809500606964">"За откачување на екранов, допрете и задржете Назад."</string>
+ <!-- no translation found for lock_to_app_toast (7693684144593484) -->
+ <skip />
<string name="lock_to_app_toast_locked" msgid="9125176335701699164">"Апликацијата е закачена: откачување не е дозволено на уредов."</string>
<string name="lock_to_app_start" msgid="6643342070839862795">"Екранот е закачен"</string>
<string name="lock_to_app_exit" msgid="8598219838213787430">"Екранот е откачен"</string>
diff --git a/core/res/res/values-ml-rIN/strings.xml b/core/res/res/values-ml-rIN/strings.xml
index e29c01b..399d90a 100644
--- a/core/res/res/values-ml-rIN/strings.xml
+++ b/core/res/res/values-ml-rIN/strings.xml
@@ -1559,7 +1559,8 @@
<string name="managed_profile_label_badge" msgid="2355652472854327647">"ഔദ്യോഗികം <xliff:g id="LABEL">%1$s</xliff:g>"</string>
<string name="managed_profile_label_badge_2" msgid="5048136430082124036">"രണ്ടാമത്തെ ഔദ്യോഗിക <xliff:g id="LABEL">%1$s</xliff:g>"</string>
<string name="managed_profile_label_badge_3" msgid="2808305070321719040">"മൂന്നാമത്തെ ഔദ്യോഗിക <xliff:g id="LABEL">%1$s</xliff:g>"</string>
- <string name="lock_to_app_toast" msgid="1420543809500606964">"ഈ സ്ക്രീൻ അൺപിൻ ചെയ്യാൻ, ബാക്ക് ബട്ടൺ സ്പർശിച്ച് പിടിക്കുക"</string>
+ <!-- no translation found for lock_to_app_toast (7693684144593484) -->
+ <skip />
<string name="lock_to_app_toast_locked" msgid="9125176335701699164">"അപ്ലിക്കേഷൻ പിൻ ചെയ്തു: ഈ ഉപകരണത്തിൽ അൺപിൻ ചെയ്യാനാവില്ല."</string>
<string name="lock_to_app_start" msgid="6643342070839862795">"സ്ക്രീൻ പിൻ ചെയ്തു"</string>
<string name="lock_to_app_exit" msgid="8598219838213787430">"സ്ക്രീൻ അൺപിൻ ചെയ്തു"</string>
diff --git a/core/res/res/values-mn-rMN/strings.xml b/core/res/res/values-mn-rMN/strings.xml
index 2f1cc69..3e5e590 100644
--- a/core/res/res/values-mn-rMN/strings.xml
+++ b/core/res/res/values-mn-rMN/strings.xml
@@ -1559,7 +1559,8 @@
<string name="managed_profile_label_badge" msgid="2355652472854327647">"Ажлын <xliff:g id="LABEL">%1$s</xliff:g>"</string>
<string name="managed_profile_label_badge_2" msgid="5048136430082124036">"2 дахь ажил <xliff:g id="LABEL">%1$s</xliff:g>"</string>
<string name="managed_profile_label_badge_3" msgid="2808305070321719040">"3 дахь ажил <xliff:g id="LABEL">%1$s</xliff:g>"</string>
- <string name="lock_to_app_toast" msgid="1420543809500606964">"Энэ дэлгэцийг эхэнд нээхийг болиулахын тулд Буцах товчлуурыг дараад, хүлээнэ үү."</string>
+ <!-- no translation found for lock_to_app_toast (7693684144593484) -->
+ <skip />
<string name="lock_to_app_toast_locked" msgid="9125176335701699164">"App-ыг тусгайлан тэмдэглэсэн байна: Энэ төхөөрөмж дээр тусгайлан тэмдэглэсэн сонголтыг устгах боломжгүй."</string>
<string name="lock_to_app_start" msgid="6643342070839862795">"Дэлгэцийг тогтоосон"</string>
<string name="lock_to_app_exit" msgid="8598219838213787430">"Дэлгэцийг сулласан"</string>
diff --git a/core/res/res/values-mr-rIN/strings.xml b/core/res/res/values-mr-rIN/strings.xml
index 50b41c0..c093c2d 100644
--- a/core/res/res/values-mr-rIN/strings.xml
+++ b/core/res/res/values-mr-rIN/strings.xml
@@ -1559,7 +1559,8 @@
<string name="managed_profile_label_badge" msgid="2355652472854327647">"कार्य <xliff:g id="LABEL">%1$s</xliff:g>"</string>
<string name="managed_profile_label_badge_2" msgid="5048136430082124036">"2 रे कार्य <xliff:g id="LABEL">%1$s</xliff:g>"</string>
<string name="managed_profile_label_badge_3" msgid="2808305070321719040">"3 रे कार्य <xliff:g id="LABEL">%1$s</xliff:g>"</string>
- <string name="lock_to_app_toast" msgid="1420543809500606964">"ही स्क्रीन अनपिन करण्यासाठी, परत ला स्पर्श करा आणि धरून ठेवा."</string>
+ <!-- no translation found for lock_to_app_toast (7693684144593484) -->
+ <skip />
<string name="lock_to_app_toast_locked" msgid="9125176335701699164">"अॅप पिन केलेला आहे: या डिव्हाइसवर अनपिन करण्यास अनुमती नाही."</string>
<string name="lock_to_app_start" msgid="6643342070839862795">"स्क्रीन पिन केली"</string>
<string name="lock_to_app_exit" msgid="8598219838213787430">"स्क्रीन अनपिन केली"</string>
diff --git a/core/res/res/values-ms-rMY/strings.xml b/core/res/res/values-ms-rMY/strings.xml
index 72daecb..ab59e38 100644
--- a/core/res/res/values-ms-rMY/strings.xml
+++ b/core/res/res/values-ms-rMY/strings.xml
@@ -1559,7 +1559,8 @@
<string name="managed_profile_label_badge" msgid="2355652472854327647">"Kerja <xliff:g id="LABEL">%1$s</xliff:g>"</string>
<string name="managed_profile_label_badge_2" msgid="5048136430082124036">"<xliff:g id="LABEL">%1$s</xliff:g> kerja ke-2"</string>
<string name="managed_profile_label_badge_3" msgid="2808305070321719040">"<xliff:g id="LABEL">%1$s</xliff:g> kerja ke-3"</string>
- <string name="lock_to_app_toast" msgid="1420543809500606964">"Untuk menyahsematkan skrin ni, ketik & tahan Kembali."</string>
+ <!-- no translation found for lock_to_app_toast (7693684144593484) -->
+ <skip />
<string name="lock_to_app_toast_locked" msgid="9125176335701699164">"Apl disemat: Nyahsemat tidak dibenarkan pada peranti ini."</string>
<string name="lock_to_app_start" msgid="6643342070839862795">"Skrin disemat"</string>
<string name="lock_to_app_exit" msgid="8598219838213787430">"Skrin dinyahsemat"</string>
diff --git a/core/res/res/values-my-rMM/strings.xml b/core/res/res/values-my-rMM/strings.xml
index c3ebf74..921b95d 100644
--- a/core/res/res/values-my-rMM/strings.xml
+++ b/core/res/res/values-my-rMM/strings.xml
@@ -1559,7 +1559,8 @@
<string name="managed_profile_label_badge" msgid="2355652472854327647">"အလုပ် <xliff:g id="LABEL">%1$s</xliff:g>"</string>
<string name="managed_profile_label_badge_2" msgid="5048136430082124036">"ဒုတိယအလုပ် <xliff:g id="LABEL">%1$s</xliff:g>"</string>
<string name="managed_profile_label_badge_3" msgid="2808305070321719040">"တတိယအလုပ် <xliff:g id="LABEL">%1$s</xliff:g>"</string>
- <string name="lock_to_app_toast" msgid="1420543809500606964">"ဤမျက်နှာပြင်ကို ပင်ဖြုတ်ရန် \"နောက်သို့\" ကိုထိပြီးဖိထားပါ။"</string>
+ <!-- no translation found for lock_to_app_toast (7693684144593484) -->
+ <skip />
<string name="lock_to_app_toast_locked" msgid="9125176335701699164">"အက်ပ်ကို ပင်ထိုးထားသည်။ ပင်ဖျက်ခြင်းကို ဒီစက်မှာ မရနိုင်ပါ။"</string>
<string name="lock_to_app_start" msgid="6643342070839862795">"မျက်နှာပြင်ကို ပင်ထိုးထား"</string>
<string name="lock_to_app_exit" msgid="8598219838213787430">"မျက်နှာပြင် ပင်ထိုးမှု ဖြတ်လိုက်ပြီ"</string>
diff --git a/core/res/res/values-nb/strings.xml b/core/res/res/values-nb/strings.xml
index 4e7c4ce..07aeceb 100644
--- a/core/res/res/values-nb/strings.xml
+++ b/core/res/res/values-nb/strings.xml
@@ -1559,7 +1559,8 @@
<string name="managed_profile_label_badge" msgid="2355652472854327647">"Jobb-<xliff:g id="LABEL">%1$s</xliff:g>"</string>
<string name="managed_profile_label_badge_2" msgid="5048136430082124036">"Andre <xliff:g id="LABEL">%1$s</xliff:g> for jobben"</string>
<string name="managed_profile_label_badge_3" msgid="2808305070321719040">"Tredje <xliff:g id="LABEL">%1$s</xliff:g> for jobben"</string>
- <string name="lock_to_app_toast" msgid="1420543809500606964">"For å løsne denne skjermen, trykk og hold inne Tilbake."</string>
+ <!-- no translation found for lock_to_app_toast (7693684144593484) -->
+ <skip />
<string name="lock_to_app_toast_locked" msgid="9125176335701699164">"Appen er festet – du kan ikke løsne apper på denne enheten."</string>
<string name="lock_to_app_start" msgid="6643342070839862795">"Skjermen er festet"</string>
<string name="lock_to_app_exit" msgid="8598219838213787430">"Skjermen er løsnet"</string>
diff --git a/core/res/res/values-ne-rNP/strings.xml b/core/res/res/values-ne-rNP/strings.xml
index 3af8130..0e95ca6 100644
--- a/core/res/res/values-ne-rNP/strings.xml
+++ b/core/res/res/values-ne-rNP/strings.xml
@@ -1565,7 +1565,8 @@
<string name="managed_profile_label_badge" msgid="2355652472854327647">"कार्य <xliff:g id="LABEL">%1$s</xliff:g>"</string>
<string name="managed_profile_label_badge_2" msgid="5048136430082124036">"कार्यालयको दोस्रो <xliff:g id="LABEL">%1$s</xliff:g>"</string>
<string name="managed_profile_label_badge_3" msgid="2808305070321719040">"कार्यालयको तेस्रो <xliff:g id="LABEL">%1$s</xliff:g>"</string>
- <string name="lock_to_app_toast" msgid="1420543809500606964">"यस स्क्रिनलाई अनपिन गर्न पछाडि बटनलाई छोइराख्नुहोस्।"</string>
+ <!-- no translation found for lock_to_app_toast (7693684144593484) -->
+ <skip />
<string name="lock_to_app_toast_locked" msgid="9125176335701699164">"अनुप्रयोग पिन गरियो: यस यन्त्रमा अनपिन गर्ने अनुमति छैन।"</string>
<string name="lock_to_app_start" msgid="6643342070839862795">"स्क्रिन पिन गरियो"</string>
<string name="lock_to_app_exit" msgid="8598219838213787430">"स्क्रिन अनपिन गरियो"</string>
diff --git a/core/res/res/values-nl/strings.xml b/core/res/res/values-nl/strings.xml
index 39a5a02..bc734ae 100644
--- a/core/res/res/values-nl/strings.xml
+++ b/core/res/res/values-nl/strings.xml
@@ -1559,7 +1559,8 @@
<string name="managed_profile_label_badge" msgid="2355652472854327647">"Werk <xliff:g id="LABEL">%1$s</xliff:g>"</string>
<string name="managed_profile_label_badge_2" msgid="5048136430082124036">"2e <xliff:g id="LABEL">%1$s</xliff:g>, werk"</string>
<string name="managed_profile_label_badge_3" msgid="2808305070321719040">"3e <xliff:g id="LABEL">%1$s</xliff:g>, werk"</string>
- <string name="lock_to_app_toast" msgid="1420543809500606964">"Tik op Terug en houd vast om dit scherm los te maken."</string>
+ <!-- no translation found for lock_to_app_toast (7693684144593484) -->
+ <skip />
<string name="lock_to_app_toast_locked" msgid="9125176335701699164">"App is vastgezet: losmaken is niet toegestaan op dit apparaat."</string>
<string name="lock_to_app_start" msgid="6643342070839862795">"Scherm vastgezet"</string>
<string name="lock_to_app_exit" msgid="8598219838213787430">"Scherm losgemaakt"</string>
diff --git a/core/res/res/values-pa-rIN/strings.xml b/core/res/res/values-pa-rIN/strings.xml
index 315e7d5..4c9bc44 100644
--- a/core/res/res/values-pa-rIN/strings.xml
+++ b/core/res/res/values-pa-rIN/strings.xml
@@ -1559,7 +1559,8 @@
<string name="managed_profile_label_badge" msgid="2355652472854327647">"ਕੰਮ <xliff:g id="LABEL">%1$s</xliff:g>"</string>
<string name="managed_profile_label_badge_2" msgid="5048136430082124036">"ਦੂਸਰੀ ਕਾਰਜ-ਸਥਾਨ <xliff:g id="LABEL">%1$s</xliff:g>"</string>
<string name="managed_profile_label_badge_3" msgid="2808305070321719040">"ਤੀਸਰੀ ਕਾਰਜ-ਸਥਾਨ <xliff:g id="LABEL">%1$s</xliff:g>"</string>
- <string name="lock_to_app_toast" msgid="1420543809500606964">"ਇਸ ਸਕ੍ਰੀਨ ਨੂੰ ਅਨਪਿੰਨ ਕਰਨ ਲਈ, ਸਪਰਸ਼ ਕਰੋ & ਦਬਾਈ ਰੱਖੋ।"</string>
+ <!-- no translation found for lock_to_app_toast (7693684144593484) -->
+ <skip />
<string name="lock_to_app_toast_locked" msgid="9125176335701699164">"ਐਪ ਪਿੰਨਡ ਹੈ: ਇਸ ਡੀਵਾਈਸ ਤੇ ਅਨਪਿਨ ਕਰਨ ਦੀ ਆਗਿਆ ਨਹੀਂ ਹੈ।"</string>
<string name="lock_to_app_start" msgid="6643342070839862795">"ਸਕ੍ਰੀਨ ਪਿੰਨ ਕੀਤੀ"</string>
<string name="lock_to_app_exit" msgid="8598219838213787430">"ਸਕ੍ਰੀਨ ਅਨਪਿਨ ਕੀਤੀ"</string>
diff --git a/core/res/res/values-pl/strings.xml b/core/res/res/values-pl/strings.xml
index 77b2bf3..4bf9f89 100644
--- a/core/res/res/values-pl/strings.xml
+++ b/core/res/res/values-pl/strings.xml
@@ -1607,7 +1607,8 @@
<string name="managed_profile_label_badge" msgid="2355652472854327647">"<xliff:g id="LABEL">%1$s</xliff:g> (praca)"</string>
<string name="managed_profile_label_badge_2" msgid="5048136430082124036">"<xliff:g id="LABEL">%1$s</xliff:g> – praca 2"</string>
<string name="managed_profile_label_badge_3" msgid="2808305070321719040">"<xliff:g id="LABEL">%1$s</xliff:g> – praca 3"</string>
- <string name="lock_to_app_toast" msgid="1420543809500606964">"Aby odpiąć ten ekran, naciśnij i przytrzymaj Wstecz."</string>
+ <!-- no translation found for lock_to_app_toast (7693684144593484) -->
+ <skip />
<string name="lock_to_app_toast_locked" msgid="9125176335701699164">"Aplikacja jest przypięta. Nie możesz jej odpiąć na tym urządzeniu."</string>
<string name="lock_to_app_start" msgid="6643342070839862795">"Ekran przypięty"</string>
<string name="lock_to_app_exit" msgid="8598219838213787430">"Ekran odpięty"</string>
diff --git a/core/res/res/values-pt-rBR/strings.xml b/core/res/res/values-pt-rBR/strings.xml
index 71b9747..ccd1d8b 100644
--- a/core/res/res/values-pt-rBR/strings.xml
+++ b/core/res/res/values-pt-rBR/strings.xml
@@ -1267,7 +1267,7 @@
<string name="progress_erasing" product="default" msgid="6596988875507043042">"Apagando cartão SD..."</string>
<string name="share" msgid="1778686618230011964">"Compartilhar"</string>
<string name="find" msgid="4808270900322985960">"Localizar"</string>
- <string name="websearch" msgid="4337157977400211589">"Pesquisa na web do Google"</string>
+ <string name="websearch" msgid="4337157977400211589">"Pesquisa Google na Web"</string>
<string name="find_next" msgid="5742124618942193978">"Localizar próximo"</string>
<string name="find_previous" msgid="2196723669388360506">"Localizar anterior"</string>
<string name="gpsNotifTicker" msgid="5622683912616496172">"Solicitação de local de <xliff:g id="NAME">%s</xliff:g>"</string>
@@ -1559,7 +1559,8 @@
<string name="managed_profile_label_badge" msgid="2355652472854327647">"Trabalho: <xliff:g id="LABEL">%1$s</xliff:g>"</string>
<string name="managed_profile_label_badge_2" msgid="5048136430082124036">"Segundo <xliff:g id="LABEL">%1$s</xliff:g> de trabalho"</string>
<string name="managed_profile_label_badge_3" msgid="2808305070321719040">"Terceiro <xliff:g id="LABEL">%1$s</xliff:g> de trabalho"</string>
- <string name="lock_to_app_toast" msgid="1420543809500606964">"Para liberar esta tela, toque no botão \"Voltar\" e mantenha-o pressionado."</string>
+ <!-- no translation found for lock_to_app_toast (7693684144593484) -->
+ <skip />
<string name="lock_to_app_toast_locked" msgid="9125176335701699164">"O app está fixado. A liberação não é permitida neste dispositivo."</string>
<string name="lock_to_app_start" msgid="6643342070839862795">"Tela fixada"</string>
<string name="lock_to_app_exit" msgid="8598219838213787430">"Tela liberada"</string>
diff --git a/core/res/res/values-pt-rPT/strings.xml b/core/res/res/values-pt-rPT/strings.xml
index 5ae5c40..16aead7 100644
--- a/core/res/res/values-pt-rPT/strings.xml
+++ b/core/res/res/values-pt-rPT/strings.xml
@@ -1559,7 +1559,8 @@
<string name="managed_profile_label_badge" msgid="2355652472854327647">"<xliff:g id="LABEL">%1$s</xliff:g> de trabalho"</string>
<string name="managed_profile_label_badge_2" msgid="5048136430082124036">"2.º <xliff:g id="LABEL">%1$s</xliff:g> de trabalho"</string>
<string name="managed_profile_label_badge_3" msgid="2808305070321719040">"3.º <xliff:g id="LABEL">%1$s</xliff:g> de trabalho"</string>
- <string name="lock_to_app_toast" msgid="1420543809500606964">"Para soltar este ecrã, toque sem soltar em Anterior."</string>
+ <!-- no translation found for lock_to_app_toast (7693684144593484) -->
+ <skip />
<string name="lock_to_app_toast_locked" msgid="9125176335701699164">"A aplicação está fixa: não é permitido soltá-la neste dispositivo."</string>
<string name="lock_to_app_start" msgid="6643342070839862795">"Ecrã fixo"</string>
<string name="lock_to_app_exit" msgid="8598219838213787430">"Ecrã solto"</string>
diff --git a/core/res/res/values-pt/strings.xml b/core/res/res/values-pt/strings.xml
index 71b9747..ccd1d8b 100644
--- a/core/res/res/values-pt/strings.xml
+++ b/core/res/res/values-pt/strings.xml
@@ -1267,7 +1267,7 @@
<string name="progress_erasing" product="default" msgid="6596988875507043042">"Apagando cartão SD..."</string>
<string name="share" msgid="1778686618230011964">"Compartilhar"</string>
<string name="find" msgid="4808270900322985960">"Localizar"</string>
- <string name="websearch" msgid="4337157977400211589">"Pesquisa na web do Google"</string>
+ <string name="websearch" msgid="4337157977400211589">"Pesquisa Google na Web"</string>
<string name="find_next" msgid="5742124618942193978">"Localizar próximo"</string>
<string name="find_previous" msgid="2196723669388360506">"Localizar anterior"</string>
<string name="gpsNotifTicker" msgid="5622683912616496172">"Solicitação de local de <xliff:g id="NAME">%s</xliff:g>"</string>
@@ -1559,7 +1559,8 @@
<string name="managed_profile_label_badge" msgid="2355652472854327647">"Trabalho: <xliff:g id="LABEL">%1$s</xliff:g>"</string>
<string name="managed_profile_label_badge_2" msgid="5048136430082124036">"Segundo <xliff:g id="LABEL">%1$s</xliff:g> de trabalho"</string>
<string name="managed_profile_label_badge_3" msgid="2808305070321719040">"Terceiro <xliff:g id="LABEL">%1$s</xliff:g> de trabalho"</string>
- <string name="lock_to_app_toast" msgid="1420543809500606964">"Para liberar esta tela, toque no botão \"Voltar\" e mantenha-o pressionado."</string>
+ <!-- no translation found for lock_to_app_toast (7693684144593484) -->
+ <skip />
<string name="lock_to_app_toast_locked" msgid="9125176335701699164">"O app está fixado. A liberação não é permitida neste dispositivo."</string>
<string name="lock_to_app_start" msgid="6643342070839862795">"Tela fixada"</string>
<string name="lock_to_app_exit" msgid="8598219838213787430">"Tela liberada"</string>
diff --git a/core/res/res/values-ro/strings.xml b/core/res/res/values-ro/strings.xml
index 7af49e8..378ea61 100644
--- a/core/res/res/values-ro/strings.xml
+++ b/core/res/res/values-ro/strings.xml
@@ -1583,7 +1583,8 @@
<string name="managed_profile_label_badge" msgid="2355652472854327647">"<xliff:g id="LABEL">%1$s</xliff:g> de serviciu"</string>
<string name="managed_profile_label_badge_2" msgid="5048136430082124036">"<xliff:g id="LABEL">%1$s</xliff:g> pentru serviciu (2)"</string>
<string name="managed_profile_label_badge_3" msgid="2808305070321719040">"<xliff:g id="LABEL">%1$s</xliff:g> pentru serviciu (3)"</string>
- <string name="lock_to_app_toast" msgid="1420543809500606964">"Pentru a anula fixarea acestui ecran, atingeți lung opțiunea Înapoi."</string>
+ <!-- no translation found for lock_to_app_toast (7693684144593484) -->
+ <skip />
<string name="lock_to_app_toast_locked" msgid="9125176335701699164">"Aplicația este fixată: Anularea fixării nu este permisă pe acest dispozitiv."</string>
<string name="lock_to_app_start" msgid="6643342070839862795">"Ecran fixat"</string>
<string name="lock_to_app_exit" msgid="8598219838213787430">"Fixarea ecranului anulată"</string>
diff --git a/core/res/res/values-ru/strings.xml b/core/res/res/values-ru/strings.xml
index 073033e..4887de9 100644
--- a/core/res/res/values-ru/strings.xml
+++ b/core/res/res/values-ru/strings.xml
@@ -1607,7 +1607,8 @@
<string name="managed_profile_label_badge" msgid="2355652472854327647">"Рабочий <xliff:g id="LABEL">%1$s</xliff:g>"</string>
<string name="managed_profile_label_badge_2" msgid="5048136430082124036">"Задача 2: <xliff:g id="LABEL">%1$s</xliff:g>"</string>
<string name="managed_profile_label_badge_3" msgid="2808305070321719040">"Задача 3: <xliff:g id="LABEL">%1$s</xliff:g>"</string>
- <string name="lock_to_app_toast" msgid="1420543809500606964">"Чтобы открепить экран, нажмите и удерживайте кнопку \"Назад\"."</string>
+ <!-- no translation found for lock_to_app_toast (7693684144593484) -->
+ <skip />
<string name="lock_to_app_toast_locked" msgid="9125176335701699164">"Включена блокировка в приложении. Ее отключение запрещено правилами организации."</string>
<string name="lock_to_app_start" msgid="6643342070839862795">"Блокировка включена"</string>
<string name="lock_to_app_exit" msgid="8598219838213787430">"Блокировка выключена"</string>
diff --git a/core/res/res/values-si-rLK/strings.xml b/core/res/res/values-si-rLK/strings.xml
index c9b231a..88d8de7 100644
--- a/core/res/res/values-si-rLK/strings.xml
+++ b/core/res/res/values-si-rLK/strings.xml
@@ -1561,7 +1561,8 @@
<string name="managed_profile_label_badge" msgid="2355652472854327647">"වැඩ <xliff:g id="LABEL">%1$s</xliff:g>"</string>
<string name="managed_profile_label_badge_2" msgid="5048136430082124036">"2වන වැඩ <xliff:g id="LABEL">%1$s</xliff:g>"</string>
<string name="managed_profile_label_badge_3" msgid="2808305070321719040">"3වන වැඩ <xliff:g id="LABEL">%1$s</xliff:g>"</string>
- <string name="lock_to_app_toast" msgid="1420543809500606964">"මෙම තිරය ඇමුණුම් ඉවත් කිරීමට, ස්පර්ශ කර අල්ලා ගෙන සිටින්න."</string>
+ <!-- no translation found for lock_to_app_toast (7693684144593484) -->
+ <skip />
<string name="lock_to_app_toast_locked" msgid="9125176335701699164">"යෙදුම අමුණා ඇත: ගැලවීමට මෙම උපාංගය මත ඉඩ දිය නොහැකිය."</string>
<string name="lock_to_app_start" msgid="6643342070839862795">"තිරය අගුළු දමා ඇත"</string>
<string name="lock_to_app_exit" msgid="8598219838213787430">"තිරයේ අගුළු ඇර ඇත"</string>
diff --git a/core/res/res/values-sk/strings.xml b/core/res/res/values-sk/strings.xml
index 298b70f..d731263c 100644
--- a/core/res/res/values-sk/strings.xml
+++ b/core/res/res/values-sk/strings.xml
@@ -1607,7 +1607,8 @@
<string name="managed_profile_label_badge" msgid="2355652472854327647">"Práca – <xliff:g id="LABEL">%1$s</xliff:g>"</string>
<string name="managed_profile_label_badge_2" msgid="5048136430082124036">"2. <xliff:g id="LABEL">%1$s</xliff:g> do práce"</string>
<string name="managed_profile_label_badge_3" msgid="2808305070321719040">"3. <xliff:g id="LABEL">%1$s</xliff:g> do práce"</string>
- <string name="lock_to_app_toast" msgid="1420543809500606964">"Ak chcete uvoľniť túto obrazovku, klepnite na tlačidlo Späť a podržte ho."</string>
+ <!-- no translation found for lock_to_app_toast (7693684144593484) -->
+ <skip />
<string name="lock_to_app_toast_locked" msgid="9125176335701699164">"Aplikácia je pripnutá. Uvoľnenie nie je na tomto zariadení povolené."</string>
<string name="lock_to_app_start" msgid="6643342070839862795">"Obrazovka bola pripnutá"</string>
<string name="lock_to_app_exit" msgid="8598219838213787430">"Obrazovka bola uvoľnená"</string>
diff --git a/core/res/res/values-sl/strings.xml b/core/res/res/values-sl/strings.xml
index c972bc0..717048d 100644
--- a/core/res/res/values-sl/strings.xml
+++ b/core/res/res/values-sl/strings.xml
@@ -1607,7 +1607,8 @@
<string name="managed_profile_label_badge" msgid="2355652472854327647">"<xliff:g id="LABEL">%1$s</xliff:g> za delo"</string>
<string name="managed_profile_label_badge_2" msgid="5048136430082124036">"2. službeni <xliff:g id="LABEL">%1$s</xliff:g>"</string>
<string name="managed_profile_label_badge_3" msgid="2808305070321719040">"3. službeni <xliff:g id="LABEL">%1$s</xliff:g>"</string>
- <string name="lock_to_app_toast" msgid="1420543809500606964">"Če želite odpeti ta zaslon, se dotaknite tipke za nazaj in jo pridržite."</string>
+ <!-- no translation found for lock_to_app_toast (7693684144593484) -->
+ <skip />
<string name="lock_to_app_toast_locked" msgid="9125176335701699164">"Aplikacija je pripeta: v tej napravi odpenjanje ni dovoljeno."</string>
<string name="lock_to_app_start" msgid="6643342070839862795">"Zaslon je pripet"</string>
<string name="lock_to_app_exit" msgid="8598219838213787430">"Zaslon je odpet"</string>
diff --git a/core/res/res/values-sq-rAL/strings.xml b/core/res/res/values-sq-rAL/strings.xml
index bf5110b..25786840 100644
--- a/core/res/res/values-sq-rAL/strings.xml
+++ b/core/res/res/values-sq-rAL/strings.xml
@@ -1559,7 +1559,8 @@
<string name="managed_profile_label_badge" msgid="2355652472854327647">"Puna <xliff:g id="LABEL">%1$s</xliff:g>"</string>
<string name="managed_profile_label_badge_2" msgid="5048136430082124036">"<xliff:g id="LABEL">%1$s</xliff:g> i dytë i punës"</string>
<string name="managed_profile_label_badge_3" msgid="2808305070321719040">"<xliff:g id="LABEL">%1$s</xliff:g> i tretë i punës"</string>
- <string name="lock_to_app_toast" msgid="1420543809500606964">"Për të hequr gozhdimin e ekranit, prek dhe mbaj të shtypur \"Prapa\"."</string>
+ <!-- no translation found for lock_to_app_toast (7693684144593484) -->
+ <skip />
<string name="lock_to_app_toast_locked" msgid="9125176335701699164">"Ekrani është i gozhduar. Anulimi i mbërthimit nuk lejohet nga organizata jote."</string>
<string name="lock_to_app_start" msgid="6643342070839862795">"Ekrani u gozhdua"</string>
<string name="lock_to_app_exit" msgid="8598219838213787430">"Ekrani u hoq nga gozhdimi"</string>
diff --git a/core/res/res/values-sr/strings.xml b/core/res/res/values-sr/strings.xml
index b5adb2c..70f93bf 100644
--- a/core/res/res/values-sr/strings.xml
+++ b/core/res/res/values-sr/strings.xml
@@ -1583,7 +1583,8 @@
<string name="managed_profile_label_badge" msgid="2355652472854327647">"<xliff:g id="LABEL">%1$s</xliff:g> на послу"</string>
<string name="managed_profile_label_badge_2" msgid="5048136430082124036">"2. пословни <xliff:g id="LABEL">%1$s</xliff:g>"</string>
<string name="managed_profile_label_badge_3" msgid="2808305070321719040">"3. пословни имејл <xliff:g id="LABEL">%1$s</xliff:g>"</string>
- <string name="lock_to_app_toast" msgid="1420543809500606964">"Да бисте откачили овај екран, додирните и задржите Назад."</string>
+ <!-- no translation found for lock_to_app_toast (7693684144593484) -->
+ <skip />
<string name="lock_to_app_toast_locked" msgid="9125176335701699164">"Апликација је закачена: откачињање није дозвољено на овом уређају."</string>
<string name="lock_to_app_start" msgid="6643342070839862795">"Екран је закачен"</string>
<string name="lock_to_app_exit" msgid="8598219838213787430">"Екран је откачен"</string>
diff --git a/core/res/res/values-sv/strings.xml b/core/res/res/values-sv/strings.xml
index dfedf4c..3071cb1 100644
--- a/core/res/res/values-sv/strings.xml
+++ b/core/res/res/values-sv/strings.xml
@@ -1559,7 +1559,8 @@
<string name="managed_profile_label_badge" msgid="2355652472854327647">"<xliff:g id="LABEL">%1$s</xliff:g> för arbetet"</string>
<string name="managed_profile_label_badge_2" msgid="5048136430082124036">"Andra <xliff:g id="LABEL">%1$s</xliff:g> för jobbet"</string>
<string name="managed_profile_label_badge_3" msgid="2808305070321719040">"Tredje <xliff:g id="LABEL">%1$s</xliff:g> för jobbet"</string>
- <string name="lock_to_app_toast" msgid="1420543809500606964">"Om du vill lossa skärmen trycker du länge på Tillbaka."</string>
+ <!-- no translation found for lock_to_app_toast (7693684144593484) -->
+ <skip />
<string name="lock_to_app_toast_locked" msgid="9125176335701699164">"Appen är fäst. Att lossa den är inte tillåtet på den här enheten."</string>
<string name="lock_to_app_start" msgid="6643342070839862795">"Skärmen är fäst"</string>
<string name="lock_to_app_exit" msgid="8598219838213787430">"Skärmen är inte längre fäst"</string>
diff --git a/core/res/res/values-sw/strings.xml b/core/res/res/values-sw/strings.xml
index 6cd3b89..8d9f85b 100644
--- a/core/res/res/values-sw/strings.xml
+++ b/core/res/res/values-sw/strings.xml
@@ -1557,7 +1557,8 @@
<string name="managed_profile_label_badge" msgid="2355652472854327647">"Ya kazini <xliff:g id="LABEL">%1$s</xliff:g>"</string>
<string name="managed_profile_label_badge_2" msgid="5048136430082124036">"<xliff:g id="LABEL">%1$s</xliff:g> ya 2 ya Kazini"</string>
<string name="managed_profile_label_badge_3" msgid="2808305070321719040">"<xliff:g id="LABEL">%1$s</xliff:g> ya 3 ya Kazini"</string>
- <string name="lock_to_app_toast" msgid="1420543809500606964">"Ili kubandua skrini hii, gusa na ushikilie Nyuma."</string>
+ <!-- no translation found for lock_to_app_toast (7693684144593484) -->
+ <skip />
<string name="lock_to_app_toast_locked" msgid="9125176335701699164">"Programu imebanwa: Kubanuliwa hakuruhusiwi kwenye kifaa hiki."</string>
<string name="lock_to_app_start" msgid="6643342070839862795">"Skrini imebandikwa"</string>
<string name="lock_to_app_exit" msgid="8598219838213787430">"Skrini imebanduliwa"</string>
diff --git a/core/res/res/values-ta-rIN/strings.xml b/core/res/res/values-ta-rIN/strings.xml
index abc9f6e..08b6802 100644
--- a/core/res/res/values-ta-rIN/strings.xml
+++ b/core/res/res/values-ta-rIN/strings.xml
@@ -1559,7 +1559,8 @@
<string name="managed_profile_label_badge" msgid="2355652472854327647">"பணியிடம் <xliff:g id="LABEL">%1$s</xliff:g>"</string>
<string name="managed_profile_label_badge_2" msgid="5048136430082124036">"2வது பணி <xliff:g id="LABEL">%1$s</xliff:g>"</string>
<string name="managed_profile_label_badge_3" msgid="2808305070321719040">"3வது பணி <xliff:g id="LABEL">%1$s</xliff:g>"</string>
- <string name="lock_to_app_toast" msgid="1420543809500606964">"இந்தத் திரையை விலக்க, \"முந்தையது\" பொத்தானைத் தொட்டுப் பிடிக்கவும்."</string>
+ <!-- no translation found for lock_to_app_toast (7693684144593484) -->
+ <skip />
<string name="lock_to_app_toast_locked" msgid="9125176335701699164">"பயன்பாடு பொருத்தப்பட்டது: பொருத்தியதை நீக்குவதற்கு இந்தச் சாதனத்தில் அனுமதியில்லை."</string>
<string name="lock_to_app_start" msgid="6643342070839862795">"திரை பின் செய்யப்பட்டது"</string>
<string name="lock_to_app_exit" msgid="8598219838213787430">"திரையின் பின் அகற்றப்பட்டது"</string>
diff --git a/core/res/res/values-te-rIN/strings.xml b/core/res/res/values-te-rIN/strings.xml
index 90db049..29a43de 100644
--- a/core/res/res/values-te-rIN/strings.xml
+++ b/core/res/res/values-te-rIN/strings.xml
@@ -1559,7 +1559,8 @@
<string name="managed_profile_label_badge" msgid="2355652472854327647">"కార్యాలయం <xliff:g id="LABEL">%1$s</xliff:g>"</string>
<string name="managed_profile_label_badge_2" msgid="5048136430082124036">"2వ కార్యాలయం <xliff:g id="LABEL">%1$s</xliff:g>"</string>
<string name="managed_profile_label_badge_3" msgid="2808305070321719040">"3వ కార్యాలయం <xliff:g id="LABEL">%1$s</xliff:g>"</string>
- <string name="lock_to_app_toast" msgid="1420543809500606964">"ఈ స్క్రీన్ని అన్పిన్ చేయడానికి, వెనుకకు తాకి & అలాగే పట్టుకోండి."</string>
+ <!-- no translation found for lock_to_app_toast (7693684144593484) -->
+ <skip />
<string name="lock_to_app_toast_locked" msgid="9125176335701699164">"అనువర్తనం పిన్ చేయబడింది: ఈ పరికరంలో అన్పిన్ చేయడానికి అనుమతి లేదు."</string>
<string name="lock_to_app_start" msgid="6643342070839862795">"స్క్రీన్ పిన్ చేయబడింది"</string>
<string name="lock_to_app_exit" msgid="8598219838213787430">"స్క్రీన్ అన్పిన్ చేయబడింది"</string>
diff --git a/core/res/res/values-th/strings.xml b/core/res/res/values-th/strings.xml
index 5395fba..453e0ae 100644
--- a/core/res/res/values-th/strings.xml
+++ b/core/res/res/values-th/strings.xml
@@ -1559,7 +1559,8 @@
<string name="managed_profile_label_badge" msgid="2355652472854327647">"<xliff:g id="LABEL">%1$s</xliff:g>ที่ทำงาน"</string>
<string name="managed_profile_label_badge_2" msgid="5048136430082124036">"<xliff:g id="LABEL">%1$s</xliff:g> งานที่ 2"</string>
<string name="managed_profile_label_badge_3" msgid="2808305070321719040">"<xliff:g id="LABEL">%1$s</xliff:g> งานที่ 3"</string>
- <string name="lock_to_app_toast" msgid="1420543809500606964">"หากต้องการเลิกตรึงหน้าจอนี้ แตะ \"กลับ\" ค้างไว้"</string>
+ <!-- no translation found for lock_to_app_toast (7693684144593484) -->
+ <skip />
<string name="lock_to_app_toast_locked" msgid="9125176335701699164">"มีการตรึงแอป: ไม่อนุญาตให้เลิกตรึงบนอุปกรณ์นี้"</string>
<string name="lock_to_app_start" msgid="6643342070839862795">"ตรึงหน้าจอแล้ว"</string>
<string name="lock_to_app_exit" msgid="8598219838213787430">"เลิกตรึงหน้าจอแล้ว"</string>
diff --git a/core/res/res/values-tl/strings.xml b/core/res/res/values-tl/strings.xml
index bbe45f5..d9be9d9 100644
--- a/core/res/res/values-tl/strings.xml
+++ b/core/res/res/values-tl/strings.xml
@@ -1559,7 +1559,8 @@
<string name="managed_profile_label_badge" msgid="2355652472854327647">"<xliff:g id="LABEL">%1$s</xliff:g> sa Trabaho"</string>
<string name="managed_profile_label_badge_2" msgid="5048136430082124036">"Pangalawang <xliff:g id="LABEL">%1$s</xliff:g> sa Trabaho"</string>
<string name="managed_profile_label_badge_3" msgid="2808305070321719040">"Pangatlong <xliff:g id="LABEL">%1$s</xliff:g> sa Trabaho"</string>
- <string name="lock_to_app_toast" msgid="1420543809500606964">"Upang i-unpin ang screen na ito, pindutin nang matagal ang Bumalik."</string>
+ <!-- no translation found for lock_to_app_toast (7693684144593484) -->
+ <skip />
<string name="lock_to_app_toast_locked" msgid="9125176335701699164">"Naka-pin ang app: Hindi pinapayagan ang pag-a-unpin sa device na ito."</string>
<string name="lock_to_app_start" msgid="6643342070839862795">"Naka-pin ang screen"</string>
<string name="lock_to_app_exit" msgid="8598219838213787430">"Naka-unpin ang screen"</string>
diff --git a/core/res/res/values-tr/strings.xml b/core/res/res/values-tr/strings.xml
index ac184a4..067e4c8 100644
--- a/core/res/res/values-tr/strings.xml
+++ b/core/res/res/values-tr/strings.xml
@@ -1559,7 +1559,8 @@
<string name="managed_profile_label_badge" msgid="2355652472854327647">"<xliff:g id="LABEL">%1$s</xliff:g> (İş)"</string>
<string name="managed_profile_label_badge_2" msgid="5048136430082124036">"İş için 2. <xliff:g id="LABEL">%1$s</xliff:g>"</string>
<string name="managed_profile_label_badge_3" msgid="2808305070321719040">"İş için 3. <xliff:g id="LABEL">%1$s</xliff:g>"</string>
- <string name="lock_to_app_toast" msgid="1420543809500606964">"Bu ekranın sabitlemesini kaldırmak için Geri\'ye dokunup basılı tutun."</string>
+ <!-- no translation found for lock_to_app_toast (7693684144593484) -->
+ <skip />
<string name="lock_to_app_toast_locked" msgid="9125176335701699164">"Uygulama sabitlendi. Bu cihazda sabitlemenin kaldırılmasına izin verilmiyor."</string>
<string name="lock_to_app_start" msgid="6643342070839862795">"Ekran sabitlendi"</string>
<string name="lock_to_app_exit" msgid="8598219838213787430">"Ekran sabitlemesi kaldırıldı"</string>
diff --git a/core/res/res/values-uk/strings.xml b/core/res/res/values-uk/strings.xml
index def0cbf..2af72cd 100644
--- a/core/res/res/values-uk/strings.xml
+++ b/core/res/res/values-uk/strings.xml
@@ -1607,7 +1607,8 @@
<string name="managed_profile_label_badge" msgid="2355652472854327647">"Робоча <xliff:g id="LABEL">%1$s</xliff:g>"</string>
<string name="managed_profile_label_badge_2" msgid="5048136430082124036">"2-а робота: <xliff:g id="LABEL">%1$s</xliff:g>"</string>
<string name="managed_profile_label_badge_3" msgid="2808305070321719040">"3-я робота: <xliff:g id="LABEL">%1$s</xliff:g>"</string>
- <string name="lock_to_app_toast" msgid="1420543809500606964">"Щоб відкріпити цей екран, натисніть і утримуйте кнопку \"Назад\"."</string>
+ <!-- no translation found for lock_to_app_toast (7693684144593484) -->
+ <skip />
<string name="lock_to_app_toast_locked" msgid="9125176335701699164">"Додаток закріплено. Його не можна відкріпити на цьому пристрої."</string>
<string name="lock_to_app_start" msgid="6643342070839862795">"Екран закріплено"</string>
<string name="lock_to_app_exit" msgid="8598219838213787430">"Екран відкріплено"</string>
diff --git a/core/res/res/values-ur-rPK/strings.xml b/core/res/res/values-ur-rPK/strings.xml
index 17b657d..5f09905 100644
--- a/core/res/res/values-ur-rPK/strings.xml
+++ b/core/res/res/values-ur-rPK/strings.xml
@@ -1559,7 +1559,8 @@
<string name="managed_profile_label_badge" msgid="2355652472854327647">"دفتر <xliff:g id="LABEL">%1$s</xliff:g>"</string>
<string name="managed_profile_label_badge_2" msgid="5048136430082124036">"دوسرا کام <xliff:g id="LABEL">%1$s</xliff:g>"</string>
<string name="managed_profile_label_badge_3" msgid="2808305070321719040">"تیسرا کام <xliff:g id="LABEL">%1$s</xliff:g>"</string>
- <string name="lock_to_app_toast" msgid="1420543809500606964">"اس اسکرین سے پن ہٹانے کیلئے، پیچھے کو تھپتھپائیں اور دبا کر رکھیں۔"</string>
+ <!-- no translation found for lock_to_app_toast (7693684144593484) -->
+ <skip />
<string name="lock_to_app_toast_locked" msgid="9125176335701699164">"ایپ کو پن کر دیا گیا ہے: اس آلہ پر پن ہٹانے کی اجازت نہیں ہے۔"</string>
<string name="lock_to_app_start" msgid="6643342070839862795">"اسکرین کو پن کر دیا گیا"</string>
<string name="lock_to_app_exit" msgid="8598219838213787430">"اسکرین کا پن ہٹا دیا گیا"</string>
diff --git a/core/res/res/values-uz-rUZ/strings.xml b/core/res/res/values-uz-rUZ/strings.xml
index bc17d6e..489aeb7 100644
--- a/core/res/res/values-uz-rUZ/strings.xml
+++ b/core/res/res/values-uz-rUZ/strings.xml
@@ -703,7 +703,7 @@
<string name="lockscreen_transport_stop_description" msgid="5907083260651210034">"To‘xtatish"</string>
<string name="lockscreen_transport_rew_description" msgid="6944412838651990410">"Orqaga o‘tkazish"</string>
<string name="lockscreen_transport_ffw_description" msgid="42987149870928985">"Oldinga o‘tkazish"</string>
- <string name="emergency_calls_only" msgid="6733978304386365407">"Faqat favqulodda qo‘ng‘iroqlar"</string>
+ <string name="emergency_calls_only" msgid="6733978304386365407">"Faqat favqulodda chaqiruvlar"</string>
<string name="lockscreen_network_locked_message" msgid="143389224986028501">"Tarmoq qulflangan"</string>
<string name="lockscreen_sim_puk_locked_message" msgid="7441797339976230">"SIM karta PUK kod bilan qulflangan."</string>
<string name="lockscreen_sim_puk_locked_instructions" msgid="8127916255245181063">"Foydalanuvchi qo‘llanmasiga qarang yoki Abonentlarni qo‘llab-quvvatlash markaziga murojaat qiling."</string>
@@ -1559,7 +1559,8 @@
<string name="managed_profile_label_badge" msgid="2355652472854327647">"Ish <xliff:g id="LABEL">%1$s</xliff:g>"</string>
<string name="managed_profile_label_badge_2" msgid="5048136430082124036">"2-ishxona <xliff:g id="LABEL">%1$s</xliff:g>"</string>
<string name="managed_profile_label_badge_3" msgid="2808305070321719040">"3-ishxona <xliff:g id="LABEL">%1$s</xliff:g>"</string>
- <string name="lock_to_app_toast" msgid="1420543809500606964">"Bu ekrandan chiqish uchun “Orqaga” tugmasini bosib turing."</string>
+ <!-- no translation found for lock_to_app_toast (7693684144593484) -->
+ <skip />
<string name="lock_to_app_toast_locked" msgid="9125176335701699164">"Ilova qadab qo‘yilgan. Uni ekrandan yechish ushbu qurilmada ta’qiqlangan."</string>
<string name="lock_to_app_start" msgid="6643342070839862795">"Ekran qadab qo‘yildi"</string>
<string name="lock_to_app_exit" msgid="8598219838213787430">"Ekran bo‘shatildi"</string>
diff --git a/core/res/res/values-vi/strings.xml b/core/res/res/values-vi/strings.xml
index 8448f38..68bd578 100644
--- a/core/res/res/values-vi/strings.xml
+++ b/core/res/res/values-vi/strings.xml
@@ -1559,7 +1559,8 @@
<string name="managed_profile_label_badge" msgid="2355652472854327647">"<xliff:g id="LABEL">%1$s</xliff:g> làm việc"</string>
<string name="managed_profile_label_badge_2" msgid="5048136430082124036">"Công việc thứ 2 <xliff:g id="LABEL">%1$s</xliff:g>"</string>
<string name="managed_profile_label_badge_3" msgid="2808305070321719040">"Công việc thứ 2 <xliff:g id="LABEL">%1$s</xliff:g>"</string>
- <string name="lock_to_app_toast" msgid="1420543809500606964">"Để bỏ ghim màn hình này, nhấn và giữ Quay lại."</string>
+ <!-- no translation found for lock_to_app_toast (7693684144593484) -->
+ <skip />
<string name="lock_to_app_toast_locked" msgid="9125176335701699164">"Ứng dụng được ghim: Không được phép bỏ ghim trên thiết bị này."</string>
<string name="lock_to_app_start" msgid="6643342070839862795">"Đã ghim màn hình"</string>
<string name="lock_to_app_exit" msgid="8598219838213787430">"Đã bỏ ghim màn hình"</string>
diff --git a/core/res/res/values-zh-rCN/strings.xml b/core/res/res/values-zh-rCN/strings.xml
index 4d80c82..aa127144 100644
--- a/core/res/res/values-zh-rCN/strings.xml
+++ b/core/res/res/values-zh-rCN/strings.xml
@@ -298,9 +298,9 @@
<string name="permdesc_readCellBroadcasts" msgid="6361972776080458979">"允许应用读取您的设备收到的小区广播消息。小区广播消息是在某些地区发送的、用于发布紧急情况警告的提醒信息。恶意应用可能会在您收到小区紧急广播时干扰您设备的性能或操作。"</string>
<string name="permlab_subscribedFeedsRead" msgid="4756609637053353318">"读取订阅的供稿"</string>
<string name="permdesc_subscribedFeedsRead" msgid="5557058907906144505">"允许应用获取有关当前同步的 Feed 的详情。"</string>
- <string name="permlab_sendSms" msgid="7544599214260982981">"发送和查看短信"</string>
+ <string name="permlab_sendSms" msgid="7544599214260982981">"发送短信"</string>
<string name="permdesc_sendSms" msgid="7094729298204937667">"允许该应用发送短信。此权限可能会导致意外收费。恶意应用可能会未经您的确认而发送短信,由此产生相关费用。"</string>
- <string name="permlab_readSms" msgid="8745086572213270480">"读取您的讯息(短信或彩信)"</string>
+ <string name="permlab_readSms" msgid="8745086572213270480">"读取短信"</string>
<string name="permdesc_readSms" product="tablet" msgid="4741697454888074891">"此应用可读取您平板电脑上存储的所有短信。"</string>
<string name="permdesc_readSms" product="tv" msgid="5796670395641116592">"此应用可读取您电视上存储的所有短信。"</string>
<string name="permdesc_readSms" product="default" msgid="6826832415656437652">"此应用可读取您手机上存储的所有短信。"</string>
@@ -334,7 +334,7 @@
<string name="permdesc_broadcastSticky" product="tablet" msgid="7749760494399915651">"允许该应用发送持久广播消息,此类消息在广播结束后仍会保留。过度使用可能会导致平板电脑使用过多内存,从而降低其速度或稳定性。"</string>
<string name="permdesc_broadcastSticky" product="tv" msgid="6839285697565389467">"允许应用发送持久广播消息,此类消息在广播结束后仍会保留。过度使用可能会导致电视使用过多内存,从而降低其速度或稳定性。"</string>
<string name="permdesc_broadcastSticky" product="default" msgid="2825803764232445091">"允许该应用发送持久广播消息,此类消息在广播结束后仍会保留。过度使用可能会导致手机使用过多内存,从而降低其速度或稳定性。"</string>
- <string name="permlab_readContacts" msgid="8348481131899886131">"读取您的通讯录"</string>
+ <string name="permlab_readContacts" msgid="8348481131899886131">"读取联系人"</string>
<string name="permdesc_readContacts" product="tablet" msgid="5294866856941149639">"允许该应用读取您平板电脑上存储的联系人的相关数据,包括您通过打电话、发送电子邮件或以其他方式与特定个人通信的频率。此权限可让应用保存您的联系人数据,而恶意应用可能会在您不知情的情况下分享联系人数据。"</string>
<string name="permdesc_readContacts" product="tv" msgid="1839238344654834087">"允许应用读取您的电视上存储的联系人相关数据,包括您与特定联系人通话、发送电子邮件或通过其他方式进行通信的频率。此权限可让应用保存您的联系人数据,而且恶意应用可能会在您不知情的情况下分享联系人数据。"</string>
<string name="permdesc_readContacts" product="default" msgid="8440654152457300662">"允许该应用读取您手机上存储的联系人的相关数据,包括您通过打电话、发送电子邮件或以其他方式与特定个人通信的频率。此权限可让应用保存您的联系人数据,而恶意应用可能会在您不知情的情况下分享联系人数据。"</string>
@@ -344,7 +344,7 @@
<string name="permdesc_writeContacts" product="default" msgid="589869224625163558">"允许该应用修改您手机上存储的联系人的相关数据,包括您通过打电话、发送电子邮件或以其他方式与特定联系人通信的频率。此权限可让应用删除联系人数据。"</string>
<string name="permlab_readCallLog" msgid="3478133184624102739">"读取通话记录"</string>
<string name="permdesc_readCallLog" msgid="3204122446463552146">"此应用可读取您的通话记录。"</string>
- <string name="permlab_writeCallLog" msgid="8552045664743499354">"写入通话记录"</string>
+ <string name="permlab_writeCallLog" msgid="8552045664743499354">"新建/修改/删除通话记录"</string>
<string name="permdesc_writeCallLog" product="tablet" msgid="6661806062274119245">"允许该应用修改平板电脑的通话记录,包括有关来电和外拨电话的数据。恶意应用可能会借此清除或修改您的通话记录。"</string>
<string name="permdesc_writeCallLog" product="tv" msgid="4225034892248398019">"允许应用修改电视的通话记录,包括有关来电和外拨电话的数据。恶意应用可能会借此清除或修改您的通话记录。"</string>
<string name="permdesc_writeCallLog" product="default" msgid="683941736352787842">"允许该应用修改手机的通话记录,包括有关来电和外拨电话的数据。恶意应用可能会借此清除或修改您的通话记录。"</string>
@@ -376,7 +376,7 @@
<string name="permdesc_camera" msgid="5392231870049240670">"此应用可随时使用相机拍摄照片和录制视频。"</string>
<string name="permlab_vibrate" msgid="7696427026057705834">"控制振动"</string>
<string name="permdesc_vibrate" msgid="6284989245902300945">"允许应用控制振动器。"</string>
- <string name="permlab_callPhone" msgid="3925836347681847954">"直接拨打电话号码"</string>
+ <string name="permlab_callPhone" msgid="3925836347681847954">"拨打电话"</string>
<string name="permdesc_callPhone" msgid="3740797576113760827">"允许该应用在您未执行操作的情况下拨打电话号码。此权限可能会导致意外收费或呼叫。请注意,此权限不允许该应用拨打紧急电话号码。恶意应用可通过拨打电话产生相关费用,而无需您的确认。"</string>
<string name="permlab_accessImsCallService" msgid="3574943847181793918">"使用即时通讯通话服务"</string>
<string name="permdesc_accessImsCallService" msgid="8992884015198298775">"允许应用自行使用即时通讯服务拨打电话。"</string>
@@ -1559,7 +1559,8 @@
<string name="managed_profile_label_badge" msgid="2355652472854327647">"工作<xliff:g id="LABEL">%1$s</xliff:g>"</string>
<string name="managed_profile_label_badge_2" msgid="5048136430082124036">"第二个工作<xliff:g id="LABEL">%1$s</xliff:g>"</string>
<string name="managed_profile_label_badge_3" msgid="2808305070321719040">"第三个工作<xliff:g id="LABEL">%1$s</xliff:g>"</string>
- <string name="lock_to_app_toast" msgid="1420543809500606964">"要取消固定此屏幕,请触摸并按住“返回”按钮。"</string>
+ <!-- no translation found for lock_to_app_toast (7693684144593484) -->
+ <skip />
<string name="lock_to_app_toast_locked" msgid="9125176335701699164">"应用处于固定状态:在此设备上不允许退出该模式。"</string>
<string name="lock_to_app_start" msgid="6643342070839862795">"已固定屏幕"</string>
<string name="lock_to_app_exit" msgid="8598219838213787430">"已取消固定屏幕"</string>
diff --git a/core/res/res/values-zh-rHK/strings.xml b/core/res/res/values-zh-rHK/strings.xml
index 410548e..09141a1 100644
--- a/core/res/res/values-zh-rHK/strings.xml
+++ b/core/res/res/values-zh-rHK/strings.xml
@@ -1559,7 +1559,8 @@
<string name="managed_profile_label_badge" msgid="2355652472854327647">"公司<xliff:g id="LABEL">%1$s</xliff:g>"</string>
<string name="managed_profile_label_badge_2" msgid="5048136430082124036">"第二個工作<xliff:g id="LABEL">%1$s</xliff:g>"</string>
<string name="managed_profile_label_badge_3" msgid="2808305070321719040">"第三個工作<xliff:g id="LABEL">%1$s</xliff:g>"</string>
- <string name="lock_to_app_toast" msgid="1420543809500606964">"如要取消固定這個畫面,請按住 [返回]。"</string>
+ <!-- no translation found for lock_to_app_toast (7693684144593484) -->
+ <skip />
<string name="lock_to_app_toast_locked" msgid="9125176335701699164">"應用程式已固定:不允許在此裝置上取消固定。"</string>
<string name="lock_to_app_start" msgid="6643342070839862795">"螢幕已固定"</string>
<string name="lock_to_app_exit" msgid="8598219838213787430">"已取消固定螢幕"</string>
diff --git a/core/res/res/values-zh-rTW/strings.xml b/core/res/res/values-zh-rTW/strings.xml
index 51f6d7d..bc57595 100644
--- a/core/res/res/values-zh-rTW/strings.xml
+++ b/core/res/res/values-zh-rTW/strings.xml
@@ -1559,7 +1559,8 @@
<string name="managed_profile_label_badge" msgid="2355652472854327647">"公司<xliff:g id="LABEL">%1$s</xliff:g>"</string>
<string name="managed_profile_label_badge_2" msgid="5048136430082124036">"第 2 項工作:<xliff:g id="LABEL">%1$s</xliff:g>"</string>
<string name="managed_profile_label_badge_3" msgid="2808305070321719040">"第 3 項工作:<xliff:g id="LABEL">%1$s</xliff:g>"</string>
- <string name="lock_to_app_toast" msgid="1420543809500606964">"如要取消固定這個畫面,請按住「返回」按鈕。"</string>
+ <!-- no translation found for lock_to_app_toast (7693684144593484) -->
+ <skip />
<string name="lock_to_app_toast_locked" msgid="9125176335701699164">"應用程式已固定:無法在這部裝置取消固定。"</string>
<string name="lock_to_app_start" msgid="6643342070839862795">"已固定螢幕"</string>
<string name="lock_to_app_exit" msgid="8598219838213787430">"已取消固定螢幕"</string>
diff --git a/core/res/res/values-zu/strings.xml b/core/res/res/values-zu/strings.xml
index a26c765..e5ad8d7 100644
--- a/core/res/res/values-zu/strings.xml
+++ b/core/res/res/values-zu/strings.xml
@@ -1559,7 +1559,8 @@
<string name="managed_profile_label_badge" msgid="2355652472854327647">"Umsebenzi <xliff:g id="LABEL">%1$s</xliff:g>"</string>
<string name="managed_profile_label_badge_2" msgid="5048136430082124036">"Umsebenzi wesibili <xliff:g id="LABEL">%1$s</xliff:g>"</string>
<string name="managed_profile_label_badge_3" msgid="2808305070321719040">"Umsebenzi wesithathu <xliff:g id="LABEL">%1$s</xliff:g>"</string>
- <string name="lock_to_app_toast" msgid="1420543809500606964">"Ukuze ususe ukuphina lesi sikrini, thinta futhi ubambe okuthi Emuva."</string>
+ <!-- no translation found for lock_to_app_toast (7693684144593484) -->
+ <skip />
<string name="lock_to_app_toast_locked" msgid="9125176335701699164">"Uhlelo lokusebenza luphiniwe: Ukususa ukuphina akuvunyelwe kule divayisi."</string>
<string name="lock_to_app_start" msgid="6643342070839862795">"Isikrini siphiniwe"</string>
<string name="lock_to_app_exit" msgid="8598219838213787430">"Isikrini sisuswe ukuphina"</string>
diff --git a/core/res/res/values/attrs.xml b/core/res/res/values/attrs.xml
index 05658b0..37b3ffc 100644
--- a/core/res/res/values/attrs.xml
+++ b/core/res/res/values/attrs.xml
@@ -7009,6 +7009,12 @@
for more info. -->
<attr name="actionProviderClass" format="string" />
+ <!-- The content description associated with the item. -->
+ <attr name="contentDescription" format="string" />
+
+ <!-- The tooltip text associated with the item. -->
+ <attr name="tooltip" format="string" />
+
</declare-styleable>
<!-- Attrbitutes for a ActvityChooserView. -->
diff --git a/core/res/res/values/bools.xml b/core/res/res/values/bools.xml
index 5c50e73..b49fe49 100644
--- a/core/res/res/values/bools.xml
+++ b/core/res/res/values/bools.xml
@@ -24,4 +24,10 @@
<bool name="show_ongoing_ime_switcher">true</bool>
<bool name="action_bar_expanded_action_views_exclusive">true</bool>
<bool name="target_honeycomb_needs_options_menu">true</bool>
+ <!-- Whether or not to use the drawable/lockscreen_notselected and
+ drawable/lockscreen_selected instead of the generic dots when displaying
+ the LockPatternView.
+ <p>The main purpose is for OEMs to customize the rendering of the
+ lockscreen, setting this to true should come with customized drawables. -->
+ <bool name="use_lock_pattern_drawable">false</bool>
</resources>
diff --git a/core/res/res/values/config.xml b/core/res/res/values/config.xml
index 5967c69..9cbb8c3 100644
--- a/core/res/res/values/config.xml
+++ b/core/res/res/values/config.xml
@@ -1260,9 +1260,8 @@
<!-- A list of potential packages, in priority order, that may contain a
network recommendation provider. A network recommendation provider must:
* Be granted the SCORE_NETWORKS permission.
- * Include a Receiver for the android.net.scoring.SCORE_NETWORKS action guarded by the
- BROADCAST_NETWORK_PRIVILEGED permission.
- * Include a Service for the android.net.scoring.RECOMMEND_NETWORKS action.
+ * Include a Service for the android.net.scoring.RECOMMEND_NETWORKS action
+ protected by the BIND_NETWORK_RECOMMENDATION_SERVICE permission.
This may be empty if network scoring and recommending isn't supported.
-->
@@ -2697,4 +2696,7 @@
<!-- Flag indicates that whether non-system apps can be installed on internal storage. -->
<bool name="config_allow3rdPartyAppOnInternal">true</bool>
+
+ <!-- Component name of the default cell broadcast receiver -->
+ <string name="config_defaultCellBroadcastReceiverComponent" translatable="false">com.android.cellbroadcastreceiver/.PrivilegedCellBroadcastReceiver</string>
</resources>
diff --git a/core/res/res/values/dimens.xml b/core/res/res/values/dimens.xml
index e3b7f02..bd19521 100644
--- a/core/res/res/values/dimens.xml
+++ b/core/res/res/values/dimens.xml
@@ -64,6 +64,9 @@
when the user opens homescreen. -->
<dimen name="docked_stack_minimize_thickness">8dp</dimen>
+ <!-- The amount to leave on-screen when the PIP is minimized. -->
+ <dimen name="pip_minimized_visible_size">48dp</dimen>
+
<!-- Min width for a tablet device -->
<dimen name="min_xlarge_screen_width">800dp</dimen>
diff --git a/core/res/res/values/strings.xml b/core/res/res/values/strings.xml
index 880944e..b7f5a9b 100644
--- a/core/res/res/values/strings.xml
+++ b/core/res/res/values/strings.xml
@@ -4135,7 +4135,7 @@
<string name="date_picker_day_typeface">sans-serif-medium</string>
<!-- Notify use that they are in Lock-to-app -->
- <string name="lock_to_app_toast">To unpin this screen, touch & hold Back.</string>
+ <string name="lock_to_app_toast">To unpin this screen, touch & hold Back and Overview.</string>
<!-- Notify user that they are locked in lock-to-app mode -->
<string name="lock_to_app_toast_locked">App is pinned: Unpinning isn\'t allowed on this device.</string>
<!-- Starting lock-to-app indication. -->
diff --git a/core/res/res/values/styles.xml b/core/res/res/values/styles.xml
index 0f756b9..ce7ab16 100644
--- a/core/res/res/values/styles.xml
+++ b/core/res/res/values/styles.xml
@@ -1290,6 +1290,7 @@
<style name="Widget.ActionButton.Overflow">
<item name="src">@drawable/ic_menu_more</item>
<item name="contentDescription">@string/action_menu_overflow_description</item>
+ <item name="tooltip">@string/action_menu_overflow_description</item>
</style>
<style name="Widget.ActionButton.CloseMode">
diff --git a/core/res/res/values/styles_holo.xml b/core/res/res/values/styles_holo.xml
index 8ca12ae..12b8164 100644
--- a/core/res/res/values/styles_holo.xml
+++ b/core/res/res/values/styles_holo.xml
@@ -660,6 +660,7 @@
<item name="src">@drawable/ic_menu_moreoverflow_holo_dark</item>
<item name="background">?attr/actionBarItemBackground</item>
<item name="contentDescription">@string/action_menu_overflow_description</item>
+ <item name="tooltip">@string/action_menu_overflow_description</item>
</style>
<style name="Widget.Holo.ActionButton.TextButton" parent="Widget.Holo.ButtonBar.Button" />
@@ -994,6 +995,7 @@
<style name="Widget.Holo.Light.ActionButton.Overflow">
<item name="src">@drawable/ic_menu_moreoverflow_holo_light</item>
<item name="contentDescription">@string/action_menu_overflow_description</item>
+ <item name="tooltip">@string/action_menu_overflow_description</item>
</style>
<style name="Widget.Holo.Light.ActionBar.TabView" parent="Widget.Holo.ActionBar.TabView" />
diff --git a/core/res/res/values/styles_material.xml b/core/res/res/values/styles_material.xml
index a1e12d2..709200e 100644
--- a/core/res/res/values/styles_material.xml
+++ b/core/res/res/values/styles_material.xml
@@ -944,6 +944,7 @@
<item name="src">@drawable/ic_menu_moreoverflow_material</item>
<item name="background">?attr/actionBarItemBackground</item>
<item name="contentDescription">@string/action_menu_overflow_description</item>
+ <item name="tooltip">@string/action_menu_overflow_description</item>
<item name="minWidth">@dimen/action_button_min_width_overflow_material</item>
<item name="minHeight">@dimen/action_button_min_height_material</item>
<item name="paddingStart">@dimen/action_bar_overflow_padding_start_material</item>
diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml
index d02e156..cd3c0e3 100644
--- a/core/res/res/values/symbols.xml
+++ b/core/res/res/values/symbols.xml
@@ -1542,6 +1542,7 @@
<java-symbol type="dimen" name="docked_stack_divider_thickness" />
<java-symbol type="dimen" name="docked_stack_divider_insets" />
<java-symbol type="dimen" name="docked_stack_minimize_thickness" />
+ <java-symbol type="dimen" name="pip_minimized_visible_size" />
<java-symbol type="integer" name="config_dockedStackDividerSnapMode" />
<java-symbol type="fraction" name="docked_stack_divider_fixed_ratio" />
<java-symbol type="fraction" name="thumbnail_fullscreen_scale" />
@@ -2774,4 +2775,10 @@
<!-- Whether allow 3rd party apps on internal storage. -->
<java-symbol type="bool" name="config_allow3rdPartyAppOnInternal" />
+
+ <java-symbol type="bool" name="use_lock_pattern_drawable" />
+ <java-symbol type="drawable" name="lockscreen_notselected" />
+ <java-symbol type="drawable" name="lockscreen_selected" />
+
+ <java-symbol type="string" name="config_defaultCellBroadcastReceiverComponent" />
</resources>
diff --git a/core/res/res/values/themes_device_defaults.xml b/core/res/res/values/themes_device_defaults.xml
index a711088..6bd6e1c 100644
--- a/core/res/res/values/themes_device_defaults.xml
+++ b/core/res/res/values/themes_device_defaults.xml
@@ -742,6 +742,14 @@
<item name="colorAccent">@color/accent_device_default_light</item>
</style>
+ <!-- @hide DeviceDefault theme that should look like the Settings app. The action bar will use a
+ light background and accent color for text and icon. -->
+ <style name="Theme.DeviceDefault.Settings.LightActionBar">
+ <!-- ActionBar -->
+ <item name="actionBarTheme">@style/ThemeOverlay.DeviceDefault.ActionBar.Accent</item>
+ <item name="actionBarStyle">@style/Widget.DeviceDefault.Light.ActionBar</item>
+ </style>
+
<!-- @hide DeviceDefault theme for a window that should use Settings theme colors
but has a full dark palette. ONLY USED FOR QUICK SETTINGS THEME -->
<style name="Theme.DeviceDefault.QuickSettings" parent="Theme.Material">
@@ -809,6 +817,12 @@
<style name="ThemeOverlay.DeviceDefault" />
+ <!-- @hide Theme overlay that inherits from material actionbar, and use accent color for
+ primary text -->
+ <style name="ThemeOverlay.DeviceDefault.ActionBar.Accent" parent="ThemeOverlay.Material.ActionBar">
+ <item name="textColorPrimary">@color/btn_colored_borderless_text_material</item>
+ </style>
+
<style name="ThemeOverlay.DeviceDefault.Accent">
<item name="colorAccent">@color/accent_device_default_dark</item>
</style>
diff --git a/core/tests/coretests/Android.mk b/core/tests/coretests/Android.mk
index 4699fd5..a0a9e01 100644
--- a/core/tests/coretests/Android.mk
+++ b/core/tests/coretests/Android.mk
@@ -33,7 +33,9 @@
mockito-target-minus-junit4 \
espresso-core \
ub-uiautomator \
- platform-test-annotations
+ platform-test-annotations \
+ compatibility-device-util
+
LOCAL_JAVA_LIBRARIES := android.test.runner conscrypt telephony-common org.apache.http.legacy
LOCAL_PACKAGE_NAME := FrameworksCoreTests
diff --git a/core/tests/coretests/AndroidManifest.xml b/core/tests/coretests/AndroidManifest.xml
index ba1a55d..e3a85b5 100644
--- a/core/tests/coretests/AndroidManifest.xml
+++ b/core/tests/coretests/AndroidManifest.xml
@@ -1107,6 +1107,13 @@
</intent-filter>
</activity>
+ <activity android:name="android.app.Activity" android:label="Empty Activity">
+ <intent-filter>
+ <action android:name="android.intent.action.MAIN" />
+ <category android:name="android.intent.category.FRAMEWORK_INSTRUMENTATION_TEST" />
+ </intent-filter>
+ </activity>
+
<!-- Activity-level metadata -->
<meta-data android:name="com.android.frameworks.coretests.isApp" android:value="true" />
<meta-data android:name="com.android.frameworks.coretests.string" android:value="foo" />
@@ -1156,6 +1163,7 @@
</activity>
<activity android:name="android.app.EmptyActivity">
</activity>
+ <activity android:name="com.android.internal.app.ChooserWrapperActivity"/>
<receiver android:name="android.app.activity.AbortReceiver">
<intent-filter android:priority="1">
diff --git a/core/tests/coretests/src/android/net/NetworkScorerAppManagerTest.java b/core/tests/coretests/src/android/net/NetworkScorerAppManagerTest.java
index 5bfff26..29020ba 100644
--- a/core/tests/coretests/src/android/net/NetworkScorerAppManagerTest.java
+++ b/core/tests/coretests/src/android/net/NetworkScorerAppManagerTest.java
@@ -169,6 +169,25 @@
assertNull(activeScorer);
}
+ public void testIsCallerActiveScorer_providerNotAvailable() throws Exception {
+ ContentResolver cr = mTargetContext.getContentResolver();
+ Settings.Global.putInt(cr, Settings.Global.NETWORK_RECOMMENDATIONS_ENABLED, 1);
+
+ assertFalse(mNetworkScorerAppManager.isCallerActiveScorer(924));
+ }
+
+ public void testIsCallerActiveScorer_providerAvailable() throws Exception {
+ setNetworkRecommendationPackageNames("package1");
+ mockScoreNetworksGranted("package1");
+ mockRecommendationServiceAvailable("package1", 924 /* packageUid */);
+
+ ContentResolver cr = mTargetContext.getContentResolver();
+ Settings.Global.putInt(cr, Settings.Global.NETWORK_RECOMMENDATIONS_ENABLED, 1);
+
+ assertTrue(mNetworkScorerAppManager.isCallerActiveScorer(924));
+ assertFalse(mNetworkScorerAppManager.isCallerActiveScorer(925));
+ }
+
private void setNetworkRecommendationPackageNames(String... names) {
if (names == null) {
names = new String[0];
diff --git a/core/tests/coretests/src/android/net/ScoredNetworkTest.java b/core/tests/coretests/src/android/net/ScoredNetworkTest.java
index 9c3346e..e818c56 100644
--- a/core/tests/coretests/src/android/net/ScoredNetworkTest.java
+++ b/core/tests/coretests/src/android/net/ScoredNetworkTest.java
@@ -166,4 +166,52 @@
assertTrue(newNetwork.meteredHint);
assertNull(newNetwork.attributes);
}
+
+ @Test
+ public void calculateBadgeShouldReturnNoBadgeWhenNoAttributesBundle() {
+ ScoredNetwork network = new ScoredNetwork(KEY, CURVE);
+ assertEquals(ScoredNetwork.BADGING_NONE, network.calculateBadge(TEST_RSSI));
+ }
+
+ @Test
+ public void calculateBadgeShouldReturnNoBadgeWhenNoBadgingCurveInBundle() {
+ ScoredNetwork network = new ScoredNetwork(KEY, CURVE, false /* meteredHint */, ATTRIBUTES);
+ assertEquals(ScoredNetwork.BADGING_NONE, network.calculateBadge(TEST_RSSI));
+ }
+
+ @Test
+ public void calculateBadgeShouldReturn4kBadge() {
+ ScoredNetwork network =
+ buildScoredNetworkWithGivenBadgeForTestRssi(ScoredNetwork.BADGING_4K);
+ assertEquals(ScoredNetwork.BADGING_4K, network.calculateBadge(TEST_RSSI));
+ }
+
+ @Test
+ public void calculateBadgeShouldReturnHdBadge() {
+ ScoredNetwork network =
+ buildScoredNetworkWithGivenBadgeForTestRssi(ScoredNetwork.BADGING_HD);
+ assertEquals(ScoredNetwork.BADGING_HD, network.calculateBadge(TEST_RSSI));
+ }
+
+ @Test
+ public void calculateBadgeShouldReturnSdBadge() {
+ ScoredNetwork network =
+ buildScoredNetworkWithGivenBadgeForTestRssi(ScoredNetwork.BADGING_SD);
+ assertEquals(ScoredNetwork.BADGING_SD, network.calculateBadge(TEST_RSSI));
+ }
+
+ @Test
+ public void calculateBadgeShouldReturnNoBadge() {
+ ScoredNetwork network =
+ buildScoredNetworkWithGivenBadgeForTestRssi(ScoredNetwork.BADGING_NONE);
+ assertEquals(ScoredNetwork.BADGING_NONE, network.calculateBadge(TEST_RSSI));
+ }
+
+ private ScoredNetwork buildScoredNetworkWithGivenBadgeForTestRssi(int badge) {
+ RssiCurve badgingCurve =
+ new RssiCurve(RSSI_START, 10, new byte[] {0, 0, 0, 0, 0, 0, (byte) badge});
+ Bundle attr = new Bundle();
+ attr.putParcelable(ScoredNetwork.ATTRIBUTES_KEY_BADGING_CURVE, badgingCurve);
+ return new ScoredNetwork(KEY, CURVE, false /* meteredHint */, attr);
+ }
}
diff --git a/core/tests/coretests/src/android/view/RenderNodeAnimatorTest.java b/core/tests/coretests/src/android/view/RenderNodeAnimatorTest.java
new file mode 100644
index 0000000..b52d98c
--- /dev/null
+++ b/core/tests/coretests/src/android/view/RenderNodeAnimatorTest.java
@@ -0,0 +1,59 @@
+/*
+ * 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 android.view;
+
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertNull;
+
+import android.app.Activity;
+import android.content.Context;
+import android.support.test.InstrumentationRegistry;
+import android.support.test.annotation.UiThreadTest;
+import android.support.test.filters.MediumTest;
+import android.support.test.rule.ActivityTestRule;
+
+import org.junit.Rule;
+import org.junit.Test;
+
+@MediumTest
+public class RenderNodeAnimatorTest {
+ @Rule
+ public ActivityTestRule<Activity> mActivityRule = new ActivityTestRule<>(Activity.class);
+
+ private Context getContext() {
+ return InstrumentationRegistry.getTargetContext();
+ }
+
+ private Activity getActivity() {
+ return mActivityRule.getActivity();
+ }
+
+ @UiThreadTest
+ @Test
+ public void testAlphaTransformationInfo() throws Throwable {
+ View view = new View(getContext());
+
+ // attach the view, since otherwise the RenderNodeAnimator won't accept view as target
+ getActivity().setContentView(view);
+
+ RenderNodeAnimator anim = new RenderNodeAnimator(RenderNodeAnimator.ALPHA, 0.5f);
+ anim.setTarget(view);
+ assertNull(view.mTransformationInfo);
+ anim.start(); // should initialize mTransformationInfo
+ assertNotNull(view.mTransformationInfo);
+ }
+}
diff --git a/core/tests/coretests/src/android/view/ViewInvalidateTest.java b/core/tests/coretests/src/android/view/ViewInvalidateTest.java
new file mode 100644
index 0000000..4db70ec
--- /dev/null
+++ b/core/tests/coretests/src/android/view/ViewInvalidateTest.java
@@ -0,0 +1,265 @@
+/*
+ * Copyright (C) 2016 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 android.view;
+
+import static junit.framework.Assert.assertFalse;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
+
+import android.app.Activity;
+import android.content.Context;
+import android.graphics.Rect;
+import android.support.test.InstrumentationRegistry;
+import android.support.test.annotation.UiThreadTest;
+import android.support.test.filters.LargeTest;
+import android.support.test.rule.ActivityTestRule;
+import android.support.test.runner.AndroidJUnit4;
+import android.widget.FrameLayout;
+
+import com.android.compatibility.common.util.WidgetTestUtils;
+
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+/**
+ * Test of invalidates, drawing, and the flags that support them
+ */
+@LargeTest
+@RunWith(AndroidJUnit4.class)
+public class ViewInvalidateTest {
+ @Rule
+ public ActivityTestRule<Activity> mActivityRule = new ActivityTestRule<>(Activity.class);
+
+ private static final int INVAL_TEST_FLAG_MASK = View.PFLAG_DIRTY
+ | View.PFLAG_DIRTY_OPAQUE
+ | View.PFLAG_DRAWN
+ | View.PFLAG_DRAWING_CACHE_VALID
+ | View.PFLAG_INVALIDATED
+ | View.PFLAG_DRAW_ANIMATION;
+
+ @Before
+ public void setup() throws Throwable {
+ // separate runnable to initialize, so ref is safe to pass to runOnMainAndDrawSync
+ mActivityRule.runOnUiThread(() -> {
+ mParent = new FrameLayout(getContext());
+ mChild = new View(getContext());
+ });
+
+ // attached view is drawn once
+ WidgetTestUtils.runOnMainAndDrawSync(mActivityRule, mParent, () -> {
+ mParent.addView(mChild);
+ getActivity().setContentView(mParent);
+
+ // 'invalidated', but not yet drawn
+ validateInvalFlags(mChild, View.PFLAG_INVALIDATED);
+ });
+ }
+
+ @After
+ public void teardown() {
+ // ensure we don't share views between tests
+ mParent = null;
+ mChild = null;
+ }
+
+ Context getContext() {
+ return InstrumentationRegistry.getTargetContext();
+ }
+
+ Activity getActivity() {
+ return mActivityRule.getActivity();
+ }
+
+ private ViewGroup mParent;
+ private View mChild;
+
+ private static void validateInvalFlags(View view, int... expectedFlagArray) {
+ int expectedFlags = 0;
+ for (int expectedFlag : expectedFlagArray) {
+ expectedFlags |= expectedFlag;
+ }
+
+ final int observedFlags = view.mPrivateFlags & INVAL_TEST_FLAG_MASK;
+ assertEquals(String.format("expect %x, observed %x", expectedFlags, observedFlags),
+ expectedFlags, observedFlags);
+ }
+
+ private static ViewRootImpl getViewRoot(View view) {
+ ViewParent parent = view.getParent();
+ while (parent != null) {
+ if (parent instanceof ViewRootImpl) {
+ return (ViewRootImpl) parent;
+ }
+ parent = parent.getParent();
+ }
+ return null;
+ }
+
+ @UiThreadTest
+ @Test
+ public void testInvalidate_behavior() throws Throwable {
+ validateInvalFlags(mChild,
+ View.PFLAG_DRAWING_CACHE_VALID,
+ View.PFLAG_DRAWN);
+ validateInvalFlags(mParent,
+ View.PFLAG_DRAWING_CACHE_VALID,
+ View.PFLAG_DRAWN);
+ assertFalse(getViewRoot(mParent).mTraversalScheduled);
+
+ mChild.invalidate();
+
+ // no longer drawn, is now invalidated
+ validateInvalFlags(mChild,
+ View.PFLAG_DIRTY,
+ View.PFLAG_INVALIDATED);
+
+ // parent drawing cache no longer valid, marked dirty
+ validateInvalFlags(mParent,
+ View.PFLAG_DRAWN,
+ View.PFLAG_DIRTY);
+ assertTrue(getViewRoot(mParent).mTraversalScheduled);
+ }
+
+ @UiThreadTest
+ @Test
+ public void testInvalidate_false() {
+ // Invalidate makes it invalid
+ validateInvalFlags(mChild,
+ View.PFLAG_DRAWING_CACHE_VALID,
+ View.PFLAG_DRAWN);
+
+ mChild.invalidate(/*don't invalidate cache*/ false);
+
+ // drawn is cleared, dirty set, nothing else changed
+ validateInvalFlags(mChild,
+ View.PFLAG_DRAWING_CACHE_VALID,
+ View.PFLAG_DIRTY);
+ }
+
+ @Test
+ public void testInvalidate_simple() throws Throwable {
+ // simple invalidate, which marks the view invalid
+ WidgetTestUtils.runOnMainAndDrawSync(mActivityRule, mParent, () -> {
+ validateInvalFlags(mChild,
+ View.PFLAG_DRAWING_CACHE_VALID,
+ View.PFLAG_DRAWN);
+
+ mChild.invalidate();
+
+ validateInvalFlags(mChild,
+ View.PFLAG_DIRTY,
+ View.PFLAG_INVALIDATED);
+ });
+
+ // after draw pass, view has drawn, no longer invalid
+ mActivityRule.runOnUiThread(() -> {
+ validateInvalFlags(mChild,
+ View.PFLAG_DRAWING_CACHE_VALID,
+ View.PFLAG_DRAWN);
+ });
+ }
+
+ @UiThreadTest
+ @Test
+ public void testInvalidate_manualUpdateDisplayList() {
+ // Invalidate makes it invalid
+ validateInvalFlags(mChild,
+ View.PFLAG_DRAWING_CACHE_VALID,
+ View.PFLAG_DRAWN);
+
+ mChild.invalidate();
+ validateInvalFlags(mChild,
+ View.PFLAG_DIRTY,
+ View.PFLAG_INVALIDATED);
+
+ // updateDisplayListIfDirty makes it valid again, but invalidate still set,
+ // since it's cleared by View#draw(canvas, parent, drawtime)
+ mChild.updateDisplayListIfDirty();
+ validateInvalFlags(mChild,
+ View.PFLAG_DRAWING_CACHE_VALID,
+ View.PFLAG_DRAWN,
+ View.PFLAG_INVALIDATED);
+ }
+
+ @UiThreadTest
+ @Test
+ public void testInvalidateChild_simple() {
+ validateInvalFlags(mParent,
+ View.PFLAG_DRAWING_CACHE_VALID,
+ View.PFLAG_DRAWN);
+ assertFalse(getViewRoot(mParent).mTraversalScheduled);
+
+ mParent.invalidateChild(mChild, new Rect(0, 0, 1, 1));
+
+ validateInvalFlags(mParent,
+ View.PFLAG_DIRTY,
+ View.PFLAG_DRAWN);
+ assertTrue(getViewRoot(mParent).mTraversalScheduled);
+ }
+
+ @Test
+ public void testInvalidateChild_childHardwareLayer() throws Throwable {
+ WidgetTestUtils.runOnMainAndDrawSync(mActivityRule, mParent, () -> {
+ // do in runnable, so tree won't be dirty
+ mChild.setLayerType(View.LAYER_TYPE_HARDWARE, null);
+ });
+
+ mActivityRule.runOnUiThread(() -> {
+ validateInvalFlags(mParent,
+ View.PFLAG_DRAWING_CACHE_VALID,
+ View.PFLAG_DRAWN);
+
+ mParent.invalidateChild(mChild, new Rect(0, 0, 1, 1));
+
+ validateInvalFlags(mParent,
+ View.PFLAG_DIRTY,
+ View.PFLAG_DRAWN,
+ View.PFLAG_INVALIDATED);
+ });
+ }
+
+ @UiThreadTest
+ @Test
+ public void testInvalidateChild_legacyAnimation() throws Throwable {
+ mChild.mPrivateFlags |= View.PFLAG_DRAW_ANIMATION;
+
+ validateInvalFlags(mChild,
+ View.PFLAG_DRAW_ANIMATION,
+ View.PFLAG_DRAWING_CACHE_VALID,
+ View.PFLAG_DRAWN);
+ validateInvalFlags(mParent,
+ View.PFLAG_DRAWING_CACHE_VALID,
+ View.PFLAG_DRAWN);
+ assertFalse(getViewRoot(mParent).mIsAnimating);
+
+ mParent.invalidateChild(mChild, new Rect(0, 0, 1, 1));
+
+ validateInvalFlags(mChild,
+ View.PFLAG_DRAW_ANIMATION,
+ View.PFLAG_DRAWING_CACHE_VALID,
+ View.PFLAG_DRAWN);
+ validateInvalFlags(mParent,
+ View.PFLAG_DIRTY,
+ View.PFLAG_DRAW_ANIMATION, // carried up to parent
+ View.PFLAG_DRAWN);
+ assertTrue(getViewRoot(mParent).mIsAnimating);
+ }
+}
diff --git a/core/tests/coretests/src/com/android/internal/app/ChooserActivityTest.java b/core/tests/coretests/src/com/android/internal/app/ChooserActivityTest.java
new file mode 100644
index 0000000..8a7b881
--- /dev/null
+++ b/core/tests/coretests/src/com/android/internal/app/ChooserActivityTest.java
@@ -0,0 +1,178 @@
+/*
+ * Copyright (C) 2016 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 com.android.internal.R;
+import com.android.internal.app.ResolverActivity.ResolvedComponentInfo;
+
+import org.junit.Before;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mockito;
+
+import android.content.Intent;
+import android.content.pm.ResolveInfo;
+import android.support.test.InstrumentationRegistry;
+import android.support.test.rule.ActivityTestRule;
+import android.support.test.runner.AndroidJUnit4;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import static android.support.test.espresso.Espresso.onView;
+import static android.support.test.espresso.action.ViewActions.click;
+import static android.support.test.espresso.assertion.ViewAssertions.matches;
+import static android.support.test.espresso.matcher.ViewMatchers.isDisplayed;
+import static android.support.test.espresso.matcher.ViewMatchers.withId;
+import static android.support.test.espresso.matcher.ViewMatchers.withText;
+import static com.android.internal.app.ChooserWrapperActivity.sOverrides;
+import static org.hamcrest.CoreMatchers.is;
+import static org.hamcrest.CoreMatchers.not;
+import static org.hamcrest.MatcherAssert.assertThat;
+import static org.mockito.Mockito.when;
+
+/**
+ * Chooser activity instrumentation tests
+ */
+@RunWith(AndroidJUnit4.class)
+public class ChooserActivityTest {
+ @Rule
+ public ActivityTestRule<ChooserWrapperActivity> mActivityRule =
+ new ActivityTestRule<>(ChooserWrapperActivity.class, false,
+ false);
+
+ @Before
+ public void cleanOverrideData() {
+ sOverrides.reset();
+ }
+
+ @Test
+ public void customTitle() throws InterruptedException {
+ Intent sendIntent = createSendImageIntent();
+ when(sOverrides.resolverListController.getResolversForIntent(Mockito.anyBoolean(),
+ Mockito.anyBoolean(),
+ Mockito.isA(List.class))).thenReturn(null);
+ mActivityRule.launchActivity(Intent.createChooser(sendIntent, "chooser test"));
+ waitForIdle();
+ onView(withId(R.id.title)).check(matches(withText("chooser test")));
+ }
+
+ @Test
+ public void emptyTitle() throws InterruptedException {
+ sOverrides.isVoiceInteraction = false;
+ Intent sendIntent = createSendImageIntent();
+ when(sOverrides.resolverListController.getResolversForIntent(Mockito.anyBoolean(),
+ Mockito.anyBoolean(),
+ Mockito.isA(List.class))).thenReturn(null);
+ mActivityRule.launchActivity(Intent.createChooser(sendIntent, null));
+ waitForIdle();
+ onView(withId(R.id.title))
+ .check(matches(withText(R.string.whichSendApplication)));
+ }
+
+ @Test
+ public void twoOptionsAndUserSelectsOne() throws InterruptedException {
+ Intent sendIntent = createSendImageIntent();
+ List<ResolvedComponentInfo> resolvedComponentInfos = createResolvedComponentsForTest(2);
+
+ when(sOverrides.resolverListController.getResolversForIntent(Mockito.anyBoolean(),
+ Mockito.anyBoolean(),
+ Mockito.isA(List.class))).thenReturn(resolvedComponentInfos);
+
+ final ChooserWrapperActivity activity = mActivityRule
+ .launchActivity(Intent.createChooser(sendIntent, null));
+ waitForIdle();
+
+ assertThat(activity.getAdapter().getCount(), is(2));
+ onView(withId(R.id.profile_button)).check(matches(not(isDisplayed())));
+
+ ResolveInfo[] chosen = new ResolveInfo[1];
+ sOverrides.onSafelyStartCallback = targetInfo -> {
+ chosen[0] = targetInfo.getResolveInfo();
+ return true;
+ };
+
+ ResolveInfo toChoose = resolvedComponentInfos.get(0).getResolveInfoAt(0);
+ onView(withText(toChoose.activityInfo.name))
+ .perform(click());
+ waitForIdle();
+ assertThat(chosen[0], is(toChoose));
+ }
+
+ @Test
+ public void noResultsFromPackageManager() {
+ when(sOverrides.resolverListController.getResolversForIntent(Mockito.anyBoolean(),
+ Mockito.anyBoolean(),
+ Mockito.isA(List.class))).thenReturn(null);
+ Intent sendIntent = createSendImageIntent();
+ final ChooserWrapperActivity activity = mActivityRule
+ .launchActivity(Intent.createChooser(sendIntent, null));
+ waitForIdle();
+ assertThat(activity.isFinishing(), is(false));
+
+ onView(withId(R.id.empty)).check(matches(isDisplayed()));
+ onView(withId(R.id.resolver_list)).check(matches(not(isDisplayed())));
+ InstrumentationRegistry.getInstrumentation().runOnMainSync(
+ () -> activity.getAdapter().handlePackagesChanged()
+ );
+ // backward compatibility. looks like we finish when data is empty after package change
+ assertThat(activity.isFinishing(), is(true));
+ }
+
+ @Test
+ public void autoLaunchSingleResult() throws InterruptedException {
+ ResolveInfo[] chosen = new ResolveInfo[1];
+ sOverrides.onSafelyStartCallback = targetInfo -> {
+ chosen[0] = targetInfo.getResolveInfo();
+ return true;
+ };
+
+ List<ResolvedComponentInfo> resolvedComponentInfos = createResolvedComponentsForTest(1);
+ when(sOverrides.resolverListController.getResolversForIntent(Mockito.anyBoolean(),
+ Mockito.anyBoolean(),
+ Mockito.isA(List.class))).thenReturn(resolvedComponentInfos);
+
+ Intent sendIntent = createSendImageIntent();
+ final ChooserWrapperActivity activity = mActivityRule
+ .launchActivity(Intent.createChooser(sendIntent, null));
+ waitForIdle();
+
+ assertThat(chosen[0], is(resolvedComponentInfos.get(0).getResolveInfoAt(0)));
+ assertThat(activity.isFinishing(), is(true));
+ }
+
+ private Intent createSendImageIntent() {
+ Intent sendIntent = new Intent();
+ sendIntent.setAction(Intent.ACTION_SEND);
+ sendIntent.putExtra(Intent.EXTRA_TEXT, "testing intent sending");
+ sendIntent.setType("image/jpeg");
+ return sendIntent;
+ }
+
+ private List<ResolvedComponentInfo> createResolvedComponentsForTest(int numberOfResults) {
+ List<ResolvedComponentInfo> infoList = new ArrayList<>(numberOfResults);
+ for (int i = 0; i < numberOfResults; i++) {
+ infoList.add(ChooserDataProvider.createResolvedComponentInfo(i));
+ }
+ return infoList;
+ }
+
+ private void waitForIdle() {
+ InstrumentationRegistry.getInstrumentation().waitForIdleSync();
+ }
+}
\ No newline at end of file
diff --git a/core/tests/coretests/src/com/android/internal/app/ChooserDataProvider.java b/core/tests/coretests/src/com/android/internal/app/ChooserDataProvider.java
new file mode 100644
index 0000000..f6f63f1
--- /dev/null
+++ b/core/tests/coretests/src/com/android/internal/app/ChooserDataProvider.java
@@ -0,0 +1,75 @@
+/*
+ * Copyright (C) 2008 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.ComponentName;
+import android.content.Intent;
+import android.content.pm.ActivityInfo;
+import android.content.pm.ApplicationInfo;
+import android.content.pm.ResolveInfo;
+import android.os.UserHandle;
+import android.service.chooser.ChooserTarget;
+
+import java.util.HashMap;
+import java.util.Map;
+import java.util.concurrent.atomic.AtomicInteger;
+
+/**
+ * Utility class used by chooser tests to create mock data
+ */
+class ChooserDataProvider {
+
+ static ResolverActivity.ResolvedComponentInfo createResolvedComponentInfo(int i) {
+ return new ResolverActivity.ResolvedComponentInfo(createComponentName(i),
+ createResolverIntent(i), createResolveInfo(i));
+ }
+
+ static ComponentName createComponentName(int i) {
+ final String name = "component" + i;
+ return new ComponentName("foo.bar." + name, name);
+ }
+
+ static ResolveInfo createResolveInfo(int i) {
+ final ResolveInfo resolveInfo = new ResolveInfo();
+ resolveInfo.activityInfo = createActivityInfo(i);
+ resolveInfo.targetUserId = UserHandle.USER_CURRENT;
+ return resolveInfo;
+ }
+
+ static ActivityInfo createActivityInfo(int i) {
+ ActivityInfo ai = new ActivityInfo();
+ ai.name = "activity_name" + i;
+ ai.packageName = "foo_bar" + i;
+ ai.enabled = true;
+ ai.exported = true;
+ ai.permission = null;
+ ai.applicationInfo = createApplicationInfo();
+ return ai;
+ }
+
+ static ApplicationInfo createApplicationInfo() {
+ ApplicationInfo ai = new ApplicationInfo();
+ ai.name = "app_name";
+ ai.packageName = "foo.bar";
+ ai.enabled = true;
+ return ai;
+ }
+
+ static Intent createResolverIntent(int i) {
+ return new Intent("intentAction" + i);
+ }
+}
\ No newline at end of file
diff --git a/core/tests/coretests/src/com/android/internal/app/ChooserWrapperActivity.java b/core/tests/coretests/src/com/android/internal/app/ChooserWrapperActivity.java
new file mode 100644
index 0000000..66fb451
--- /dev/null
+++ b/core/tests/coretests/src/com/android/internal/app/ChooserWrapperActivity.java
@@ -0,0 +1,85 @@
+/*
+ * Copyright (C) 2008 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.pm.PackageManager;
+
+import java.util.function.Function;
+
+import static org.mockito.Mockito.mock;
+
+
+/**
+ * Simple wrapper around chooser activity to be able to initiate it under test
+ */
+public class ChooserWrapperActivity extends ChooserActivity {
+ static final OverrideData sOverrides = new OverrideData();
+
+ ResolveListAdapter getAdapter() {
+ return mAdapter;
+ }
+
+ @Override
+ public boolean isVoiceInteraction() {
+ if (sOverrides.isVoiceInteraction != null) {
+ return sOverrides.isVoiceInteraction;
+ }
+ return super.isVoiceInteraction();
+ }
+
+ @Override
+ public void safelyStartActivity(TargetInfo cti) {
+ if (sOverrides.onSafelyStartCallback != null &&
+ sOverrides.onSafelyStartCallback.apply(cti)) {
+ return;
+ }
+ super.safelyStartActivity(cti);
+ }
+
+ @Override
+ protected ResolverListController createListController() {
+ return sOverrides.resolverListController;
+ }
+
+ @Override
+ public PackageManager getPackageManager() {
+ if (sOverrides.createPackageManager != null) {
+ return sOverrides.createPackageManager.apply(super.getPackageManager());
+ }
+ return super.getPackageManager();
+ }
+
+ /**
+ * We cannot directly mock the activity created since instrumentation creates it.
+ * <p>
+ * Instead, we use static instances of this object to modify behavior.
+ */
+ static class OverrideData {
+ @SuppressWarnings("Since15")
+ public Function<PackageManager, PackageManager> createPackageManager;
+ public Function<TargetInfo, Boolean> onSafelyStartCallback;
+ public ResolverListController resolverListController;
+ public Boolean isVoiceInteraction;
+
+ public void reset() {
+ onSafelyStartCallback = null;
+ isVoiceInteraction = null;
+ createPackageManager = null;
+ resolverListController = mock(ResolverListController.class);
+ }
+ }
+}
\ No newline at end of file
diff --git a/core/tests/coretests/src/com/android/internal/logging/LogBuilderTest.java b/core/tests/coretests/src/com/android/internal/logging/LogBuilderTest.java
new file mode 100644
index 0000000..e7d23a8
--- /dev/null
+++ b/core/tests/coretests/src/com/android/internal/logging/LogBuilderTest.java
@@ -0,0 +1,43 @@
+package com.android.internal.logging;
+
+import junit.framework.TestCase;
+
+public class LogBuilderTest extends TestCase {
+
+ public void testSerialize() {
+ LogBuilder builder = new LogBuilder();
+ builder.addTaggedData(1, "one");
+ builder.addTaggedData(2, "two");
+ Object[] out = builder.serialize();
+ assertEquals(1, out[0]);
+ assertEquals("one", out[1]);
+ assertEquals(2, out[2]);
+ assertEquals("two", out[3]);
+ }
+
+ public void testInvalidInputThrows() {
+ LogBuilder builder = new LogBuilder();
+ boolean threw = false;
+ try {
+ builder.addTaggedData(0, new Object());
+ } catch (IllegalArgumentException e) {
+ threw = true;
+ }
+ assertTrue(threw);
+ assertEquals(0, builder.serialize().length);
+ }
+
+ public void testValidInputTypes() {
+ LogBuilder builder = new LogBuilder();
+ builder.addTaggedData(1, "onetwothree");
+ builder.addTaggedData(2, 123);
+ builder.addTaggedData(3, 123L);
+ builder.addTaggedData(4, 123.0F);
+ Object[] out = builder.serialize();
+ assertEquals("onetwothree", out[1]);
+ assertEquals(123, out[3]);
+ assertEquals(123L, out[5]);
+ assertEquals(123.0F, out[7]);
+ }
+
+}
diff --git a/core/tests/coretests/src/com/android/internal/os/BatteryStatsSensorTest.java b/core/tests/coretests/src/com/android/internal/os/BatteryStatsSensorTest.java
new file mode 100644
index 0000000..0bdf7ca
--- /dev/null
+++ b/core/tests/coretests/src/com/android/internal/os/BatteryStatsSensorTest.java
@@ -0,0 +1,66 @@
+/*
+ * Copyright (C) 2016 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.os;
+
+import android.app.ActivityManager;
+import android.os.BatteryStats;
+import android.os.Debug;
+import android.support.test.filters.SmallTest;
+import android.util.Log;
+
+import junit.framework.TestCase;
+
+/**
+ * Test BatteryStatsImpl Sensor Timers.
+ */
+public class BatteryStatsSensorTest extends TestCase {
+
+ private static final int UID = 10500;
+ private static final int SENSOR_ID = -10000;
+
+ @SmallTest
+ public void testSensorStartStop() throws Exception {
+ final MockClocks clocks = new MockClocks();
+ MockBatteryStatsImpl bi = new MockBatteryStatsImpl(clocks);
+ bi.mForceOnBattery = true;
+ clocks.realtime = 100;
+ clocks.uptime = 100;
+ bi.getOnBatteryTimeBase().setRunning(true, 100, 100);
+ bi.noteUidProcessStateLocked(UID, ActivityManager.PROCESS_STATE_CACHED_EMPTY);
+ bi.noteUidProcessStateLocked(UID, ActivityManager.PROCESS_STATE_IMPORTANT_FOREGROUND);
+ bi.noteStartSensorLocked(UID, SENSOR_ID);
+ clocks.realtime = 200;
+ clocks.uptime = 200;
+ bi.noteStopSensorLocked(UID, SENSOR_ID);
+
+ bi.noteUidProcessStateLocked(UID, ActivityManager.PROCESS_STATE_RECEIVER);
+ bi.noteStartSensorLocked(UID, SENSOR_ID);
+ clocks.realtime = 400;
+ clocks.uptime = 400;
+ bi.noteStopSensorLocked(UID, SENSOR_ID);
+
+ BatteryStats.Timer sensorTimer = bi.getUidStats().get(UID).getSensorStats()
+ .get(SENSOR_ID).getSensorTime();
+ BatteryStats.Counter sensorBgCounter = bi.getUidStats().get(UID).getSensorStats()
+ .get(SENSOR_ID).getSensorBgCount();
+
+ assertEquals(2, sensorTimer.getCountLocked(BatteryStats.STATS_SINCE_CHARGED));
+ assertEquals(300000,
+ sensorTimer.getTotalTimeLocked(clocks.realtime, BatteryStats.STATS_SINCE_CHARGED));
+
+ assertEquals(1, sensorBgCounter.getCountLocked(BatteryStats.STATS_SINCE_CHARGED));
+ }
+}
diff --git a/core/tests/coretests/src/com/android/internal/os/BatteryStatsTests.java b/core/tests/coretests/src/com/android/internal/os/BatteryStatsTests.java
index 9518219..c7cd0ee 100644
--- a/core/tests/coretests/src/com/android/internal/os/BatteryStatsTests.java
+++ b/core/tests/coretests/src/com/android/internal/os/BatteryStatsTests.java
@@ -11,6 +11,7 @@
BatteryStatsTimeBaseTest.class,
BatteryStatsTimerTest.class,
BatteryStatsUidTest.class,
+ BatteryStatsSensorTest.class,
})
public class BatteryStatsTests {
}
diff --git a/core/tests/coretests/src/com/android/internal/os/MockBatteryStatsImpl.java b/core/tests/coretests/src/com/android/internal/os/MockBatteryStatsImpl.java
index 3924489..1054106 100644
--- a/core/tests/coretests/src/com/android/internal/os/MockBatteryStatsImpl.java
+++ b/core/tests/coretests/src/com/android/internal/os/MockBatteryStatsImpl.java
@@ -16,36 +16,28 @@
package com.android.internal.os;
-import java.io.PrintWriter;
-import java.io.StringWriter;
-import java.util.ArrayList;
-
-import android.os.BatteryStats;
-import android.os.Parcel;
-import android.test.suitebuilder.annotation.SmallTest;
-import android.util.Log;
-
-import junit.framework.Assert;
-import junit.framework.TestCase;
-
-import com.android.internal.os.BatteryStatsImpl;
-
-import org.mockito.Mockito;
-
/**
* Mocks a BatteryStatsImpl object.
*/
public class MockBatteryStatsImpl extends BatteryStatsImpl {
public BatteryStatsImpl.Clocks clocks;
+ public boolean mForceOnBattery;
+
+ MockBatteryStatsImpl(Clocks clocks) {
+ super(clocks);
+ this.clocks = mClocks;
+ }
MockBatteryStatsImpl() {
- super(new MockClocks());
- this.clocks = mClocks;
+ this(new MockClocks());
}
public TimeBase getOnBatteryTimeBase() {
return mOnBatteryTimeBase;
}
+ public boolean isOnBattery() {
+ return mForceOnBattery ? true : super.isOnBattery();
+ }
}
diff --git a/core/tests/hosttests/test-apps/MultiDexLegacyAndException/Android.mk b/core/tests/hosttests/test-apps/MultiDexLegacyAndException/Android.mk
index 9b2b9f1..836ede6 100644
--- a/core/tests/hosttests/test-apps/MultiDexLegacyAndException/Android.mk
+++ b/core/tests/hosttests/test-apps/MultiDexLegacyAndException/Android.mk
@@ -23,7 +23,7 @@
LOCAL_SRC_FILES := $(call all-java-files-under, src)
-LOCAL_SDK_VERSION := current
+LOCAL_SDK_VERSION := 8
LOCAL_PACKAGE_NAME := MultiDexLegacyAndException
diff --git a/core/tests/hosttests/test-apps/MultiDexLegacyTestApp/Android.mk b/core/tests/hosttests/test-apps/MultiDexLegacyTestApp/Android.mk
index 874263f..2915914 100644
--- a/core/tests/hosttests/test-apps/MultiDexLegacyTestApp/Android.mk
+++ b/core/tests/hosttests/test-apps/MultiDexLegacyTestApp/Android.mk
@@ -23,7 +23,7 @@
LOCAL_SRC_FILES := $(call all-java-files-under, src)
-LOCAL_SDK_VERSION := current
+LOCAL_SDK_VERSION := 8
LOCAL_PACKAGE_NAME := MultiDexLegacyTestApp
@@ -45,7 +45,7 @@
LOCAL_SRC_FILES := $(call all-java-files-under, src)
-LOCAL_SDK_VERSION := current
+LOCAL_SDK_VERSION := 8
LOCAL_PACKAGE_NAME := MultiDexLegacyTestApp2
diff --git a/docs/html/google/play/billing/billing_admin.jd b/docs/html/google/play/billing/billing_admin.jd
index 9936489..1dc58e2 100644
--- a/docs/html/google/play/billing/billing_admin.jd
+++ b/docs/html/google/play/billing/billing_admin.jd
@@ -125,7 +125,10 @@
</dd>
</dl>
</li>
- <li><p>Enter additional information about the item, then click <strong>Save</strong>.</p>
+ <li><p>Enter additional information about the item. If you're adding a
+ subscription, also include
+ <a href="#billing-form-add-subscription">subscription-specific details</a>.
+ After you've provided this information, click <strong>Save</strong>.</p>
<dl>
<dt>Publishing State</dt>
<dd>
@@ -185,6 +188,73 @@
</figcaption>
</figure>
+<h4 id="billing-form-add-subscription">
+ Adding subscription details
+</h4>
+
+<p>
+ When you add a subscription to a product list, you must define its billing
+ period. All other settings related to subscriptions are optional. The
+ following list shows each property that you can set:
+</p>
+
+<dl>
+ <dt>Billing period</dt>
+ <dd>
+ <p>
+ Sets the frequency at which a user is charged while their subscription
+ is active.
+ </p>
+
+ <p>
+ If the billing period for the new subscription is Seasonal, you must
+ specify when the season starts and ends using the <strong>Start
+ date</strong> and <strong>End date</strong> options. The subscription is
+ active only between these two dates.
+ </p>
+
+ <p>
+ To allow users to activate a seasonal subscription for a discounted price
+ after the season begins, you can provide prorated pricing by selecting
+ <strong>Add Prorated Price</strong>. In the text boxes that appear after
+ you select this option, specify a discounted price for your subscription,
+ as well as the first date during the season when users can activate the
+ subscription for the discounted price. You can set multiple prorated
+ prices for a single subscription, with each price point taking effect on
+ a different start date.
+ </p>
+
+ <p class="note">
+ <strong>Note:</strong> After you activate a subscription, you cannot
+ change the subscription's billing period. For a seasonal subscription,
+ this restriction means that you also cannot change the season's start and
+ end dates. However, you can still add, change, and remove the prorated
+ prices that you've associated with a seasonal subscription.
+ </p>
+ </dd>
+
+ <dt>Free trial period</dt>
+ <dd>
+ Sets the number of days that users can access the subscription for free
+ after they first activate it. The trial period must be at least 7 days.
+ </dd>
+
+ <dt>Grace period</dt>
+ <dd>
+ Determines the amount of time that the user can continue accessing the
+ subscription after their payment is declined. If the user doesn't fix their
+ payment issue after the grace period has ended, their access to the
+ subscription is revoked.
+ </dd>
+</dl>
+
+<p>
+ To learn more about how you can manage subscriptions using the In-app Billing
+ service, see the
+ <a href="/google/play/billing/billing_subscriptions.html">In-app
+ Subscriptions</a> guide.
+</p>
+
<h3 id="billing-bulk-add">Adding a batch of items to a product list</h3>
<p>To add a batch of items to a product list using a CSV file, you first need to
diff --git a/docs/html/google/play/billing/billing_integrate.jd b/docs/html/google/play/billing/billing_integrate.jd
index 506a440..d2839bd 100755
--- a/docs/html/google/play/billing/billing_integrate.jd
+++ b/docs/html/google/play/billing/billing_integrate.jd
@@ -310,7 +310,7 @@
skuList.add("premiumUpgrade");
skuList.add("gas");
Bundle querySkus = new Bundle();
-querySkus.putStringArrayList(“ITEM_ID_LIST”, skuList);
+querySkus.putStringArrayList("ITEM_ID_LIST", skuList);
</pre>
<p>
diff --git a/docs/html/google/play/billing/billing_testing.jd b/docs/html/google/play/billing/billing_testing.jd
index 44b7ad3..22480a2 100644
--- a/docs/html/google/play/billing/billing_testing.jd
+++ b/docs/html/google/play/billing/billing_testing.jd
@@ -199,6 +199,15 @@
with a reserved product ID. Figure 1 shows the checkout flow for the reserved item that has the
product ID android.test.purchased.</p>
+<p class="note">
+ <strong>Note:</strong> If you're testing subscription purchases, you must use
+ the product ID of an actual subscription, not a reserved product ID. To verify
+ that Google Play is processing the test subscription purchases correctly, you
+ should
+ <a href="/google/play/billing/billing/billing_admin.html#billing-testing-setup">set
+ up test accounts</a> for your app.
+</p>
+
<img src="{@docRoot}images/billing_test_flow.png" height="381" id="figure1" />
<p class="img-caption">
<strong>Figure 1.</strong>Purchase flow for the special reserved item android.test.purchased.
diff --git a/graphics/java/android/graphics/Bitmap.java b/graphics/java/android/graphics/Bitmap.java
index b6db327..ba7f05d 100644
--- a/graphics/java/android/graphics/Bitmap.java
+++ b/graphics/java/android/graphics/Bitmap.java
@@ -372,6 +372,16 @@
}
/**
+ * This is called by methods that want to throw an exception if the bitmap
+ * is {@link Config#HARDWARE}.
+ */
+ private void checkHardware(String errorMessage) {
+ if (getConfig() == Config.HARDWARE) {
+ throw new IllegalStateException(errorMessage);
+ }
+ }
+
+ /**
* Common code for checking that x and y are >= 0
*
* @param x x coordinate to ensure is >= 0
@@ -512,8 +522,11 @@
* <p>After this method returns, the current position of the buffer is
* updated: the position is incremented by the number of elements written
* in the buffer.</p>
+ * @throws IllegalStateException if the bitmap's config is {@link Config#HARDWARE}
*/
public void copyPixelsToBuffer(Buffer dst) {
+ checkHardware("unable to copyPixelsToBuffer, "
+ + "pixel access is not supported on Config#HARDWARE bitmaps");
int elements = dst.remaining();
int shift;
if (dst instanceof ByteBuffer) {
@@ -550,9 +563,11 @@
* updated: the position is incremented by the number of elements read from
* the buffer. If you need to read the bitmap from the buffer again you must
* first rewind the buffer.</p>
+ * @throws IllegalStateException if the bitmap's config is {@link Config#HARDWARE}
*/
public void copyPixelsFromBuffer(Buffer src) {
checkRecycled("copyPixelsFromBuffer called on recycled bitmap");
+ checkHardware("unable to copyPixelsFromBuffer, Config#HARDWARE bitmaps are immutable");
int elements = src.remaining();
int shift;
@@ -640,6 +655,17 @@
}
/**
+ * Create hardware bitmap backed GraphicBuffer.
+ *
+ * @return Bitmap or null if this GraphicBuffer has unsupported PixelFormat.
+ * currently PIXEL_FORMAT_RGBA_8888 is the only supported format
+ * @hide
+ */
+ public static Bitmap createHardwareBitmap(GraphicBuffer graphicBuffer) {
+ return nativeCreateHardwareBitmap(graphicBuffer);
+ }
+
+ /**
* Creates a new bitmap, scaled from an existing bitmap, when possible. If the
* specified width and height are the same as the current width and height of
* the source bitmap, the source bitmap is returned and no new bitmap is
@@ -753,6 +779,11 @@
return source;
}
+ boolean isHardware = source.getConfig() == Config.HARDWARE;
+ if (isHardware) {
+ source = nativeCopyPreserveInternalConfig(source.mNativePtr);
+ }
+
int neww = width;
int newh = height;
Canvas canvas = new Canvas();
@@ -824,7 +855,9 @@
canvas.setBitmap(bitmap);
canvas.drawBitmap(source, srcR, dstR, paint);
canvas.setBitmap(null);
-
+ if (isHardware) {
+ return bitmap.copy(Config.HARDWARE, false);
+ }
return bitmap;
}
@@ -1428,9 +1461,8 @@
@ColorInt
public int getPixel(int x, int y) {
checkRecycled("Can't call getPixel() on a recycled bitmap");
- if (getConfig() == Config.HARDWARE) {
- throw new IllegalStateException("Can't access pixels in hardware Bitmaps");
- }
+ checkHardware("unable to getPixel(), "
+ + "pixel access is not supported on Config#HARDWARE bitmaps");
checkPixelAccess(x, y);
return nativeGetPixel(mNativePtr, x, y);
}
@@ -1462,9 +1494,8 @@
public void getPixels(@ColorInt int[] pixels, int offset, int stride,
int x, int y, int width, int height) {
checkRecycled("Can't call getPixels() on a recycled bitmap");
- if (getConfig() == Config.HARDWARE) {
- throw new IllegalStateException("Can't access pixels in hardware Bitmaps");
- }
+ checkHardware("unable to getPixels(), "
+ + "pixel access is not supported on Config#HARDWARE bitmaps");
if (width == 0 || height == 0) {
return; // nothing to do
}
@@ -1715,6 +1746,15 @@
nativePrepareToDraw(mNativePtr);
}
+ /**
+ *
+ * @return {@link GraphicBuffer} which is internally used by hardware bitmap
+ * @hide
+ */
+ public GraphicBuffer createGraphicBufferHandle() {
+ return nativeCreateGraphicBufferHandle(mNativePtr);
+ }
+
//////////// native methods
private static native Bitmap nativeCreate(int[] colors, int offset,
@@ -1773,4 +1813,7 @@
private static native boolean nativeSameAs(long nativeBitmap0, long nativeBitmap1);
private static native void nativePrepareToDraw(long nativeBitmap);
private static native int nativeGetAllocationByteCount(long nativeBitmap);
+ private static native Bitmap nativeCopyPreserveInternalConfig(long nativeBitmap);
+ private static native Bitmap nativeCreateHardwareBitmap(GraphicBuffer buffer);
+ private static native GraphicBuffer nativeCreateGraphicBufferHandle(long nativeBitmap);
}
diff --git a/graphics/java/android/graphics/Canvas.java b/graphics/java/android/graphics/Canvas.java
index b093458..cc5cc7b 100644
--- a/graphics/java/android/graphics/Canvas.java
+++ b/graphics/java/android/graphics/Canvas.java
@@ -801,12 +801,13 @@
* @param op How the clip is modified
* @return true if the resulting is non-empty
*
+ * @removed
* @deprecated Unlike all other clip calls this API does not respect the
* current matrix. Use {@link #clipRect(Rect)} as an alternative.
*/
@Deprecated
public boolean clipRegion(@NonNull Region region, @NonNull Region.Op op) {
- return nClipRegion(mNativeCanvasWrapper, region.ni(), op.nativeInt);
+ return false;
}
/**
@@ -819,12 +820,13 @@
* @param region The region to operate on the current clip, based on op
* @return true if the resulting is non-empty
*
+ * @removed
* @deprecated Unlike all other clip calls this API does not respect the
* current matrix. Use {@link #clipRect(Rect)} as an alternative.
*/
@Deprecated
public boolean clipRegion(@NonNull Region region) {
- return clipRegion(region, Region.Op.INTERSECT);
+ return false;
}
public @Nullable DrawFilter getDrawFilter() {
@@ -1115,10 +1117,6 @@
long nativePath,
int regionOp);
@FastNative
- private static native boolean nClipRegion(long nativeCanvas,
- long nativeRegion,
- int regionOp);
- @FastNative
private static native void nSetDrawFilter(long nativeCanvas,
long nativeFilter);
@FastNative
diff --git a/core/java/android/view/GraphicBuffer.aidl b/graphics/java/android/graphics/GraphicBuffer.aidl
similarity index 95%
rename from core/java/android/view/GraphicBuffer.aidl
rename to graphics/java/android/graphics/GraphicBuffer.aidl
index 6dc6bed..134699a 100644
--- a/core/java/android/view/GraphicBuffer.aidl
+++ b/graphics/java/android/graphics/GraphicBuffer.aidl
@@ -14,6 +14,6 @@
* limitations under the License.
*/
-package android.view;
+package android.graphics;
parcelable GraphicBuffer;
diff --git a/core/java/android/view/GraphicBuffer.java b/graphics/java/android/graphics/GraphicBuffer.java
similarity index 93%
rename from core/java/android/view/GraphicBuffer.java
rename to graphics/java/android/graphics/GraphicBuffer.java
index 64611d0..3be9216 100644
--- a/core/java/android/view/GraphicBuffer.java
+++ b/graphics/java/android/graphics/GraphicBuffer.java
@@ -14,12 +14,8 @@
* limitations under the License.
*/
-package android.view;
+package android.graphics;
-import android.graphics.Bitmap;
-import android.graphics.Canvas;
-import android.graphics.PixelFormat;
-import android.graphics.Rect;
import android.os.Parcel;
import android.os.Parcelable;
@@ -265,16 +261,6 @@
nWriteGraphicBufferToParcel(mNativeObject, dest);
}
- /**
- * Create hardware bitmap backed by this GraphicBuffer.
- *
- * @return Bitmap or null if this GraphicBuffer has unsupported PixelFormat.
- * currently PIXEL_FORMAT_RGBA_8888 is the only supported format
- */
- public Bitmap createHardwareBitmap() {
- return nCreateHardwareBitmap(mNativeObject);
- }
-
public static final Parcelable.Creator<GraphicBuffer> CREATOR =
new Parcelable.Creator<GraphicBuffer>() {
public GraphicBuffer createFromParcel(Parcel in) {
@@ -300,5 +286,4 @@
private static native long nReadGraphicBufferFromParcel(Parcel in);
private static native boolean nLockCanvas(long nativeObject, Canvas canvas, Rect dirty);
private static native boolean nUnlockCanvasAndPost(long nativeObject, Canvas canvas);
- private static native Bitmap nCreateHardwareBitmap(long nativeObject);
}
diff --git a/libs/androidfw/AttributeResolution.cpp b/libs/androidfw/AttributeResolution.cpp
index f5aef05..d433b90 100644
--- a/libs/androidfw/AttributeResolution.cpp
+++ b/libs/androidfw/AttributeResolution.cpp
@@ -418,8 +418,10 @@
out_values[STYLE_CHANGING_CONFIGURATIONS] = type_set_flags;
out_values[STYLE_DENSITY] = config.density;
- if (out_indices != nullptr && value.dataType != Res_value::TYPE_NULL) {
+ if (value.dataType != Res_value::TYPE_NULL) {
indices_idx++;
+
+ // out_indices must NOT be nullptr.
out_indices[indices_idx] = ii;
}
@@ -428,9 +430,8 @@
res.unlock();
- if (out_indices != nullptr) {
- out_indices[0] = indices_idx;
- }
+ // out_indices must NOT be nullptr.
+ out_indices[0] = indices_idx;
}
bool RetrieveAttributes(const ResTable* res, ResXMLParser* xml_parser,
diff --git a/libs/androidfw/include/androidfw/AttributeResolution.h b/libs/androidfw/include/androidfw/AttributeResolution.h
index 8d5ff46..69b76041 100644
--- a/libs/androidfw/include/androidfw/AttributeResolution.h
+++ b/libs/androidfw/include/androidfw/AttributeResolution.h
@@ -40,14 +40,20 @@
// TODO(adamlesinski): Run performance tests against these methods and a new, single method
// that uses all the sources and branches to the right ones within the inner loop.
+// `out_values` must NOT be nullptr.
+// `out_indices` may be nullptr.
bool ResolveAttrs(ResTable::Theme* theme, uint32_t def_style_attr, uint32_t def_style_res,
uint32_t* src_values, size_t src_values_length, uint32_t* attrs,
size_t attrs_length, uint32_t* out_values, uint32_t* out_indices);
+// `out_values` must NOT be nullptr.
+// `out_indices` is NOT optional and must NOT be nullptr.
void ApplyStyle(ResTable::Theme* theme, ResXMLParser* xml_parser, uint32_t def_style_attr,
uint32_t def_style_res, const uint32_t* attrs, size_t attrs_length,
uint32_t* out_values, uint32_t* out_indices);
+// `out_values` must NOT be nullptr.
+// `out_indices` may be nullptr.
bool RetrieveAttributes(const ResTable* res, ResXMLParser* xml_parser, uint32_t* attrs,
size_t attrs_length, uint32_t* out_values, uint32_t* out_indices);
diff --git a/libs/androidfw/tests/AttributeResolution_test.cpp b/libs/androidfw/tests/AttributeResolution_test.cpp
index d417aba..7550517 100644
--- a/libs/androidfw/tests/AttributeResolution_test.cpp
+++ b/libs/androidfw/tests/AttributeResolution_test.cpp
@@ -16,6 +16,8 @@
#include "androidfw/AttributeResolution.h"
+#include <array>
+
#include "android-base/file.h"
#include "android-base/logging.h"
#include "android-base/macros.h"
@@ -67,15 +69,13 @@
ResTable::Theme theme(table_);
ASSERT_EQ(NO_ERROR, theme.applyStyle(R::style::StyleTwo));
- uint32_t attrs[] = {R::attr::attr_one, R::attr::attr_two, R::attr::attr_three,
- R::attr::attr_four};
- std::vector<uint32_t> values;
- values.resize(arraysize(attrs) * 6);
+ std::array<uint32_t, 4> attrs{
+ {R::attr::attr_one, R::attr::attr_two, R::attr::attr_three, R::attr::attr_four}};
+ std::array<uint32_t, attrs.size() * STYLE_NUM_ENTRIES> values;
ASSERT_TRUE(ResolveAttrs(&theme, 0 /*def_style_attr*/, 0 /*def_style_res*/,
- nullptr /*src_values*/, 0 /*src_values_length*/,
- attrs, arraysize(attrs), values.data(),
- nullptr /*out_indices*/));
+ nullptr /*src_values*/, 0 /*src_values_length*/, attrs.data(),
+ attrs.size(), values.data(), nullptr /*out_indices*/));
const uint32_t public_flag = ResTable_typeSpec::SPEC_PUBLIC;
@@ -112,13 +112,12 @@
}
TEST_F(AttributeResolutionXmlTest, XmlParser) {
- uint32_t attrs[] = {R::attr::attr_one, R::attr::attr_two, R::attr::attr_three,
- R::attr::attr_four};
- std::vector<uint32_t> values;
- values.resize(arraysize(attrs) * 6);
+ std::array<uint32_t, 4> attrs{
+ {R::attr::attr_one, R::attr::attr_two, R::attr::attr_three, R::attr::attr_four}};
+ std::array<uint32_t, attrs.size() * STYLE_NUM_ENTRIES> values;
- ASSERT_TRUE(RetrieveAttributes(&table_, &xml_parser_, attrs, arraysize(attrs),
- values.data(), nullptr /*out_indices*/));
+ ASSERT_TRUE(RetrieveAttributes(&table_, &xml_parser_, attrs.data(), attrs.size(), values.data(),
+ nullptr /*out_indices*/));
uint32_t* values_cursor = values.data();
EXPECT_EQ(Res_value::TYPE_NULL, values_cursor[STYLE_TYPE]);
@@ -157,14 +156,13 @@
ResTable::Theme theme(table_);
ASSERT_EQ(NO_ERROR, theme.applyStyle(R::style::StyleTwo));
- uint32_t attrs[] = {R::attr::attr_one, R::attr::attr_two, R::attr::attr_three,
- R::attr::attr_four, R::attr::attr_five};
- std::vector<uint32_t> values;
- values.resize(arraysize(attrs) * 6);
+ std::array<uint32_t, 5> attrs{{R::attr::attr_one, R::attr::attr_two, R::attr::attr_three,
+ R::attr::attr_four, R::attr::attr_five}};
+ std::array<uint32_t, attrs.size() * STYLE_NUM_ENTRIES> values;
+ std::array<uint32_t, attrs.size()> indices;
- ApplyStyle(&theme, &xml_parser_, 0 /*def_style_attr*/,
- 0 /*def_style_res*/, attrs, arraysize(attrs),
- values.data(), nullptr /*out_indices*/);
+ ApplyStyle(&theme, &xml_parser_, 0 /*def_style_attr*/, 0 /*def_style_res*/, attrs.data(),
+ attrs.size(), values.data(), indices.data());
const uint32_t public_flag = ResTable_typeSpec::SPEC_PUBLIC;
diff --git a/libs/hwui/CanvasState.cpp b/libs/hwui/CanvasState.cpp
index dbbf00d..9c068b0 100644
--- a/libs/hwui/CanvasState.cpp
+++ b/libs/hwui/CanvasState.cpp
@@ -212,11 +212,6 @@
return !mSnapshot->clipIsEmpty();
}
-bool CanvasState::clipRegion(const SkRegion* region, SkClipOp op) {
- mSnapshot->clipRegionTransformed(*region, op);
- return !mSnapshot->clipIsEmpty();
-}
-
void CanvasState::setClippingOutline(LinearAllocator& allocator, const Outline* outline) {
Rect bounds;
float radius;
diff --git a/libs/hwui/CanvasState.h b/libs/hwui/CanvasState.h
index a805597..b1fe09e 100644
--- a/libs/hwui/CanvasState.h
+++ b/libs/hwui/CanvasState.h
@@ -124,7 +124,6 @@
bool clipRect(float left, float top, float right, float bottom, SkClipOp op);
bool clipPath(const SkPath* path, SkClipOp op);
- bool clipRegion(const SkRegion* region, SkClipOp op);
/**
* Sets a "clipping outline", which is independent from the regular clip.
diff --git a/libs/hwui/ClipArea.h b/libs/hwui/ClipArea.h
index 2e56160..cf57516 100644
--- a/libs/hwui/ClipArea.h
+++ b/libs/hwui/ClipArea.h
@@ -146,7 +146,6 @@
void setClip(float left, float top, float right, float bottom);
void clipRectWithTransform(const Rect& r, const mat4* transform,
SkRegion::Op op);
- void clipRegion(const SkRegion& region, SkRegion::Op op);
void clipPathWithTransform(const SkPath& path, const mat4* transform,
SkRegion::Op op);
@@ -195,6 +194,7 @@
void regionModeClipRectWithTransform(const Rect& r, const mat4* transform,
SkRegion::Op op);
+ void clipRegion(const SkRegion& region, SkRegion::Op op);
void ensureClipRegion();
void onClipRegionUpdated();
diff --git a/libs/hwui/FontRenderer.cpp b/libs/hwui/FontRenderer.cpp
index effc65e..4f9a3de 100644
--- a/libs/hwui/FontRenderer.cpp
+++ b/libs/hwui/FontRenderer.cpp
@@ -22,6 +22,7 @@
#include "Caches.h"
#include "Debug.h"
#include "Extensions.h"
+#include "font/Font.h"
#include "Glop.h"
#include "GlopBuilder.h"
#include "PixelBuffer.h"
diff --git a/libs/hwui/RecordingCanvas.cpp b/libs/hwui/RecordingCanvas.cpp
index 96c6d29..ee6279d 100644
--- a/libs/hwui/RecordingCanvas.cpp
+++ b/libs/hwui/RecordingCanvas.cpp
@@ -240,9 +240,6 @@
bool RecordingCanvas::clipPath(const SkPath* path, SkClipOp op) {
return mState.clipPath(path, op);
}
-bool RecordingCanvas::clipRegion(const SkRegion* region, SkClipOp op) {
- return mState.clipRegion(region, op);
-}
// ----------------------------------------------------------------------------
// android/graphics/Canvas draw operations
diff --git a/libs/hwui/RecordingCanvas.h b/libs/hwui/RecordingCanvas.h
index 5d49385..44181bd2 100644
--- a/libs/hwui/RecordingCanvas.h
+++ b/libs/hwui/RecordingCanvas.h
@@ -134,7 +134,6 @@
virtual bool clipRect(float left, float top, float right, float bottom,
SkClipOp op) override;
virtual bool clipPath(const SkPath* path, SkClipOp op) override;
- virtual bool clipRegion(const SkRegion* region, SkClipOp op) override;
// Misc
virtual SkDrawFilter* getDrawFilter() override { return mDrawFilter.get(); }
diff --git a/libs/hwui/SkiaCanvas.cpp b/libs/hwui/SkiaCanvas.cpp
index 8cae771..344df0a7 100644
--- a/libs/hwui/SkiaCanvas.cpp
+++ b/libs/hwui/SkiaCanvas.cpp
@@ -416,23 +416,6 @@
return !mCanvas->isClipEmpty();
}
-bool SkiaCanvas::clipRegion(const SkRegion* region, SkClipOp op) {
- SkPath rgnPath;
- if (region->getBoundaryPath(&rgnPath)) {
- // The region is specified in device space.
- SkMatrix savedMatrix = mCanvas->getTotalMatrix();
- mCanvas->resetMatrix();
- this->recordClip(rgnPath, op);
- mCanvas->clipPath(rgnPath, op);
- mCanvas->setMatrix(savedMatrix);
- } else {
- const auto emptyClip = SkRect::MakeEmpty();
- this->recordClip(emptyClip, op);
- mCanvas->clipRect(emptyClip, op);
- }
- return !mCanvas->isClipEmpty();
-}
-
// ----------------------------------------------------------------------------
// Canvas state operations: Filters
// ----------------------------------------------------------------------------
diff --git a/libs/hwui/SkiaCanvas.h b/libs/hwui/SkiaCanvas.h
index 9639ebd..34c3717 100644
--- a/libs/hwui/SkiaCanvas.h
+++ b/libs/hwui/SkiaCanvas.h
@@ -94,7 +94,6 @@
virtual bool clipRect(float left, float top, float right, float bottom,
SkClipOp op) override;
virtual bool clipPath(const SkPath* path, SkClipOp op) override;
- virtual bool clipRegion(const SkRegion* region, SkClipOp op) override;
virtual SkDrawFilter* getDrawFilter() override;
virtual void setDrawFilter(SkDrawFilter* drawFilter) override;
diff --git a/libs/hwui/SkiaCanvasProxy.cpp b/libs/hwui/SkiaCanvasProxy.cpp
index 75396f7..c5156cf 100644
--- a/libs/hwui/SkiaCanvasProxy.cpp
+++ b/libs/hwui/SkiaCanvasProxy.cpp
@@ -19,6 +19,7 @@
#include "hwui/Bitmap.h"
#include <cutils/log.h>
+#include <SkLatticeIter.h>
#include <SkPatchUtils.h>
#include <SkPaint.h>
#include <SkPath.h>
@@ -140,6 +141,39 @@
SkDEBUGFAIL("SkiaCanvasProxy::onDrawBitmapNine is not yet supported");
}
+void SkiaCanvasProxy::onDrawImage(const SkImage* image, SkScalar left, SkScalar top,
+ const SkPaint* paint) {
+ SkBitmap skiaBitmap;
+ if (image->asLegacyBitmap(&skiaBitmap, SkImage::kRO_LegacyBitmapMode)) {
+ onDrawBitmap(skiaBitmap, left, top, paint);
+ }
+}
+
+void SkiaCanvasProxy::onDrawImageRect(const SkImage* image, const SkRect* srcPtr, const SkRect& dst,
+ const SkPaint* paint, SrcRectConstraint constraint) {
+ SkBitmap skiaBitmap;
+ if (image->asLegacyBitmap(&skiaBitmap, SkImage::kRO_LegacyBitmapMode)) {
+ sk_sp<Bitmap> bitmap = Bitmap::createFrom(skiaBitmap.info(), *skiaBitmap.pixelRef());
+ SkRect src = (srcPtr) ? *srcPtr : SkRect::MakeWH(image->width(), image->height());
+ mCanvas->drawBitmap(*bitmap, src.fLeft, src.fTop, src.fRight, src.fBottom,
+ dst.fLeft, dst.fTop, dst.fRight, dst.fBottom, paint);
+ }
+}
+
+void SkiaCanvasProxy::onDrawImageNine(const SkImage*, const SkIRect& center, const SkRect& dst,
+ const SkPaint*) {
+ SkDEBUGFAIL("SkiaCanvasProxy::onDrawImageNine is not yet supported");
+}
+
+void SkiaCanvasProxy::onDrawImageLattice(const SkImage* image, const Lattice& lattice,
+ const SkRect& dst, const SkPaint* paint) {
+ SkLatticeIter iter(lattice, dst);
+ SkRect srcR, dstR;
+ while (iter.next(&srcR, &dstR)) {
+ onDrawImageRect(image, &srcR, dstR, paint, SkCanvas::kStrict_SrcRectConstraint);
+ }
+}
+
void SkiaCanvasProxy::onDrawVertices(VertexMode mode, int vertexCount, const SkPoint vertices[],
const SkPoint texs[], const SkColor colors[], SkBlendMode, const uint16_t indices[],
int indexCount, const SkPaint& paint) {
@@ -444,9 +478,5 @@
mCanvas->clipPath(&path, op);
}
-void SkiaCanvasProxy::onClipRegion(const SkRegion& region, SkClipOp op) {
- mCanvas->clipRegion(®ion, op);
-}
-
}; // namespace uirenderer
}; // namespace android
diff --git a/libs/hwui/SkiaCanvasProxy.h b/libs/hwui/SkiaCanvasProxy.h
index badcc1d..b3f6c07 100644
--- a/libs/hwui/SkiaCanvasProxy.h
+++ b/libs/hwui/SkiaCanvasProxy.h
@@ -66,6 +66,13 @@
const SkPaint* paint, SrcRectConstraint) override;
virtual void onDrawBitmapNine(const SkBitmap& bitmap, const SkIRect& center,
const SkRect& dst, const SkPaint*) override;
+ virtual void onDrawImage(const SkImage*, SkScalar dx, SkScalar dy, const SkPaint*);
+ virtual void onDrawImageRect(const SkImage*, const SkRect*, const SkRect&, const SkPaint*,
+ SrcRectConstraint);
+ virtual void onDrawImageNine(const SkImage*, const SkIRect& center, const SkRect& dst,
+ const SkPaint*);
+ virtual void onDrawImageLattice(const SkImage*, const Lattice& lattice, const SkRect& dst,
+ const SkPaint*);
virtual void onDrawVertices(VertexMode, int vertexCount, const SkPoint vertices[],
const SkPoint texs[], const SkColor colors[], SkBlendMode,
const uint16_t indices[], int indexCount,
@@ -93,7 +100,6 @@
virtual void onClipRect(const SkRect&, SkClipOp, ClipEdgeStyle) override;
virtual void onClipRRect(const SkRRect&, SkClipOp, ClipEdgeStyle) override;
virtual void onClipPath(const SkPath&, SkClipOp, ClipEdgeStyle) override;
- virtual void onClipRegion(const SkRegion&, SkClipOp) override;
private:
Canvas* mCanvas;
diff --git a/libs/hwui/Snapshot.cpp b/libs/hwui/Snapshot.cpp
index 3f08009..9d719bd 100644
--- a/libs/hwui/Snapshot.cpp
+++ b/libs/hwui/Snapshot.cpp
@@ -72,11 +72,6 @@
// Clipping
///////////////////////////////////////////////////////////////////////////////
-void Snapshot::clipRegionTransformed(const SkRegion& region, SkClipOp op) {
- flags |= Snapshot::kFlagClipSet;
- mClipArea->clipRegion(region, static_cast<SkRegion::Op>(op));
-}
-
void Snapshot::clip(const Rect& localClip, SkClipOp op) {
flags |= Snapshot::kFlagClipSet;
mClipArea->clipRectWithTransform(localClip, transform, static_cast<SkRegion::Op>(op));
diff --git a/libs/hwui/Snapshot.h b/libs/hwui/Snapshot.h
index 4f92657..8cd90a6 100644
--- a/libs/hwui/Snapshot.h
+++ b/libs/hwui/Snapshot.h
@@ -118,12 +118,6 @@
void clipTransformed(const Rect& r, SkClipOp op = SkClipOp::kIntersect);
/**
- * Modifies the current clip with the specified region and operation.
- * The specified region is considered already transformed.
- */
- void clipRegionTransformed(const SkRegion& region, SkClipOp op);
-
- /**
* Modifies the current clip with the specified path and operation.
*/
void clipPath(const SkPath& path, SkClipOp op);
diff --git a/libs/hwui/hwui/Canvas.h b/libs/hwui/hwui/Canvas.h
index e7b6b2d..969d877 100644
--- a/libs/hwui/hwui/Canvas.h
+++ b/libs/hwui/hwui/Canvas.h
@@ -184,7 +184,6 @@
virtual bool clipRect(float left, float top, float right, float bottom,
SkClipOp op) = 0;
virtual bool clipPath(const SkPath* path, SkClipOp op) = 0;
- virtual bool clipRegion(const SkRegion* region, SkClipOp op) = 0;
// filters
virtual SkDrawFilter* getDrawFilter() = 0;
diff --git a/location/java/android/location/GnssMeasurement.java b/location/java/android/location/GnssMeasurement.java
index 761ee22..7033900 100644
--- a/location/java/android/location/GnssMeasurement.java
+++ b/location/java/android/location/GnssMeasurement.java
@@ -63,7 +63,7 @@
*/
@Retention(RetentionPolicy.SOURCE)
@IntDef({MULTIPATH_INDICATOR_UNKNOWN, MULTIPATH_INDICATOR_DETECTED,
- MULTIPATH_INDICATOR_NOT_USED})
+ MULTIPATH_INDICATOR_NOT_DETECTED})
public @interface MultipathIndicator {}
/**
@@ -81,9 +81,6 @@
*/
public static final int MULTIPATH_INDICATOR_NOT_DETECTED = 2;
- /** @removed */
- public static final int MULTIPATH_INDICATOR_NOT_USED = 2;
-
/** This GNSS measurement's tracking state is invalid or unknown. */
public static final int STATE_UNKNOWN = 0;
/** This GNSS measurement's tracking state has code lock. */
@@ -803,8 +800,8 @@
return "Unknown";
case MULTIPATH_INDICATOR_DETECTED:
return "Detected";
- case MULTIPATH_INDICATOR_NOT_USED:
- return "NotUsed";
+ case MULTIPATH_INDICATOR_NOT_DETECTED:
+ return "NotDetected";
default:
return "<Invalid:" + mMultipathIndicator + ">";
}
diff --git a/location/java/android/location/GnssMeasurementsEvent.java b/location/java/android/location/GnssMeasurementsEvent.java
index 7db0466..d66fd9c 100644
--- a/location/java/android/location/GnssMeasurementsEvent.java
+++ b/location/java/android/location/GnssMeasurementsEvent.java
@@ -34,13 +34,6 @@
* Events are delivered to registered instances of {@link Callback}.
*/
public final class GnssMeasurementsEvent implements Parcelable {
- /** @removed */
- public static final int STATUS_NOT_SUPPORTED = 0;
- /** @removed */
- public static final int STATUS_READY = 1;
- /** @removed */
- public static final int STATUS_GNSS_LOCATION_DISABLED = 2;
-
private final GnssClock mClock;
private final Collection<GnssMeasurement> mReadOnlyMeasurements;
diff --git a/location/java/android/location/GnssNavigationMessageEvent.aidl b/location/java/android/location/GnssNavigationMessageEvent.aidl
deleted file mode 100644
index e765739..0000000
--- a/location/java/android/location/GnssNavigationMessageEvent.aidl
+++ /dev/null
@@ -1,19 +0,0 @@
-/*
- * Copyright (C) 2014, 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 android.location;
-
-parcelable GnssNavigationMessageEvent;
diff --git a/location/java/android/location/GnssNavigationMessageEvent.java b/location/java/android/location/GnssNavigationMessageEvent.java
deleted file mode 100644
index f7e5665..0000000
--- a/location/java/android/location/GnssNavigationMessageEvent.java
+++ /dev/null
@@ -1,125 +0,0 @@
-/*
- * Copyright (C) 2014 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 android.location;
-
-import android.annotation.IntDef;
-import android.annotation.NonNull;
-import android.os.Parcel;
-import android.os.Parcelable;
-
-import java.lang.annotation.Retention;
-import java.lang.annotation.RetentionPolicy;
-import java.security.InvalidParameterException;
-
-/**
- * A class implementing a container for data associated with a navigation message event.
- * Events are delivered to registered instances of {@link Callback}.
- * @removed
- */
-public final class GnssNavigationMessageEvent implements Parcelable {
- /**
- * The status of GNSS measurements event.
- * @hide
- */
- @Retention(RetentionPolicy.SOURCE)
- @IntDef({STATUS_NOT_SUPPORTED, STATUS_READY, STATUS_GNSS_LOCATION_DISABLED})
- public @interface GnssNavigationMessageStatus {}
-
- /**
- * The system does not support tracking of GNSS Navigation Messages.
- *
- * This status will not change in the future.
- */
- public static final int STATUS_NOT_SUPPORTED = 0;
-
- /**
- * GNSS Navigation Messages are successfully being tracked, it will receive updates once they
- * are available.
- */
- public static final int STATUS_READY = 1;
-
- /**
- * GNSS provider or Location is disabled, updated will not be received until they are enabled.
- */
- public static final int STATUS_GNSS_LOCATION_DISABLED = 2;
-
- private final GnssNavigationMessage mNavigationMessage;
-
- /**
- * Used for receiving GNSS satellite Navigation Messages from the GNSS engine.
- *
- * <p>You can implement this interface and call
- * {@link LocationManager#registerGnssNavigationMessageCallback}.
- */
- public static abstract class Callback {
-
- /**
- * Returns the latest collected GNSS Navigation Message.
- */
- public void onGnssNavigationMessageReceived(GnssNavigationMessageEvent event) {}
-
- /**
- * Returns the latest status of the GNSS Navigation Messages sub-system.
- */
- public void onStatusChanged(@GnssNavigationMessageStatus int status) {}
- }
-
- public GnssNavigationMessageEvent(GnssNavigationMessage message) {
- if (message == null) {
- throw new InvalidParameterException("Parameter 'message' must not be null.");
- }
- mNavigationMessage = message;
- }
-
- @NonNull
- public GnssNavigationMessage getNavigationMessage() {
- return mNavigationMessage;
- }
-
- public static final Creator<GnssNavigationMessageEvent> CREATOR =
- new Creator<GnssNavigationMessageEvent>() {
- @Override
- public GnssNavigationMessageEvent createFromParcel(Parcel in) {
- ClassLoader classLoader = getClass().getClassLoader();
- GnssNavigationMessage navigationMessage = in.readParcelable(classLoader);
- return new GnssNavigationMessageEvent(navigationMessage);
- }
-
- @Override
- public GnssNavigationMessageEvent[] newArray(int size) {
- return new GnssNavigationMessageEvent[size];
- }
- };
-
- @Override
- public int describeContents() {
- return 0;
- }
-
- @Override
- public void writeToParcel(Parcel parcel, int flags) {
- parcel.writeParcelable(mNavigationMessage, flags);
- }
-
- @Override
- public String toString() {
- StringBuilder builder = new StringBuilder("[ GnssNavigationMessageEvent:\n\n");
- builder.append(mNavigationMessage.toString());
- builder.append("\n]");
- return builder.toString();
- }
-}
diff --git a/location/java/android/location/GnssNmeaListener.java b/location/java/android/location/GnssNmeaListener.java
deleted file mode 100644
index 756ae49..0000000
--- a/location/java/android/location/GnssNmeaListener.java
+++ /dev/null
@@ -1,31 +0,0 @@
-/*
- * Copyright (C) 2016 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 android.location;
-
-/**
-* Used for receiving NMEA sentences from the GNSS.
-* NMEA 0183 is a standard for communicating with marine electronic devices
-* and is a common method for receiving data from a GNSS, typically over a serial port.
-* See <a href="http://en.wikipedia.org/wiki/NMEA_0183">NMEA 0183</a> for more details.
-* You can implement this interface and call {@link LocationManager#addNmeaListener}
-* to receive NMEA data from the GNSS engine.
-* @removed
-*/
-public interface GnssNmeaListener {
- /** Called when an NMEA message is received. */
- void onNmeaReceived(long timestamp, String nmea);
-}
diff --git a/location/java/android/location/GnssStatus.java b/location/java/android/location/GnssStatus.java
index e68821b..f105144 100644
--- a/location/java/android/location/GnssStatus.java
+++ b/location/java/android/location/GnssStatus.java
@@ -111,11 +111,6 @@
mAzimuths = azimuths;
}
- /** @removed */
- public int getNumSatellites() {
- return getSatelliteCount();
- }
-
/**
* Gets the total number of satellites in satellite list.
*/
@@ -191,11 +186,6 @@
return mAzimuths[satIndex];
}
- /** @removed */
- public boolean hasEphemeris(int satIndex) {
- return hasEphemerisData(satIndex);
- }
-
/**
* Reports whether the satellite at the specified index has ephemeris data.
*
@@ -205,11 +195,6 @@
return (mSvidWithFlags[satIndex] & GNSS_SV_FLAGS_HAS_EPHEMERIS_DATA) != 0;
}
- /** @removed */
- public boolean hasAlmanac(int satIndex) {
- return hasAlmanacData(satIndex);
- }
-
/**
* Reports whether the satellite at the specified index has almanac data.
*
diff --git a/location/java/android/location/GnssStatusCallback.java b/location/java/android/location/GnssStatusCallback.java
deleted file mode 100644
index bf295ef..0000000
--- a/location/java/android/location/GnssStatusCallback.java
+++ /dev/null
@@ -1,45 +0,0 @@
-/*
- * Copyright (C) 2016 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 android.location;
-
-/**
- * Used for receiving notifications when GNSS events happen.
- * @removed
- */
-public abstract class GnssStatusCallback {
- /**
- * Called when GNSS system has started.
- */
- public void onStarted() {}
-
- /**
- * Called when GNSS system has stopped.
- */
- public void onStopped() {}
-
- /**
- * Called when the GNSS system has received its first fix since starting.
- * @param ttffMillis the time from start to first fix in milliseconds.
- */
- public void onFirstFix(int ttffMillis) {}
-
- /**
- * Called periodically to report GNSS satellite status.
- * @param status the current status of all satellites.
- */
- public void onSatelliteStatusChanged(GnssStatus status) {}
-}
diff --git a/location/java/android/location/LocationManager.java b/location/java/android/location/LocationManager.java
index da0e515..087e74f 100644
--- a/location/java/android/location/LocationManager.java
+++ b/location/java/android/location/LocationManager.java
@@ -70,16 +70,10 @@
new HashMap<>();
private final HashMap<GpsStatus.NmeaListener, GnssStatusListenerTransport> mGpsNmeaListeners =
new HashMap<>();
- private final HashMap<GnssStatusCallback, GnssStatusListenerTransport>
- mOldGnssStatusListeners = new HashMap<>();
private final HashMap<GnssStatus.Callback, GnssStatusListenerTransport> mGnssStatusListeners =
new HashMap<>();
- private final HashMap<GnssNmeaListener, GnssStatusListenerTransport> mOldGnssNmeaListeners =
- new HashMap<>();
private final HashMap<OnNmeaMessageListener, GnssStatusListenerTransport> mGnssNmeaListeners =
new HashMap<>();
- private final HashMap<GnssNavigationMessageEvent.Callback, GnssNavigationMessage.Callback>
- mNavigationMessageBridge = new HashMap<>();
private GnssStatus mGnssStatus;
private int mTimeToFirstFix;
@@ -1398,9 +1392,7 @@
private final GpsStatus.Listener mGpsListener;
private final GpsStatus.NmeaListener mGpsNmeaListener;
- private final GnssStatusCallback mOldGnssCallback;
private final GnssStatus.Callback mGnssCallback;
- private final GnssNmeaListener mOldGnssNmeaListener;
private final OnNmeaMessageListener mGnssNmeaListener;
private class GnssHandler extends Handler {
@@ -1464,7 +1456,6 @@
mGnssHandler = new GnssHandler(handler);
mGpsNmeaListener = null;
mNmeaBuffer = null;
- mOldGnssCallback = null;
mGnssCallback = mGpsListener != null ? new GnssStatus.Callback() {
@Override
public void onStarted() {
@@ -1486,7 +1477,6 @@
mGpsListener.onGpsStatusChanged(GpsStatus.GPS_EVENT_SATELLITE_STATUS);
}
} : null;
- mOldGnssNmeaListener = null;
mGnssNmeaListener = null;
}
@@ -1499,9 +1489,7 @@
mGnssHandler = new GnssHandler(handler);
mGpsNmeaListener = listener;
mNmeaBuffer = new ArrayList<Nmea>();
- mOldGnssCallback = null;
mGnssCallback = null;
- mOldGnssNmeaListener = null;
mGnssNmeaListener = mGpsNmeaListener != null ? new OnNmeaMessageListener() {
@Override
public void onNmeaMessage(String nmea, long timestamp) {
@@ -1510,85 +1498,26 @@
} : null;
}
- GnssStatusListenerTransport(GnssStatusCallback callback) {
- this(callback, null);
- }
-
- GnssStatusListenerTransport(GnssStatusCallback callback, Handler handler) {
- mOldGnssCallback = callback;
- mGnssCallback = mOldGnssCallback != null ? new GnssStatus.Callback() {
- @Override
- public void onStarted() {
- mOldGnssCallback.onStarted();
- }
-
- @Override
- public void onStopped() {
- mOldGnssCallback.onStopped();
- }
-
- @Override
- public void onFirstFix(int ttff) {
- mOldGnssCallback.onFirstFix(ttff);
- }
-
- @Override
- public void onSatelliteStatusChanged(GnssStatus status) {
- mOldGnssCallback.onSatelliteStatusChanged(status);
- }
- } : null;
- mGnssHandler = new GnssHandler(handler);
- mOldGnssNmeaListener = null;
- mGnssNmeaListener = null;
- mNmeaBuffer = null;
- mGpsListener = null;
- mGpsNmeaListener = null;
- }
-
GnssStatusListenerTransport(GnssStatus.Callback callback) {
this(callback, null);
}
GnssStatusListenerTransport(GnssStatus.Callback callback, Handler handler) {
- mOldGnssCallback = null;
mGnssCallback = callback;
mGnssHandler = new GnssHandler(handler);
- mOldGnssNmeaListener = null;
mGnssNmeaListener = null;
mNmeaBuffer = null;
mGpsListener = null;
mGpsNmeaListener = null;
}
- GnssStatusListenerTransport(GnssNmeaListener listener) {
- this(listener, null);
- }
-
- GnssStatusListenerTransport(GnssNmeaListener listener, Handler handler) {
- mGnssCallback = null;
- mOldGnssCallback = null;
- mGnssHandler = new GnssHandler(handler);
- mOldGnssNmeaListener = listener;
- mGnssNmeaListener = mOldGnssNmeaListener != null ? new OnNmeaMessageListener() {
- @Override
- public void onNmeaMessage(String message, long timestamp) {
- mOldGnssNmeaListener.onNmeaReceived(timestamp, message);
- }
- } : null;
- mGpsListener = null;
- mGpsNmeaListener = null;
- mNmeaBuffer = new ArrayList<Nmea>();
- }
-
GnssStatusListenerTransport(OnNmeaMessageListener listener) {
this(listener, null);
}
GnssStatusListenerTransport(OnNmeaMessageListener listener, Handler handler) {
- mOldGnssCallback = null;
mGnssCallback = null;
mGnssHandler = new GnssHandler(handler);
- mOldGnssNmeaListener = null;
mGnssNmeaListener = listener;
mGpsListener = null;
mGpsNmeaListener = null;
@@ -1703,73 +1632,9 @@
}
/**
- * Registers a GNSS status listener.
+ * Registers a GNSS status callback.
*
- * @param callback GNSS status listener object to register
- *
- * @return true if the listener was successfully added
- *
- * @throws SecurityException if the ACCESS_FINE_LOCATION permission is not present
- * @removed
- */
- @RequiresPermission(ACCESS_FINE_LOCATION)
- public boolean registerGnssStatusCallback(GnssStatusCallback callback) {
- return registerGnssStatusCallback(callback, null);
- }
-
- /**
- * Registers a GNSS status listener.
- *
- * @param callback GNSS status listener object to register
- * @param handler the handler that the callback runs on.
- *
- * @return true if the listener was successfully added
- *
- * @throws SecurityException if the ACCESS_FINE_LOCATION permission is not present
- * @removed
- */
- @RequiresPermission(ACCESS_FINE_LOCATION)
- public boolean registerGnssStatusCallback(GnssStatusCallback callback, Handler handler) {
- boolean result;
- if (mOldGnssStatusListeners.get(callback) != null) {
- // listener is already registered
- return true;
- }
- try {
- GnssStatusListenerTransport transport =
- new GnssStatusListenerTransport(callback, handler);
- result = mService.registerGnssStatusCallback(transport, mContext.getPackageName());
- if (result) {
- mOldGnssStatusListeners.put(callback, transport);
- }
- } catch (RemoteException e) {
- throw e.rethrowFromSystemServer();
- }
-
- return result;
- }
-
- /**
- * Removes a GNSS status listener.
- *
- * @param callback GNSS status listener object to remove
- * @removed
- */
- public void unregisterGnssStatusCallback(GnssStatusCallback callback) {
- try {
- GnssStatusListenerTransport transport = mOldGnssStatusListeners.remove(callback);
- if (transport != null) {
- mService.unregisterGnssStatusCallback(transport);
- }
- } catch (RemoteException e) {
- throw e.rethrowFromSystemServer();
- }
- }
-
- /**
- * Registers a GNSS status listener.
- *
- * @param callback GNSS status listener object to register
+ * @param callback GNSS status callback object to register
*
* @return true if the listener was successfully added
*
@@ -1781,9 +1646,9 @@
}
/**
- * Registers a GNSS status listener.
+ * Registers a GNSS status callback.
*
- * @param callback GNSS status listener object to register
+ * @param callback GNSS status callback object to register
* @param handler the handler that the callback runs on.
*
* @return true if the listener was successfully added
@@ -1812,9 +1677,9 @@
}
/**
- * Removes a GNSS status listener.
+ * Removes a GNSS status callback.
*
- * @param callback GNSS status listener object to remove
+ * @param callback GNSS status callback object to remove
*/
public void unregisterGnssStatusCallback(GnssStatus.Callback callback) {
try {
@@ -1880,71 +1745,6 @@
/**
* Adds an NMEA listener.
*
- * @param listener a {@link GnssNmeaListener} object to register
- *
- * @return true if the listener was successfully added
- *
- * @throws SecurityException if the ACCESS_FINE_LOCATION permission is not present
- * @removed
- */
- @RequiresPermission(ACCESS_FINE_LOCATION)
- public boolean addNmeaListener(GnssNmeaListener listener) {
- return addNmeaListener(listener, null);
- }
-
- /**
- * Adds an NMEA listener.
- *
- * @param listener a {@link GnssNmeaListener} object to register
- * @param handler the handler that the listener runs on.
- *
- * @return true if the listener was successfully added
- *
- * @throws SecurityException if the ACCESS_FINE_LOCATION permission is not present
- * @removed
- */
- @RequiresPermission(ACCESS_FINE_LOCATION)
- public boolean addNmeaListener(GnssNmeaListener listener, Handler handler) {
- boolean result;
-
- if (mGpsNmeaListeners.get(listener) != null) {
- // listener is already registered
- return true;
- }
- try {
- GnssStatusListenerTransport transport =
- new GnssStatusListenerTransport(listener, handler);
- result = mService.registerGnssStatusCallback(transport, mContext.getPackageName());
- if (result) {
- mOldGnssNmeaListeners.put(listener, transport);
- }
- } catch (RemoteException e) {
- throw e.rethrowFromSystemServer();
- }
-
- return result;
- }
-
- /**
- * Removes an NMEA listener.
- *
- * @param listener a {@link GnssNmeaListener} object to remove
- * @removed
- */
- public void removeNmeaListener(GnssNmeaListener listener) {
- try {
- GnssStatusListenerTransport transport = mOldGnssNmeaListeners.remove(listener);
- if (transport != null) {
- mService.unregisterGnssStatusCallback(transport);
- }
- } catch (RemoteException e) {
- throw e.rethrowFromSystemServer();
- }
- }
-
- /**
- * Adds an NMEA listener.
- *
* @param listener a {@link OnNmeaMessageListener} object to register
*
* @return true if the listener was successfully added
@@ -2088,58 +1888,6 @@
/**
* Registers a GNSS Navigation Message callback.
*
- * @param callback a {@link GnssNavigationMessageEvent.Callback} object to register.
- * @return {@code true} if the callback was added successfully, {@code false} otherwise.
- * @removed
- */
- public boolean registerGnssNavigationMessageCallback(
- GnssNavigationMessageEvent.Callback callback) {
- return registerGnssNavigationMessageCallback(callback, null);
- }
-
- /**
- * Registers a GNSS Navigation Message callback.
- *
- * @param callback a {@link GnssNavigationMessageEvent.Callback} object to register.
- * @param handler the handler that the callback runs on.
- * @return {@code true} if the callback was added successfully, {@code false} otherwise.
- * @removed
- */
- @RequiresPermission(ACCESS_FINE_LOCATION)
- public boolean registerGnssNavigationMessageCallback(
- final GnssNavigationMessageEvent.Callback callback, Handler handler) {
- GnssNavigationMessage.Callback bridge = new GnssNavigationMessage.Callback() {
- @Override
- public void onGnssNavigationMessageReceived(GnssNavigationMessage message) {
- GnssNavigationMessageEvent event = new GnssNavigationMessageEvent(message);
- callback.onGnssNavigationMessageReceived(event);
- }
-
- @Override
- public void onStatusChanged(int status) {
- callback.onStatusChanged(status);
- }
- };
- mNavigationMessageBridge.put(callback, bridge);
- return mGnssNavigationMessageCallbackTransport.add(bridge, handler);
- }
-
- /**
- * Unregisters a GNSS Navigation Message callback.
- *
- * @param callback a {@link GnssNavigationMessageEvent.Callback} object to remove.
- * @removed
- */
- public void unregisterGnssNavigationMessageCallback(
- GnssNavigationMessageEvent.Callback callback) {
- mGnssNavigationMessageCallbackTransport.remove(
- mNavigationMessageBridge.remove(
- callback));
- }
-
- /**
- * Registers a GNSS Navigation Message callback.
- *
* @param callback a {@link GnssNavigationMessage.Callback} object to register.
* @return {@code true} if the callback was added successfully, {@code false} otherwise.
*/
diff --git a/media/java/android/media/AudioManager.java b/media/java/android/media/AudioManager.java
index 23bb6f9..1d124c5 100644
--- a/media/java/android/media/AudioManager.java
+++ b/media/java/android/media/AudioManager.java
@@ -3482,6 +3482,20 @@
return delay;
}
+ /**
+ * Indicate A2DP device configuration has changed.
+ * @param device Bluetooth device whose configuration has changed.
+ * {@hide}
+ */
+ public void handleBluetoothA2dpDeviceConfigChange(BluetoothDevice device) {
+ IAudioService service = getService();
+ try {
+ service.handleBluetoothA2dpDeviceConfigChange(device);
+ } catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
+ }
+ }
+
/** {@hide} */
public IRingtonePlayer getRingtonePlayer() {
try {
diff --git a/media/java/android/media/AudioManagerInternal.java b/media/java/android/media/AudioManagerInternal.java
index ac59ace..b60dbd5 100644
--- a/media/java/android/media/AudioManagerInternal.java
+++ b/media/java/android/media/AudioManagerInternal.java
@@ -41,8 +41,6 @@
public abstract void setRingerModeInternal(int ringerMode, String caller);
- public abstract int getVolumeControllerUid();
-
public abstract void updateRingerModeAffectedStreamsInternal();
public interface RingerModeDelegate {
diff --git a/media/java/android/media/AudioPlaybackConfiguration.java b/media/java/android/media/AudioPlaybackConfiguration.java
index e610f0b..147c5df 100644
--- a/media/java/android/media/AudioPlaybackConfiguration.java
+++ b/media/java/android/media/AudioPlaybackConfiguration.java
@@ -38,6 +38,8 @@
/** @hide */
public final static int PLAYER_PIID_INVALID = -1;
+ /** @hide */
+ public final static int PLAYER_UPID_INVALID = -1;
// information about the implementation
/**
@@ -159,11 +161,11 @@
/**
* @hide
*/
- public AudioPlaybackConfiguration(PlayerBase.PlayerIdCard pic) {
- mPlayerIId = pic.mPIId;
+ public AudioPlaybackConfiguration(PlayerBase.PlayerIdCard pic, int piid, int uid, int pid) {
+ mPlayerIId = piid;
mPlayerType = pic.mPlayerType;
- mClientUid = pic.mClientUid;
- mClientPid = pic.mClientPid;
+ mClientUid = uid;
+ mClientPid = pid;
mPlayerState = PLAYER_STATE_IDLE;
mPlayerAttr = pic.mAttributes;
}
@@ -187,8 +189,8 @@
.build();
// anonymized data
anonymCopy.mPlayerType = PLAYER_TYPE_UNKNOWN;
- anonymCopy.mClientUid = 0;
- anonymCopy.mClientPid = 0;
+ anonymCopy.mClientUid = PLAYER_UPID_INVALID;
+ anonymCopy.mClientPid = PLAYER_UPID_INVALID;
return anonymCopy;
}
diff --git a/media/java/android/media/AudioSystem.java b/media/java/android/media/AudioSystem.java
index 17928995..b44a710 100644
--- a/media/java/android/media/AudioSystem.java
+++ b/media/java/android/media/AudioSystem.java
@@ -689,6 +689,9 @@
public static native int setDeviceConnectionState(int device, int state,
String device_address, String device_name);
public static native int getDeviceConnectionState(int device, String device_address);
+ public static native int handleDeviceConfigChange(int device,
+ String device_address,
+ String device_name);
public static native int setPhoneState(int state);
public static native int setForceUse(int usage, int config);
public static native int getForceUse(int usage);
diff --git a/media/java/android/media/ExternalRingtonesCursorWrapper.java b/media/java/android/media/ExternalRingtonesCursorWrapper.java
new file mode 100644
index 0000000..dd4c77a
--- /dev/null
+++ b/media/java/android/media/ExternalRingtonesCursorWrapper.java
@@ -0,0 +1,46 @@
+/*
+ * Copyright (C) 2016 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 android.media;
+
+import android.content.ContentProvider;
+import android.database.Cursor;
+import android.database.CursorWrapper;
+import android.net.Uri;
+
+/**
+ * Cursor that adds the user id to fetched URIs. This is especially useful for {@link getCursor} as
+ * a managed profile should also list its parent's ringtones
+ *
+ * @hide
+ */
+public class ExternalRingtonesCursorWrapper extends CursorWrapper {
+
+ private int mUserId;
+
+ public ExternalRingtonesCursorWrapper(Cursor cursor, int userId) {
+ super(cursor);
+ mUserId = userId;
+ }
+
+ public String getString(int index) {
+ String result = super.getString(index);
+ if (index == RingtoneManager.URI_COLUMN_INDEX) {
+ result = ContentProvider.maybeAddUserId(Uri.parse(result), mUserId).toString();
+ }
+ return result;
+ }
+}
diff --git a/media/java/android/media/IAudioService.aidl b/media/java/android/media/IAudioService.aidl
index d53c937..432e77c 100644
--- a/media/java/android/media/IAudioService.aidl
+++ b/media/java/android/media/IAudioService.aidl
@@ -46,7 +46,7 @@
// frameworks/native/include/audiomanager/IAudioManager.h must be updated to match the order
// in this file.
//
- // When a method's argument list is changed, BnAudioManager's corresponding serialization code
+ // When a method's argument list is changed, BpAudioManager's corresponding serialization code
// (if any) in frameworks/native/services/audiomanager/IAudioManager.cpp must be updated.
oneway void adjustSuggestedStreamVolume(int direction, int suggestedStreamType, int flags,
@@ -143,6 +143,8 @@
int setBluetoothA2dpDeviceConnectionState(in BluetoothDevice device, int state, int profile);
+ void handleBluetoothA2dpDeviceConfigChange(in BluetoothDevice device);
+
AudioRoutesInfo startWatchingRoutes(in IAudioRoutesObserver observer);
boolean isCameraSoundForced();
@@ -182,7 +184,7 @@
List<AudioPlaybackConfiguration> getActivePlaybackConfigurations();
- oneway void trackPlayer(in PlayerBase.PlayerIdCard pic);
+ int trackPlayer(in PlayerBase.PlayerIdCard pic);
oneway void playerAttributes(in int piid, in AudioAttributes attr);
diff --git a/media/java/android/media/MediaPlayer.java b/media/java/android/media/MediaPlayer.java
index 77a0fbd..500556a 100644
--- a/media/java/android/media/MediaPlayer.java
+++ b/media/java/android/media/MediaPlayer.java
@@ -2291,7 +2291,7 @@
* {@link #setSubtitleAnchor(SubtitleController, Anchor)} (e.g. {@link VideoView} provides one).
*/
private synchronized void setSubtitleAnchor() {
- if (mSubtitleController == null) {
+ if ((mSubtitleController == null) && (ActivityThread.currentApplication() != null)) {
final HandlerThread thread = new HandlerThread("SetSubtitleAnchorThread");
thread.start();
Handler handler = new Handler(thread.getLooper());
@@ -2442,10 +2442,7 @@
}
private void scanInternalSubtitleTracks() {
- if (mSubtitleController == null) {
- Log.d(TAG, "setSubtitleAnchor in MediaPlayer");
- setSubtitleAnchor();
- }
+ setSubtitleAnchor();
populateInbandTracks();
diff --git a/media/java/android/media/PlayerBase.java b/media/java/android/media/PlayerBase.java
index 49c89a3..4eacb38 100644
--- a/media/java/android/media/PlayerBase.java
+++ b/media/java/android/media/PlayerBase.java
@@ -78,7 +78,7 @@
}
mAttributes = attr;
mImplType = implType;
- mPlayerIId = AudioSystem.newAudioPlayerId();
+ int newPiid = AudioPlaybackConfiguration.PLAYER_PIID_INVALID;
IBinder b = ServiceManager.getService(Context.APP_OPS_SERVICE);
mAppOps = IAppOpsService.Stub.asInterface(b);
// initialize mHasAppOpsPlayAudio
@@ -100,10 +100,11 @@
mHasAppOpsPlayAudio = false;
}
try {
- getService().trackPlayer(new PlayerIdCard(mPlayerIId, mImplType, mAttributes));
+ newPiid = getService().trackPlayer(new PlayerIdCard(mImplType, mAttributes));
} catch (RemoteException e) {
Log.e(TAG, "Error talking to audio service, player will not be tracked", e);
}
+ mPlayerIId = newPiid;
}
@@ -311,26 +312,20 @@
* Class holding all the information about a player that needs to be known at registration time
*/
public static class PlayerIdCard implements Parcelable {
- public final int mPIId;
public final int mPlayerType;
- public final int mClientUid;
- public final int mClientPid;
public final static int AUDIO_ATTRIBUTES_NONE = 0;
public final static int AUDIO_ATTRIBUTES_DEFINED = 1;
public final AudioAttributes mAttributes;
- PlayerIdCard(int piid, int type, @NonNull AudioAttributes attr) {
- mPIId = piid;
+ PlayerIdCard(int type, @NonNull AudioAttributes attr) {
mPlayerType = type;
- mClientUid = Binder.getCallingUid();
- mClientPid = Binder.getCallingPid();
mAttributes = attr;
}
@Override
public int hashCode() {
- return Objects.hash(mPIId, mPlayerType);
+ return Objects.hash(mPlayerType);
}
@Override
@@ -340,10 +335,7 @@
@Override
public void writeToParcel(Parcel dest, int flags) {
- dest.writeInt(mPIId);
dest.writeInt(mPlayerType);
- dest.writeInt(mClientUid);
- dest.writeInt(mClientPid);
mAttributes.writeToParcel(dest, 0);
}
@@ -363,10 +355,7 @@
};
private PlayerIdCard(Parcel in) {
- mPIId = in.readInt();
mPlayerType = in.readInt();
- mClientUid = in.readInt();
- mClientPid = in.readInt();
mAttributes = AudioAttributes.CREATOR.createFromParcel(in);
}
@@ -377,7 +366,8 @@
PlayerIdCard that = (PlayerIdCard) o;
- return (mPIId == that.mPIId);
+ // FIXME change to the binder player interface once supported as a member
+ return ((mPlayerType == that.mPlayerType) && mAttributes.equals(that.mAttributes));
}
}
diff --git a/media/java/android/media/RingtoneManager.java b/media/java/android/media/RingtoneManager.java
index de9f020..7614999 100644
--- a/media/java/android/media/RingtoneManager.java
+++ b/media/java/android/media/RingtoneManager.java
@@ -17,9 +17,11 @@
package android.media;
import android.Manifest;
+import android.annotation.NonNull;
import android.annotation.RequiresPermission;
import android.annotation.SdkConstant;
import android.annotation.SdkConstant.SdkConstantType;
+import android.annotation.WorkerThread;
import android.app.Activity;
import android.content.ContentProvider;
import android.content.ContentResolver;
@@ -28,6 +30,7 @@
import android.content.pm.PackageManager;
import android.content.pm.UserInfo;
import android.database.Cursor;
+import android.media.MediaScannerConnection.MediaScannerConnectionClient;
import android.net.Uri;
import android.os.Environment;
import android.os.ParcelFileDescriptor;
@@ -43,11 +46,16 @@
import libcore.io.Streams;
+import java.io.Closeable;
+import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
+import java.io.FileNotFoundException;
+import java.io.FileOutputStream;
import java.util.ArrayList;
import java.util.List;
+import java.util.concurrent.LinkedBlockingQueue;
import static android.content.ContentProvider.maybeAddUserId;
import static android.content.pm.PackageManager.NameNotFoundException;
@@ -253,6 +261,8 @@
private boolean mStopPreviousRingtone = true;
private Ringtone mPreviousRingtone;
+ private boolean mIncludeParentRingtones;
+
/**
* Constructs a RingtoneManager. This constructor is recommended as its
* constructed instance manages cursor(s).
@@ -260,9 +270,24 @@
* @param activity The activity used to get a managed cursor.
*/
public RingtoneManager(Activity activity) {
+ this(activity, /* includeParentRingtones */ false);
+ }
+
+ /**
+ * Constructs a RingtoneManager. This constructor is recommended if there's the need to also
+ * list ringtones from the user's parent.
+ *
+ * @param activity The activity used to get a managed cursor.
+ * @param includeParentRingtones if true, this ringtone manager's cursor will also retrieve
+ * ringtones from the parent of the user specified in the given activity
+ *
+ * @hide
+ */
+ public RingtoneManager(Activity activity, boolean includeParentRingtones) {
mActivity = activity;
mContext = activity;
setType(mType);
+ mIncludeParentRingtones = includeParentRingtones;
}
/**
@@ -273,9 +298,23 @@
* @param context The context to used to get a cursor.
*/
public RingtoneManager(Context context) {
+ this(context, /* includeParentRingtones */ false);
+ }
+
+ /**
+ * Constructs a RingtoneManager.
+ *
+ * @param context The context to used to get a cursor.
+ * @param includeParentRingtones if true, this ringtone manager's cursor will also retrieve
+ * ringtones from the parent of the user specified in the given context
+ *
+ * @hide
+ */
+ public RingtoneManager(Context context, boolean includeParentRingtones) {
mActivity = null;
mContext = context;
setType(mType);
+ mIncludeParentRingtones = includeParentRingtones;
}
/**
@@ -395,14 +434,38 @@
if (mCursor != null && mCursor.requery()) {
return mCursor;
}
-
- final Cursor internalCursor = getInternalRingtones();
- final Cursor mediaCursor = getMediaRingtones();
-
- return mCursor = new SortCursor(new Cursor[] { internalCursor, mediaCursor },
+
+ ArrayList<Cursor> ringtoneCursors = new ArrayList<Cursor>();
+ ringtoneCursors.add(getInternalRingtones());
+ ringtoneCursors.add(getMediaRingtones());
+
+ if (mIncludeParentRingtones) {
+ Cursor parentRingtonesCursor = getParentProfileRingtones();
+ if (parentRingtonesCursor != null) {
+ ringtoneCursors.add(parentRingtonesCursor);
+ }
+ }
+
+ return mCursor = new SortCursor(ringtoneCursors.toArray(new Cursor[ringtoneCursors.size()]),
MediaStore.Audio.Media.DEFAULT_SORT_ORDER);
}
+ private Cursor getParentProfileRingtones() {
+ final UserManager um = UserManager.get(mContext);
+ final UserInfo parentInfo = um.getProfileParent(mContext.getUserId());
+ if (parentInfo != null && parentInfo.id != mContext.getUserId()) {
+ final Context parentContext = createPackageContextAsUser(mContext, parentInfo.id);
+ if (parentContext != null) {
+ // We don't need to re-add the internal ringtones for the work profile since
+ // they are the same as the personal profile. We just need the external
+ // ringtones.
+ return new ExternalRingtonesCursorWrapper(getMediaRingtones(parentContext),
+ parentInfo.id);
+ }
+ }
+ return null;
+ }
+
/**
* Gets a {@link Ringtone} for the ringtone at the given position in the
* {@link Cursor}.
@@ -434,7 +497,35 @@
return getUriFromCursor(mCursor);
}
-
+
+ /**
+ * Queries the database for the Uri to a ringtone in a specific path (the ringtone has to have
+ * been scanned before)
+ *
+ * @param context Context used to query the database
+ * @param path Path to the ringtone file
+ * @return Uri of the ringtone, null if something fails in the query or the ringtone doesn't
+ * exist
+ *
+ * @hide
+ */
+ private static Uri getExistingRingtoneUriFromPath(Context context, String path) {
+ final String[] proj = {MediaStore.Audio.Media._ID};
+ final String[] selectionArgs = {path};
+ try (final Cursor cursor = context.getContentResolver().query(
+ MediaStore.Audio.Media.EXTERNAL_CONTENT_URI, proj,
+ MediaStore.Audio.Media.DATA + "=? ", selectionArgs, /* sortOrder */ null)) {
+ if (cursor == null || !cursor.moveToFirst()) {
+ return null;
+ }
+ final int id = cursor.getInt(cursor.getColumnIndex(MediaStore.MediaColumns._ID));
+ if (id == -1) {
+ return null;
+ }
+ return Uri.withAppendedPath(MediaStore.Audio.Media.EXTERNAL_CONTENT_URI, "" + id);
+ }
+ }
+
private static Uri getUriFromCursor(Cursor cursor) {
return ContentUris.withAppendedId(Uri.parse(cursor.getString(URI_COLUMN_INDEX)), cursor
.getLong(ID_COLUMN_INDEX));
@@ -523,7 +614,11 @@
}
private Cursor getMediaRingtones() {
- if (PackageManager.PERMISSION_GRANTED != mContext.checkPermission(
+ return getMediaRingtones(mContext);
+ }
+
+ private Cursor getMediaRingtones(Context context) {
+ if (PackageManager.PERMISSION_GRANTED != context.checkPermission(
android.Manifest.permission.READ_EXTERNAL_STORAGE,
Process.myPid(), Process.myUid())) {
Log.w(TAG, "No READ_EXTERNAL_STORAGE permission, ignoring ringtones on ext storage");
@@ -537,7 +632,7 @@
? query(
MediaStore.Audio.Media.EXTERNAL_CONTENT_URI, MEDIA_COLUMNS,
constructBooleanTrueWhereClause(mFilterColumns), null,
- MediaStore.Audio.Media.DEFAULT_SORT_ORDER)
+ MediaStore.Audio.Media.DEFAULT_SORT_ORDER, context)
: null;
}
@@ -592,10 +687,19 @@
String selection,
String[] selectionArgs,
String sortOrder) {
+ return query(uri, projection, selection, selectionArgs, sortOrder, mContext);
+ }
+
+ private Cursor query(Uri uri,
+ String[] projection,
+ String selection,
+ String[] selectionArgs,
+ String sortOrder,
+ Context context) {
if (mActivity != null) {
return mActivity.managedQuery(uri, projection, selection, selectionArgs, sortOrder);
} else {
- return mContext.getContentResolver().query(uri, projection, selection, selectionArgs,
+ return context.getContentResolver().query(uri, projection, selection, selectionArgs,
sortOrder);
}
}
@@ -642,7 +746,29 @@
return null;
}
-
+
+ /**
+ * Look up the path for a given {@link Uri} referring to a ringtone sound (TYPE_RINGTONE,
+ * TYPE_NOTIFICATION, or TYPE_ALARM). This is saved in {@link MediaStore.Audio.Media#DATA}.
+ *
+ * @return a {@link File} pointing at the location of the {@param uri} on disk, or {@code null}
+ * if there is no such file.
+ */
+ private File getRingtonePathFromUri(Uri uri) {
+ // Query cursor to get ringtone path
+ final String[] projection = {MediaStore.Audio.Media.DATA};
+ setFilterColumnsList(TYPE_RINGTONE | TYPE_NOTIFICATION | TYPE_ALARM);
+
+ String path = null;
+ try (Cursor cursor = query(uri, projection, constructBooleanTrueWhereClause(mFilterColumns),
+ null, null)) {
+ if (cursor != null && cursor.moveToFirst()) {
+ path = cursor.getString(cursor.getColumnIndex(MediaStore.Audio.Media.DATA));
+ }
+ }
+ return path != null ? new File(path) : null;
+ }
+
/**
* Disables Settings.System.SYNC_PARENT_SOUNDS, copying the parent's ringtones to the current
* profile
@@ -659,17 +785,14 @@
UserManager um = UserManager.get(userContext);
UserInfo parentInfo = um.getProfileParent(userContext.getUserId());
if (parentInfo != null) {
- try {
- Context targetContext = userContext.createPackageContextAsUser(
- userContext.getPackageName(), 0 /* flags */, UserHandle.of(parentInfo.id));
+ final Context targetContext = createPackageContextAsUser(userContext, parentInfo.id);
+ if (targetContext != null) {
for (int ringtoneType : RINGTONE_TYPES) {
Uri ringtoneUri = getActualDefaultRingtoneUri(targetContext, ringtoneType);
// Add user id of parent so that custom ringtones can be read and played
RingtoneManager.setActualDefaultRingtoneUri(userContext, ringtoneType,
maybeAddUserId(ringtoneUri, parentInfo.id));
}
- } catch (NameNotFoundException e) {
- Log.e(TAG, "Unable to create parent context", e);
}
}
}
@@ -749,9 +872,157 @@
}
private static boolean isInternalRingtoneUri(Uri uri) {
- Uri uriWithoutUserId = ContentProvider.getUriWithoutUserId(uri);
- return uriWithoutUserId == null ? false : uriWithoutUserId.toString()
- .startsWith(MediaStore.Audio.Media.INTERNAL_CONTENT_URI.toString());
+ return isRingtoneUriInStorage(uri, MediaStore.Audio.Media.INTERNAL_CONTENT_URI);
+ }
+
+ private static boolean isExternalRingtoneUri(Uri uri) {
+ return isRingtoneUriInStorage(uri, MediaStore.Audio.Media.EXTERNAL_CONTENT_URI);
+ }
+
+ private static boolean isRingtoneUriInStorage(Uri ringtone, Uri storage) {
+ Uri uriWithoutUserId = ContentProvider.getUriWithoutUserId(ringtone);
+ return uriWithoutUserId == null ? false
+ : uriWithoutUserId.toString().startsWith(storage.toString());
+ }
+
+ /** @hide */
+ public boolean isCustomRingtone(Uri uri) {
+ if(!isExternalRingtoneUri(uri)) {
+ // A custom ringtone would be in the external storage
+ return false;
+ }
+
+ final File ringtoneFile = (uri == null ? null : getRingtonePathFromUri(uri));
+ final File parent = (ringtoneFile == null ? null : ringtoneFile.getParentFile());
+ if (parent == null) {
+ return false;
+ }
+
+ final String[] directories = {
+ Environment.DIRECTORY_RINGTONES,
+ Environment.DIRECTORY_NOTIFICATIONS,
+ Environment.DIRECTORY_ALARMS
+ };
+ for (final String directory : directories) {
+ if (parent.equals(Environment.getExternalStoragePublicDirectory(directory))) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ /**
+ * Adds an audio file to the list of ringtones.
+ *
+ * After making sure the given file is an audio file, copies the file to the ringtone storage,
+ * and asks the {@link android.media.MediaScanner} to scan that file. This call will block until
+ * the scan is completed.
+ *
+ * The directory where the copied file is stored is the directory that matches the ringtone's
+ * type, which is one of: {@link android.is.Environment#DIRECTORY_RINGTONES};
+ * {@link android.is.Environment#DIRECTORY_NOTIFICATIONS};
+ * {@link android.is.Environment#DIRECTORY_ALARMS}.
+ *
+ * This does not allow modifying the type of an existing ringtone file. To change type, use the
+ * APIs in {@link android.content.ContentResolver} to update the corresponding columns.
+ *
+ * @param fileUri Uri of the file to be added as ringtone. Must be a media file.
+ * @param type The type of the ringtone to be added. Must be one of {@link #TYPE_RINGTONE},
+ * {@link #TYPE_NOTIFICATION}, or {@link #TYPE_ALARM}.
+ *
+ * @return The Uri of the installed ringtone, which may be the Uri of {@param fileUri} if it is
+ * already in ringtone storage.
+ *
+ * @throws FileNotFoundexception if an appropriate unique filename to save the new ringtone file
+ * as cannot be found, for example if the unique name is too long.
+ * @throws IllegalArgumentException if {@param fileUri} does not point to an existing audio
+ * file, or if the {@param type} is not one of the accepted ringtone types.
+ * @throws IOException if the audio file failed to copy to ringtone storage; for example, if
+ * external storage was not available, or if the file was copied but the media scanner
+ * did not recognize it as a ringtone.
+ *
+ * @hide
+ */
+ @WorkerThread
+ public Uri addCustomExternalRingtone(@NonNull final Uri fileUri, final int type)
+ throws FileNotFoundException, IllegalArgumentException, IOException {
+ if (!Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)) {
+ throw new IOException("External storage is not mounted. Unable to install ringtones.");
+ }
+
+ // Sanity-check: are we actually being asked to install an audio file?
+ final String mimeType = mContext.getContentResolver().getType(fileUri);
+ if(mimeType == null || !mimeType.startsWith("audio/")) {
+ throw new IllegalArgumentException("Ringtone file must have MIME type \"audio/*\"."
+ + " Given file has MIME type \"" + mimeType + "\"");
+ }
+
+ // Choose a directory to save the ringtone. Only one type of installation at a time is
+ // allowed. Throws IllegalArgumentException if anything else is given.
+ final String subdirectory = getExternalDirectoryForType(type);
+
+ // Find a filename. Throws FileNotFoundException if none can be found.
+ final File outFile = Utils.getUniqueExternalFile(mContext, subdirectory,
+ Utils.getFileDisplayNameFromUri(mContext, fileUri), mimeType);
+
+ // Copy contents to external ringtone storage. Throws IOException if the copy fails.
+ try (final InputStream input = mContext.getContentResolver().openInputStream(fileUri);
+ final OutputStream output = new FileOutputStream(outFile)) {
+ Streams.copy(input, output);
+ }
+
+ // Tell MediaScanner about the new file. Wait for it to assign a {@link Uri}.
+ try (NewRingtoneScanner scanner = new NewRingtoneScanner(outFile)) {
+ return scanner.take();
+ } catch (InterruptedException e) {
+ throw new IOException("Audio file failed to scan as a ringtone", e);
+ }
+ }
+
+ private static final String getExternalDirectoryForType(final int type) {
+ switch (type) {
+ case TYPE_RINGTONE:
+ return Environment.DIRECTORY_RINGTONES;
+ case TYPE_NOTIFICATION:
+ return Environment.DIRECTORY_NOTIFICATIONS;
+ case TYPE_ALARM:
+ return Environment.DIRECTORY_ALARMS;
+ default:
+ throw new IllegalArgumentException("Unsupported ringtone type: " + type);
+ }
+ }
+
+ /**
+ * Deletes the actual file in the Uri and its ringtone database entry if the Uri's actual path
+ * is in one of the following directories: {@link android.is.Environment#DIRECTORY_RINGTONES},
+ * {@link android.is.Environment#DIRECTORY_NOTIFICATIONS} or
+ * {@link android.is.Environment#DIRECTORY_ALARMS}.
+ *
+ * The given Uri must be a ringtone Content Uri.
+ *
+ * Keep in mind that if the ringtone deleted is a default ringtone, it will still live in the
+ * ringtone cache file so it will be playable from there. However, if an app uses the ringtone
+ * as its own ringtone, it won't be played, which is the same behavior observed for 3rd party
+ * custom ringtones.
+ *
+ * @hide
+ */
+ public boolean deleteExternalRingtone(Uri uri) {
+ if(!isCustomRingtone(uri)) {
+ // We can only delete custom ringtones in the default ringtone storages
+ return false;
+ }
+
+ // Save the path of the ringtone before deleting from our content resolver.
+ final File ringtoneFile = getRingtonePathFromUri(uri);
+ try {
+ if (ringtoneFile != null && mContext.getContentResolver().delete(uri, null, null) > 0) {
+ return ringtoneFile.delete();
+ }
+ } catch (SecurityException e) {
+ Log.d(TAG, "Unable to delete custom ringtone", e);
+ }
+ return false;
}
/**
@@ -860,5 +1131,67 @@
return null;
}
}
-
+
+ /**
+ * Creates a {@link android.media.MediaScannerConnection} to scan a ringtone file and add its
+ * information to the internal database.
+ *
+ * It uses a {@link java.util.concurrent.LinkedBlockingQueue} so that the caller can block until
+ * the scan is completed.
+ */
+ private class NewRingtoneScanner implements Closeable, MediaScannerConnectionClient {
+ private MediaScannerConnection mMediaScannerConnection;
+ private File mFile;
+ private LinkedBlockingQueue<Uri> mQueue = new LinkedBlockingQueue<>(1);
+
+ public NewRingtoneScanner(File file) {
+ mFile = file;
+ mMediaScannerConnection = new MediaScannerConnection(mContext, this);
+ mMediaScannerConnection.connect();
+ }
+
+ @Override
+ public void close() {
+ mMediaScannerConnection.disconnect();
+ }
+
+ @Override
+ public void onMediaScannerConnected() {
+ mMediaScannerConnection.scanFile(mFile.getAbsolutePath(), null);
+ }
+
+ @Override
+ public void onScanCompleted(String path, Uri uri) {
+ if (uri == null) {
+ // There was some issue with scanning. Delete the copied file so it is not oprhaned.
+ mFile.delete();
+ return;
+ }
+ try {
+ mQueue.put(uri);
+ } catch (InterruptedException e) {
+ Log.e(TAG, "Unable to put new ringtone Uri in queue", e);
+ }
+ }
+
+ public Uri take() throws InterruptedException {
+ return mQueue.take();
+ }
+ }
+
+ /**
+ * Attempts to create a context for the given user.
+ *
+ * @return created context, or null if package does not exist
+ * @hide
+ */
+ private static Context createPackageContextAsUser(Context context, int userId) {
+ try {
+ return context.createPackageContextAsUser(context.getPackageName(), 0 /* flags */,
+ UserHandle.of(userId));
+ } catch (NameNotFoundException e) {
+ Log.e(TAG, "Unable to create package context", e);
+ return null;
+ }
+ }
}
diff --git a/media/java/android/media/Utils.java b/media/java/android/media/Utils.java
index 35b083e..5b62f16 100644
--- a/media/java/android/media/Utils.java
+++ b/media/java/android/media/Utils.java
@@ -16,12 +16,21 @@
package android.media;
+import android.content.Context;
+import android.content.ContentResolver;
+import android.database.Cursor;
+import android.net.Uri;
+import android.os.Environment;
+import android.os.FileUtils;
+import android.provider.OpenableColumns;
import android.util.Log;
import android.util.Pair;
import android.util.Range;
import android.util.Rational;
import android.util.Size;
+import java.io.File;
+import java.io.FileNotFoundException;
import java.util.Arrays;
import java.util.Comparator;
import java.util.Vector;
@@ -307,4 +316,66 @@
Log.w(TAG, "could not parse size range '" + o + "'");
return null;
}
+
+ /**
+ * Creates a unique file in the specified external storage with the desired name. If the name is
+ * taken, the new file's name will have '(%d)' to avoid overwriting files.
+ *
+ * @param context {@link Context} to query the file name from.
+ * @param subdirectory One of the directories specified in {@link android.os.Environment}
+ * @param fileName desired name for the file.
+ * @param mimeType MIME type of the file to create.
+ * @return the File object in the storage, or null if an error occurs.
+ */
+ public static File getUniqueExternalFile(Context context, String subdirectory, String fileName,
+ String mimeType) {
+ File externalStorage = Environment.getExternalStoragePublicDirectory(subdirectory);
+ // Make sure the storage subdirectory exists
+ externalStorage.mkdirs();
+
+ File outFile = null;
+ try {
+ // Ensure the file has a unique name, as to not override any existing file
+ outFile = FileUtils.buildUniqueFile(externalStorage, mimeType, fileName);
+ } catch (FileNotFoundException e) {
+ // This might also be reached if the number of repeated files gets too high
+ Log.e(TAG, "Unable to get a unique file name: " + e);
+ return null;
+ }
+ return outFile;
+ }
+
+ /**
+ * Returns a file's display name from its {@link android.content.ContentResolver.SCHEME_FILE}
+ * or {@link android.content.ContentResolver.SCHEME_CONTENT} Uri. The display name of a file
+ * includes its extension.
+ *
+ * @param context Context trying to resolve the file's display name.
+ * @param uri Uri of the file.
+ * @return the file's display name, or the uri's string if something fails or the uri isn't in
+ * the schemes specified above.
+ */
+ static String getFileDisplayNameFromUri(Context context, Uri uri) {
+ String scheme = uri.getScheme();
+
+ if (ContentResolver.SCHEME_FILE.equals(scheme)) {
+ return uri.getLastPathSegment();
+ } else if (ContentResolver.SCHEME_CONTENT.equals(scheme)) {
+ // We need to query the ContentResolver to get the actual file name as the Uri masks it.
+ // This means we want the name used for display purposes only.
+ String[] proj = {
+ OpenableColumns.DISPLAY_NAME
+ };
+ try (Cursor cursor = context.getContentResolver().query(uri, proj, null, null, null)) {
+ if (cursor != null && cursor.getCount() != 0) {
+ cursor.moveToFirst();
+ return cursor.getString(cursor.getColumnIndex(OpenableColumns.DISPLAY_NAME));
+ }
+ }
+ }
+
+ // This will only happen if the Uri isn't either SCHEME_CONTENT or SCHEME_FILE, so we assume
+ // it already represents the file's name.
+ return uri.toString();
+ }
}
diff --git a/native/android/Android.bp b/native/android/Android.bp
index 33c9655..5843637 100644
--- a/native/android/Android.bp
+++ b/native/android/Android.bp
@@ -17,4 +17,5 @@
name: "libandroid.ndk",
symbol_file: "libandroid.map.txt",
first_version: "9",
+ unversioned_until: "current",
}
diff --git a/native/graphics/jni/Android.bp b/native/graphics/jni/Android.bp
index e09b0b4..17feb53 100644
--- a/native/graphics/jni/Android.bp
+++ b/native/graphics/jni/Android.bp
@@ -17,4 +17,5 @@
name: "libjnigraphics.ndk",
symbol_file: "libjnigraphics.map.txt",
first_version: "9",
+ unversioned_until: "current",
}
diff --git a/packages/SettingsLib/res/layout/drawer_category.xml b/packages/SettingsLib/res/layout/drawer_category.xml
index 582821b..72cfddb 100644
--- a/packages/SettingsLib/res/layout/drawer_category.xml
+++ b/packages/SettingsLib/res/layout/drawer_category.xml
@@ -26,13 +26,13 @@
android:background="?android:attr/listDivider" />
<TextView
+ style="@style/TextAppearanceSmall"
android:id="@android:id/title"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:minHeight="48dp"
android:paddingTop="16dp"
android:paddingBottom="16dp"
- android:paddingStart="16dp"
- android:textAppearance="?android:attr/textAppearanceSmall" />
+ android:paddingStart="16dp" />
</LinearLayout>
diff --git a/packages/SettingsLib/res/layout/drawer_item.xml b/packages/SettingsLib/res/layout/drawer_item.xml
index e1f1ae5..d492ddf 100644
--- a/packages/SettingsLib/res/layout/drawer_item.xml
+++ b/packages/SettingsLib/res/layout/drawer_item.xml
@@ -23,19 +23,22 @@
<ImageView
android:id="@android:id/icon"
- android:layout_width="72dp"
- android:layout_height="24dp"
+ android:layout_width="@dimen/drawer_icon_size"
+ android:layout_height="@dimen/drawer_icon_size"
+ android:layout_marginStart="@dimen/drawer_icon_margin"
+ android:layout_marginEnd="@dimen/drawer_icon_margin"
+ android:layout_marginTop="@dimen/drawer_item_top_bottom_margin"
+ android:layout_marginBottom="@dimen/drawer_item_top_bottom_margin"
+ android:scaleType="fitCenter"
android:layout_gravity="center_vertical"
- android:tint="?android:attr/colorAccent"
- android:paddingStart="16dp"
- android:paddingEnd="32dp" />
+ android:tint="?android:attr/colorAccent"/>
<TextView
+ android:textAppearance="@style/TextAppearanceMedium"
android:id="@android:id/title"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical"
- android:textColor="?android:attr/colorControlNormal"
- android:textAppearance="?android:attr/textAppearanceMedium" />
+ android:textColor="?android:attr/colorControlNormal" />
</LinearLayout>
diff --git a/packages/SettingsLib/res/layout/drawer_spacer.xml b/packages/SettingsLib/res/layout/drawer_spacer.xml
index ee1835d..98120cf 100644
--- a/packages/SettingsLib/res/layout/drawer_spacer.xml
+++ b/packages/SettingsLib/res/layout/drawer_spacer.xml
@@ -17,4 +17,4 @@
xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/spacer"
android:layout_width="match_parent"
- android:layout_height="32dp" />
+ android:layout_height="@dimen/drawer_spacer_height" />
diff --git a/packages/SettingsLib/res/layout/settings_with_drawer.xml b/packages/SettingsLib/res/layout/settings_with_drawer.xml
index abe310a..24a5422 100644
--- a/packages/SettingsLib/res/layout/settings_with_drawer.xml
+++ b/packages/SettingsLib/res/layout/settings_with_drawer.xml
@@ -17,34 +17,30 @@
xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/drawer_layout"
android:layout_width="match_parent"
- android:layout_height="match_parent"
- android:background="?android:attr/statusBarColor">
+ android:layout_height="match_parent">
<!-- The main content view -->
<LinearLayout
android:id="@+id/content_parent"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
- android:fitsSystemWindows="true" >
+ android:fitsSystemWindows="true">
<FrameLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
- style="?android:attr/actionBarStyle">
+ android:theme="?android:attr/actionBarTheme">
<Toolbar
- xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/action_bar"
+ style="?android:attr/actionBarStyle"
android:layout_width="match_parent"
android:layout_height="wrap_content"
- android:navigationContentDescription="@*android:string/action_bar_up_description"
- android:theme="?android:attr/actionBarTheme"
- style="?android:attr/toolbarStyle"
- android:background="?android:attr/colorPrimary" />
+ android:navigationContentDescription="@*android:string/action_bar_up_description"/>
</FrameLayout>
<FrameLayout
android:id="@+id/content_header_container"
+ style="?android:attr/actionBarStyle"
android:layout_width="match_parent"
- android:layout_height="wrap_content"
- style="?android:attr/actionBarStyle" />
+ android:layout_height="wrap_content"/>
<FrameLayout
android:id="@+id/content_frame"
android:layout_width="match_parent"
@@ -53,7 +49,7 @@
</LinearLayout>
<!-- The navigation drawer -->
<ListView android:id="@+id/left_drawer"
- android:layout_width="300dp"
+ android:layout_width="@dimen/drawer_width"
android:layout_height="match_parent"
android:layout_gravity="start"
android:choiceMode="singleChoice"
diff --git a/packages/SettingsLib/res/values-af/arrays.xml b/packages/SettingsLib/res/values-af/arrays.xml
index c86eb17..4d10f49 100644
--- a/packages/SettingsLib/res/values-af/arrays.xml
+++ b/packages/SettingsLib/res/values-af/arrays.xml
@@ -58,6 +58,46 @@
<item msgid="3878793616631049349">"Gebruik HDCP-kontrolering net vir DRM-inhoud"</item>
<item msgid="45075631231212732">"Gebruik altyd HDCP-kontrolering"</item>
</string-array>
+ <!-- no translation found for bluetooth_a2dp_codec_titles:0 (1852387125374225729) -->
+ <!-- no translation found for bluetooth_a2dp_codec_titles:1 (7539690996561263909) -->
+ <!-- no translation found for bluetooth_a2dp_codec_titles:2 (4260844283202960798) -->
+ <!-- no translation found for bluetooth_a2dp_codec_titles:3 (7279983368484312990) -->
+ <!-- no translation found for bluetooth_a2dp_codec_titles:4 (2301339338870319651) -->
+ <!-- no translation found for bluetooth_a2dp_codec_summaries:0 (9072025520360316957) -->
+ <!-- no translation found for bluetooth_a2dp_codec_summaries:1 (6898329690939802290) -->
+ <!-- no translation found for bluetooth_a2dp_codec_summaries:2 (1190434429082395888) -->
+ <!-- no translation found for bluetooth_a2dp_codec_summaries:3 (649699003004233053) -->
+ <!-- no translation found for bluetooth_a2dp_codec_summaries:4 (508106435710925399) -->
+ <!-- no translation found for bluetooth_a2dp_codec_sample_rate_titles:0 (7102940318360468759) -->
+ <!-- no translation found for bluetooth_a2dp_codec_sample_rate_titles:1 (8895532488906185219) -->
+ <!-- no translation found for bluetooth_a2dp_codec_sample_rate_titles:2 (2909915718994807056) -->
+ <!-- no translation found for bluetooth_a2dp_codec_sample_rate_titles:3 (3347287377354164611) -->
+ <!-- no translation found for bluetooth_a2dp_codec_sample_rate_titles:4 (1234212100239985373) -->
+ <!-- no translation found for bluetooth_a2dp_codec_sample_rate_summaries:0 (7224433008148687313) -->
+ <!-- no translation found for bluetooth_a2dp_codec_sample_rate_summaries:1 (4482862757811638365) -->
+ <!-- no translation found for bluetooth_a2dp_codec_sample_rate_summaries:2 (354495328188724404) -->
+ <!-- no translation found for bluetooth_a2dp_codec_sample_rate_summaries:3 (7329816882213695083) -->
+ <!-- no translation found for bluetooth_a2dp_codec_sample_rate_summaries:4 (6967397666254430476) -->
+ <!-- no translation found for bluetooth_a2dp_codec_bits_per_sample_titles:0 (6694044160540313386) -->
+ <!-- no translation found for bluetooth_a2dp_codec_bits_per_sample_titles:1 (5618929009984956469) -->
+ <!-- no translation found for bluetooth_a2dp_codec_bits_per_sample_titles:2 (3412640499234627248) -->
+ <!-- no translation found for bluetooth_a2dp_codec_bits_per_sample_titles:3 (121583001492929387) -->
+ <!-- no translation found for bluetooth_a2dp_codec_bits_per_sample_summaries:0 (5091076677792306320) -->
+ <!-- no translation found for bluetooth_a2dp_codec_bits_per_sample_summaries:1 (4726688794884191540) -->
+ <!-- no translation found for bluetooth_a2dp_codec_bits_per_sample_summaries:2 (305344756485516870) -->
+ <!-- no translation found for bluetooth_a2dp_codec_bits_per_sample_summaries:3 (244568657919675099) -->
+ <!-- no translation found for bluetooth_a2dp_codec_channel_mode_titles:0 (13423709606339855) -->
+ <!-- no translation found for bluetooth_a2dp_codec_channel_mode_titles:1 (4106832974775067314) -->
+ <!-- no translation found for bluetooth_a2dp_codec_channel_mode_titles:2 (5571632958424639155) -->
+ <!-- no translation found for bluetooth_a2dp_codec_channel_mode_summaries:0 (8128478683963250130) -->
+ <!-- no translation found for bluetooth_a2dp_codec_channel_mode_summaries:1 (8900559293912978337) -->
+ <!-- no translation found for bluetooth_a2dp_codec_channel_mode_summaries:2 (8883739882299884241) -->
+ <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_titles:0 (2944889121850394020) -->
+ <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_titles:1 (138837449700903545) -->
+ <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_titles:2 (4777177307869441982) -->
+ <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_summaries:0 (172302906231378902) -->
+ <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_summaries:1 (9091111147684472529) -->
+ <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_summaries:2 (3367904477834831032) -->
<string-array name="select_logd_size_titles">
<item msgid="8665206199209698501">"Af"</item>
<item msgid="1593289376502312923">"64 K"</item>
diff --git a/packages/SettingsLib/res/values-af/strings.xml b/packages/SettingsLib/res/values-af/strings.xml
index fcda1d1..2e2aee5 100644
--- a/packages/SettingsLib/res/values-af/strings.xml
+++ b/packages/SettingsLib/res/values-af/strings.xml
@@ -170,6 +170,26 @@
<string name="wifi_allow_scan_with_traffic" msgid="3601853081178265786">"Laat altyd Wi-Fi-swerfskanderings toe"</string>
<string name="mobile_data_always_on" msgid="7745605759775320362">"Sellulêre data altyd aktief"</string>
<string name="bluetooth_disable_absolute_volume" msgid="2660673801947898809">"Deaktiveer absolute volume"</string>
+ <!-- no translation found for bluetooth_select_a2dp_codec_type (90597356942154882) -->
+ <skip />
+ <!-- no translation found for bluetooth_select_a2dp_codec_type_dialog_title (6470824182074383881) -->
+ <skip />
+ <!-- no translation found for bluetooth_select_a2dp_codec_sample_rate (4788245703824623062) -->
+ <skip />
+ <!-- no translation found for bluetooth_select_a2dp_codec_sample_rate_dialog_title (4263851572248033749) -->
+ <skip />
+ <!-- no translation found for bluetooth_select_a2dp_codec_bits_per_sample (2099645202720164141) -->
+ <skip />
+ <!-- no translation found for bluetooth_select_a2dp_codec_bits_per_sample_dialog_title (2096170505745650345) -->
+ <skip />
+ <!-- no translation found for bluetooth_select_a2dp_codec_channel_mode (884855779449390540) -->
+ <skip />
+ <!-- no translation found for bluetooth_select_a2dp_codec_channel_mode_dialog_title (4073812880900816325) -->
+ <skip />
+ <!-- no translation found for bluetooth_select_a2dp_codec_ldac_playback_quality (4846872213548295632) -->
+ <skip />
+ <!-- no translation found for bluetooth_select_a2dp_codec_ldac_playback_quality_dialog_title (3940973633342423717) -->
+ <skip />
<string name="wifi_display_certification_summary" msgid="1155182309166746973">"Wys opsies vir draadlose skermsertifisering"</string>
<string name="wifi_verbose_logging_summary" msgid="6615071616111731958">"Verhoog Wi-Fi-aantekeningvlak, wys per SSID RSSI in Wi‑Fi-kieser"</string>
<string name="wifi_aggressive_handover_summary" msgid="6328455667642570371">"Wanneer dit geaktiveer is, sal Wi-Fi meer aggressief wees om die dataverbinding na selfoon oor te dra wanneer die Wi-Fi-sein swak is"</string>
diff --git a/packages/SettingsLib/res/values-am/arrays.xml b/packages/SettingsLib/res/values-am/arrays.xml
index 0b68d40..1f5c391 100644
--- a/packages/SettingsLib/res/values-am/arrays.xml
+++ b/packages/SettingsLib/res/values-am/arrays.xml
@@ -58,6 +58,46 @@
<item msgid="3878793616631049349">"ለDRM ይዘት ብቻ HDCP ምልከታን ተጠቀም"</item>
<item msgid="45075631231212732">"ሁልጊዜ የHDCP ምልከታ ተጠቀም"</item>
</string-array>
+ <!-- no translation found for bluetooth_a2dp_codec_titles:0 (1852387125374225729) -->
+ <!-- no translation found for bluetooth_a2dp_codec_titles:1 (7539690996561263909) -->
+ <!-- no translation found for bluetooth_a2dp_codec_titles:2 (4260844283202960798) -->
+ <!-- no translation found for bluetooth_a2dp_codec_titles:3 (7279983368484312990) -->
+ <!-- no translation found for bluetooth_a2dp_codec_titles:4 (2301339338870319651) -->
+ <!-- no translation found for bluetooth_a2dp_codec_summaries:0 (9072025520360316957) -->
+ <!-- no translation found for bluetooth_a2dp_codec_summaries:1 (6898329690939802290) -->
+ <!-- no translation found for bluetooth_a2dp_codec_summaries:2 (1190434429082395888) -->
+ <!-- no translation found for bluetooth_a2dp_codec_summaries:3 (649699003004233053) -->
+ <!-- no translation found for bluetooth_a2dp_codec_summaries:4 (508106435710925399) -->
+ <!-- no translation found for bluetooth_a2dp_codec_sample_rate_titles:0 (7102940318360468759) -->
+ <!-- no translation found for bluetooth_a2dp_codec_sample_rate_titles:1 (8895532488906185219) -->
+ <!-- no translation found for bluetooth_a2dp_codec_sample_rate_titles:2 (2909915718994807056) -->
+ <!-- no translation found for bluetooth_a2dp_codec_sample_rate_titles:3 (3347287377354164611) -->
+ <!-- no translation found for bluetooth_a2dp_codec_sample_rate_titles:4 (1234212100239985373) -->
+ <!-- no translation found for bluetooth_a2dp_codec_sample_rate_summaries:0 (7224433008148687313) -->
+ <!-- no translation found for bluetooth_a2dp_codec_sample_rate_summaries:1 (4482862757811638365) -->
+ <!-- no translation found for bluetooth_a2dp_codec_sample_rate_summaries:2 (354495328188724404) -->
+ <!-- no translation found for bluetooth_a2dp_codec_sample_rate_summaries:3 (7329816882213695083) -->
+ <!-- no translation found for bluetooth_a2dp_codec_sample_rate_summaries:4 (6967397666254430476) -->
+ <!-- no translation found for bluetooth_a2dp_codec_bits_per_sample_titles:0 (6694044160540313386) -->
+ <!-- no translation found for bluetooth_a2dp_codec_bits_per_sample_titles:1 (5618929009984956469) -->
+ <!-- no translation found for bluetooth_a2dp_codec_bits_per_sample_titles:2 (3412640499234627248) -->
+ <!-- no translation found for bluetooth_a2dp_codec_bits_per_sample_titles:3 (121583001492929387) -->
+ <!-- no translation found for bluetooth_a2dp_codec_bits_per_sample_summaries:0 (5091076677792306320) -->
+ <!-- no translation found for bluetooth_a2dp_codec_bits_per_sample_summaries:1 (4726688794884191540) -->
+ <!-- no translation found for bluetooth_a2dp_codec_bits_per_sample_summaries:2 (305344756485516870) -->
+ <!-- no translation found for bluetooth_a2dp_codec_bits_per_sample_summaries:3 (244568657919675099) -->
+ <!-- no translation found for bluetooth_a2dp_codec_channel_mode_titles:0 (13423709606339855) -->
+ <!-- no translation found for bluetooth_a2dp_codec_channel_mode_titles:1 (4106832974775067314) -->
+ <!-- no translation found for bluetooth_a2dp_codec_channel_mode_titles:2 (5571632958424639155) -->
+ <!-- no translation found for bluetooth_a2dp_codec_channel_mode_summaries:0 (8128478683963250130) -->
+ <!-- no translation found for bluetooth_a2dp_codec_channel_mode_summaries:1 (8900559293912978337) -->
+ <!-- no translation found for bluetooth_a2dp_codec_channel_mode_summaries:2 (8883739882299884241) -->
+ <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_titles:0 (2944889121850394020) -->
+ <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_titles:1 (138837449700903545) -->
+ <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_titles:2 (4777177307869441982) -->
+ <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_summaries:0 (172302906231378902) -->
+ <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_summaries:1 (9091111147684472529) -->
+ <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_summaries:2 (3367904477834831032) -->
<string-array name="select_logd_size_titles">
<item msgid="8665206199209698501">"ጠፍቷል"</item>
<item msgid="1593289376502312923">"64 ኪባ"</item>
diff --git a/packages/SettingsLib/res/values-am/strings.xml b/packages/SettingsLib/res/values-am/strings.xml
index a281bba..b4ada53 100644
--- a/packages/SettingsLib/res/values-am/strings.xml
+++ b/packages/SettingsLib/res/values-am/strings.xml
@@ -170,6 +170,26 @@
<string name="wifi_allow_scan_with_traffic" msgid="3601853081178265786">"ሁልጊዜ የWi‑Fi ማንቀሳቀስ ቅኝቶችን ይፍቀዱ"</string>
<string name="mobile_data_always_on" msgid="7745605759775320362">"የተንቀስቃሽ ስልክ ውሂብ ሁልጊዜ ንቁ"</string>
<string name="bluetooth_disable_absolute_volume" msgid="2660673801947898809">"ፍጹማዊ ድምፅን አሰናክል"</string>
+ <!-- no translation found for bluetooth_select_a2dp_codec_type (90597356942154882) -->
+ <skip />
+ <!-- no translation found for bluetooth_select_a2dp_codec_type_dialog_title (6470824182074383881) -->
+ <skip />
+ <!-- no translation found for bluetooth_select_a2dp_codec_sample_rate (4788245703824623062) -->
+ <skip />
+ <!-- no translation found for bluetooth_select_a2dp_codec_sample_rate_dialog_title (4263851572248033749) -->
+ <skip />
+ <!-- no translation found for bluetooth_select_a2dp_codec_bits_per_sample (2099645202720164141) -->
+ <skip />
+ <!-- no translation found for bluetooth_select_a2dp_codec_bits_per_sample_dialog_title (2096170505745650345) -->
+ <skip />
+ <!-- no translation found for bluetooth_select_a2dp_codec_channel_mode (884855779449390540) -->
+ <skip />
+ <!-- no translation found for bluetooth_select_a2dp_codec_channel_mode_dialog_title (4073812880900816325) -->
+ <skip />
+ <!-- no translation found for bluetooth_select_a2dp_codec_ldac_playback_quality (4846872213548295632) -->
+ <skip />
+ <!-- no translation found for bluetooth_select_a2dp_codec_ldac_playback_quality_dialog_title (3940973633342423717) -->
+ <skip />
<string name="wifi_display_certification_summary" msgid="1155182309166746973">"የገመድ አልባ ማሳያ እውቅና ማረጋገጫ አማራጮችን አሳይ"</string>
<string name="wifi_verbose_logging_summary" msgid="6615071616111731958">"የWi‑Fi ምዝግብ ማስታወሻ አያያዝ ደረጃ ጨምር፣ በWi‑Fi መምረጫ ውስጥ በአንድ SSID RSSI አሳይ"</string>
<string name="wifi_aggressive_handover_summary" msgid="6328455667642570371">"ሲነቃ የWi‑Fi ምልክት ዝቅተኛ ሲሆን Wi‑Fi የውሂብ ግንኙነት ለተንቀሳቃሽ ማስረከብ ላይ ይበልጥ አስገዳጅ ይሆናል"</string>
diff --git a/packages/SettingsLib/res/values-ar/arrays.xml b/packages/SettingsLib/res/values-ar/arrays.xml
index 3ae8072..ef8eadd 100644
--- a/packages/SettingsLib/res/values-ar/arrays.xml
+++ b/packages/SettingsLib/res/values-ar/arrays.xml
@@ -58,6 +58,46 @@
<item msgid="3878793616631049349">"استخدام التحقق من HDCP لمحتوى DRM فقط"</item>
<item msgid="45075631231212732">"استخدام التحقق من HDCP دومًا"</item>
</string-array>
+ <!-- no translation found for bluetooth_a2dp_codec_titles:0 (1852387125374225729) -->
+ <!-- no translation found for bluetooth_a2dp_codec_titles:1 (7539690996561263909) -->
+ <!-- no translation found for bluetooth_a2dp_codec_titles:2 (4260844283202960798) -->
+ <!-- no translation found for bluetooth_a2dp_codec_titles:3 (7279983368484312990) -->
+ <!-- no translation found for bluetooth_a2dp_codec_titles:4 (2301339338870319651) -->
+ <!-- no translation found for bluetooth_a2dp_codec_summaries:0 (9072025520360316957) -->
+ <!-- no translation found for bluetooth_a2dp_codec_summaries:1 (6898329690939802290) -->
+ <!-- no translation found for bluetooth_a2dp_codec_summaries:2 (1190434429082395888) -->
+ <!-- no translation found for bluetooth_a2dp_codec_summaries:3 (649699003004233053) -->
+ <!-- no translation found for bluetooth_a2dp_codec_summaries:4 (508106435710925399) -->
+ <!-- no translation found for bluetooth_a2dp_codec_sample_rate_titles:0 (7102940318360468759) -->
+ <!-- no translation found for bluetooth_a2dp_codec_sample_rate_titles:1 (8895532488906185219) -->
+ <!-- no translation found for bluetooth_a2dp_codec_sample_rate_titles:2 (2909915718994807056) -->
+ <!-- no translation found for bluetooth_a2dp_codec_sample_rate_titles:3 (3347287377354164611) -->
+ <!-- no translation found for bluetooth_a2dp_codec_sample_rate_titles:4 (1234212100239985373) -->
+ <!-- no translation found for bluetooth_a2dp_codec_sample_rate_summaries:0 (7224433008148687313) -->
+ <!-- no translation found for bluetooth_a2dp_codec_sample_rate_summaries:1 (4482862757811638365) -->
+ <!-- no translation found for bluetooth_a2dp_codec_sample_rate_summaries:2 (354495328188724404) -->
+ <!-- no translation found for bluetooth_a2dp_codec_sample_rate_summaries:3 (7329816882213695083) -->
+ <!-- no translation found for bluetooth_a2dp_codec_sample_rate_summaries:4 (6967397666254430476) -->
+ <!-- no translation found for bluetooth_a2dp_codec_bits_per_sample_titles:0 (6694044160540313386) -->
+ <!-- no translation found for bluetooth_a2dp_codec_bits_per_sample_titles:1 (5618929009984956469) -->
+ <!-- no translation found for bluetooth_a2dp_codec_bits_per_sample_titles:2 (3412640499234627248) -->
+ <!-- no translation found for bluetooth_a2dp_codec_bits_per_sample_titles:3 (121583001492929387) -->
+ <!-- no translation found for bluetooth_a2dp_codec_bits_per_sample_summaries:0 (5091076677792306320) -->
+ <!-- no translation found for bluetooth_a2dp_codec_bits_per_sample_summaries:1 (4726688794884191540) -->
+ <!-- no translation found for bluetooth_a2dp_codec_bits_per_sample_summaries:2 (305344756485516870) -->
+ <!-- no translation found for bluetooth_a2dp_codec_bits_per_sample_summaries:3 (244568657919675099) -->
+ <!-- no translation found for bluetooth_a2dp_codec_channel_mode_titles:0 (13423709606339855) -->
+ <!-- no translation found for bluetooth_a2dp_codec_channel_mode_titles:1 (4106832974775067314) -->
+ <!-- no translation found for bluetooth_a2dp_codec_channel_mode_titles:2 (5571632958424639155) -->
+ <!-- no translation found for bluetooth_a2dp_codec_channel_mode_summaries:0 (8128478683963250130) -->
+ <!-- no translation found for bluetooth_a2dp_codec_channel_mode_summaries:1 (8900559293912978337) -->
+ <!-- no translation found for bluetooth_a2dp_codec_channel_mode_summaries:2 (8883739882299884241) -->
+ <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_titles:0 (2944889121850394020) -->
+ <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_titles:1 (138837449700903545) -->
+ <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_titles:2 (4777177307869441982) -->
+ <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_summaries:0 (172302906231378902) -->
+ <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_summaries:1 (9091111147684472529) -->
+ <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_summaries:2 (3367904477834831032) -->
<string-array name="select_logd_size_titles">
<item msgid="8665206199209698501">"إيقاف"</item>
<item msgid="1593289376502312923">"٦٤ كيلوبايت"</item>
diff --git a/packages/SettingsLib/res/values-ar/strings.xml b/packages/SettingsLib/res/values-ar/strings.xml
index 9f6c440..20f55e1 100644
--- a/packages/SettingsLib/res/values-ar/strings.xml
+++ b/packages/SettingsLib/res/values-ar/strings.xml
@@ -170,6 +170,26 @@
<string name="wifi_allow_scan_with_traffic" msgid="3601853081178265786">"السماح دائمًا بعمليات فحص Wi-Fi للتجوال"</string>
<string name="mobile_data_always_on" msgid="7745605759775320362">"بيانات الجوّال نشطة دائمًا"</string>
<string name="bluetooth_disable_absolute_volume" msgid="2660673801947898809">"تعطيل مستوى الصوت المطلق"</string>
+ <!-- no translation found for bluetooth_select_a2dp_codec_type (90597356942154882) -->
+ <skip />
+ <!-- no translation found for bluetooth_select_a2dp_codec_type_dialog_title (6470824182074383881) -->
+ <skip />
+ <!-- no translation found for bluetooth_select_a2dp_codec_sample_rate (4788245703824623062) -->
+ <skip />
+ <!-- no translation found for bluetooth_select_a2dp_codec_sample_rate_dialog_title (4263851572248033749) -->
+ <skip />
+ <!-- no translation found for bluetooth_select_a2dp_codec_bits_per_sample (2099645202720164141) -->
+ <skip />
+ <!-- no translation found for bluetooth_select_a2dp_codec_bits_per_sample_dialog_title (2096170505745650345) -->
+ <skip />
+ <!-- no translation found for bluetooth_select_a2dp_codec_channel_mode (884855779449390540) -->
+ <skip />
+ <!-- no translation found for bluetooth_select_a2dp_codec_channel_mode_dialog_title (4073812880900816325) -->
+ <skip />
+ <!-- no translation found for bluetooth_select_a2dp_codec_ldac_playback_quality (4846872213548295632) -->
+ <skip />
+ <!-- no translation found for bluetooth_select_a2dp_codec_ldac_playback_quality_dialog_title (3940973633342423717) -->
+ <skip />
<string name="wifi_display_certification_summary" msgid="1155182309166746973">"عرض خيارات شهادة عرض شاشة لاسلكي"</string>
<string name="wifi_verbose_logging_summary" msgid="6615071616111731958">"زيادة مستوى تسجيل Wi-Fi، وعرض لكل SSID RSSI في منتقي Wi-Fi"</string>
<string name="wifi_aggressive_handover_summary" msgid="6328455667642570371">"عند تمكينه، سيكون Wi-Fi أكثر حدة في تسليم اتصال البيانات إلى الشبكة الخلوية، وذلك عندما تكون إشارة WiFi منخفضة"</string>
diff --git a/packages/SettingsLib/res/values-az-rAZ/arrays.xml b/packages/SettingsLib/res/values-az-rAZ/arrays.xml
index cd8b1e0..09f0bee 100644
--- a/packages/SettingsLib/res/values-az-rAZ/arrays.xml
+++ b/packages/SettingsLib/res/values-az-rAZ/arrays.xml
@@ -58,6 +58,46 @@
<item msgid="3878793616631049349">"Yalnız DRM məzmun oxumaq üçün HDCP istifadə edin"</item>
<item msgid="45075631231212732">"Həmişə HDCP yoxlama istifadə edin"</item>
</string-array>
+ <!-- no translation found for bluetooth_a2dp_codec_titles:0 (1852387125374225729) -->
+ <!-- no translation found for bluetooth_a2dp_codec_titles:1 (7539690996561263909) -->
+ <!-- no translation found for bluetooth_a2dp_codec_titles:2 (4260844283202960798) -->
+ <!-- no translation found for bluetooth_a2dp_codec_titles:3 (7279983368484312990) -->
+ <!-- no translation found for bluetooth_a2dp_codec_titles:4 (2301339338870319651) -->
+ <!-- no translation found for bluetooth_a2dp_codec_summaries:0 (9072025520360316957) -->
+ <!-- no translation found for bluetooth_a2dp_codec_summaries:1 (6898329690939802290) -->
+ <!-- no translation found for bluetooth_a2dp_codec_summaries:2 (1190434429082395888) -->
+ <!-- no translation found for bluetooth_a2dp_codec_summaries:3 (649699003004233053) -->
+ <!-- no translation found for bluetooth_a2dp_codec_summaries:4 (508106435710925399) -->
+ <!-- no translation found for bluetooth_a2dp_codec_sample_rate_titles:0 (7102940318360468759) -->
+ <!-- no translation found for bluetooth_a2dp_codec_sample_rate_titles:1 (8895532488906185219) -->
+ <!-- no translation found for bluetooth_a2dp_codec_sample_rate_titles:2 (2909915718994807056) -->
+ <!-- no translation found for bluetooth_a2dp_codec_sample_rate_titles:3 (3347287377354164611) -->
+ <!-- no translation found for bluetooth_a2dp_codec_sample_rate_titles:4 (1234212100239985373) -->
+ <!-- no translation found for bluetooth_a2dp_codec_sample_rate_summaries:0 (7224433008148687313) -->
+ <!-- no translation found for bluetooth_a2dp_codec_sample_rate_summaries:1 (4482862757811638365) -->
+ <!-- no translation found for bluetooth_a2dp_codec_sample_rate_summaries:2 (354495328188724404) -->
+ <!-- no translation found for bluetooth_a2dp_codec_sample_rate_summaries:3 (7329816882213695083) -->
+ <!-- no translation found for bluetooth_a2dp_codec_sample_rate_summaries:4 (6967397666254430476) -->
+ <!-- no translation found for bluetooth_a2dp_codec_bits_per_sample_titles:0 (6694044160540313386) -->
+ <!-- no translation found for bluetooth_a2dp_codec_bits_per_sample_titles:1 (5618929009984956469) -->
+ <!-- no translation found for bluetooth_a2dp_codec_bits_per_sample_titles:2 (3412640499234627248) -->
+ <!-- no translation found for bluetooth_a2dp_codec_bits_per_sample_titles:3 (121583001492929387) -->
+ <!-- no translation found for bluetooth_a2dp_codec_bits_per_sample_summaries:0 (5091076677792306320) -->
+ <!-- no translation found for bluetooth_a2dp_codec_bits_per_sample_summaries:1 (4726688794884191540) -->
+ <!-- no translation found for bluetooth_a2dp_codec_bits_per_sample_summaries:2 (305344756485516870) -->
+ <!-- no translation found for bluetooth_a2dp_codec_bits_per_sample_summaries:3 (244568657919675099) -->
+ <!-- no translation found for bluetooth_a2dp_codec_channel_mode_titles:0 (13423709606339855) -->
+ <!-- no translation found for bluetooth_a2dp_codec_channel_mode_titles:1 (4106832974775067314) -->
+ <!-- no translation found for bluetooth_a2dp_codec_channel_mode_titles:2 (5571632958424639155) -->
+ <!-- no translation found for bluetooth_a2dp_codec_channel_mode_summaries:0 (8128478683963250130) -->
+ <!-- no translation found for bluetooth_a2dp_codec_channel_mode_summaries:1 (8900559293912978337) -->
+ <!-- no translation found for bluetooth_a2dp_codec_channel_mode_summaries:2 (8883739882299884241) -->
+ <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_titles:0 (2944889121850394020) -->
+ <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_titles:1 (138837449700903545) -->
+ <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_titles:2 (4777177307869441982) -->
+ <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_summaries:0 (172302906231378902) -->
+ <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_summaries:1 (9091111147684472529) -->
+ <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_summaries:2 (3367904477834831032) -->
<string-array name="select_logd_size_titles">
<item msgid="8665206199209698501">"Deaktiv"</item>
<item msgid="1593289376502312923">"64K"</item>
diff --git a/packages/SettingsLib/res/values-az-rAZ/strings.xml b/packages/SettingsLib/res/values-az-rAZ/strings.xml
index a53e97a..4a302de 100644
--- a/packages/SettingsLib/res/values-az-rAZ/strings.xml
+++ b/packages/SettingsLib/res/values-az-rAZ/strings.xml
@@ -170,6 +170,26 @@
<string name="wifi_allow_scan_with_traffic" msgid="3601853081178265786">"Wi‑Fi axtarışlarına həmişə icazə verin"</string>
<string name="mobile_data_always_on" msgid="7745605759775320362">"Mobil data həmişə aktivdir"</string>
<string name="bluetooth_disable_absolute_volume" msgid="2660673801947898809">"Mütləq səs həcmi deaktiv edin"</string>
+ <!-- no translation found for bluetooth_select_a2dp_codec_type (90597356942154882) -->
+ <skip />
+ <!-- no translation found for bluetooth_select_a2dp_codec_type_dialog_title (6470824182074383881) -->
+ <skip />
+ <!-- no translation found for bluetooth_select_a2dp_codec_sample_rate (4788245703824623062) -->
+ <skip />
+ <!-- no translation found for bluetooth_select_a2dp_codec_sample_rate_dialog_title (4263851572248033749) -->
+ <skip />
+ <!-- no translation found for bluetooth_select_a2dp_codec_bits_per_sample (2099645202720164141) -->
+ <skip />
+ <!-- no translation found for bluetooth_select_a2dp_codec_bits_per_sample_dialog_title (2096170505745650345) -->
+ <skip />
+ <!-- no translation found for bluetooth_select_a2dp_codec_channel_mode (884855779449390540) -->
+ <skip />
+ <!-- no translation found for bluetooth_select_a2dp_codec_channel_mode_dialog_title (4073812880900816325) -->
+ <skip />
+ <!-- no translation found for bluetooth_select_a2dp_codec_ldac_playback_quality (4846872213548295632) -->
+ <skip />
+ <!-- no translation found for bluetooth_select_a2dp_codec_ldac_playback_quality_dialog_title (3940973633342423717) -->
+ <skip />
<string name="wifi_display_certification_summary" msgid="1155182309166746973">"Simsiz displey sertifikatlaşması üçün seçimləri göstərir"</string>
<string name="wifi_verbose_logging_summary" msgid="6615071616111731958">"Wi‑Fi giriş səviyyəsini qaldırın, Wi‑Fi seçəndə hər SSID RSSI üzrə göstərin"</string>
<string name="wifi_aggressive_handover_summary" msgid="6328455667642570371">"Aktiv olanda, Wi‑Fi sianqlı zəif olan zaman, Mobil şəbəkə data bağlantısına nisbətən, Wi‑Fi daha aqressiv olacaq"</string>
diff --git a/packages/SettingsLib/res/values-b+sr+Latn/arrays.xml b/packages/SettingsLib/res/values-b+sr+Latn/arrays.xml
index dbee985..b40f2eb 100644
--- a/packages/SettingsLib/res/values-b+sr+Latn/arrays.xml
+++ b/packages/SettingsLib/res/values-b+sr+Latn/arrays.xml
@@ -58,6 +58,46 @@
<item msgid="3878793616631049349">"Koristi HDCP proveru samo za DRM sadržaj"</item>
<item msgid="45075631231212732">"Uvek koristi HDCP proveru"</item>
</string-array>
+ <!-- no translation found for bluetooth_a2dp_codec_titles:0 (1852387125374225729) -->
+ <!-- no translation found for bluetooth_a2dp_codec_titles:1 (7539690996561263909) -->
+ <!-- no translation found for bluetooth_a2dp_codec_titles:2 (4260844283202960798) -->
+ <!-- no translation found for bluetooth_a2dp_codec_titles:3 (7279983368484312990) -->
+ <!-- no translation found for bluetooth_a2dp_codec_titles:4 (2301339338870319651) -->
+ <!-- no translation found for bluetooth_a2dp_codec_summaries:0 (9072025520360316957) -->
+ <!-- no translation found for bluetooth_a2dp_codec_summaries:1 (6898329690939802290) -->
+ <!-- no translation found for bluetooth_a2dp_codec_summaries:2 (1190434429082395888) -->
+ <!-- no translation found for bluetooth_a2dp_codec_summaries:3 (649699003004233053) -->
+ <!-- no translation found for bluetooth_a2dp_codec_summaries:4 (508106435710925399) -->
+ <!-- no translation found for bluetooth_a2dp_codec_sample_rate_titles:0 (7102940318360468759) -->
+ <!-- no translation found for bluetooth_a2dp_codec_sample_rate_titles:1 (8895532488906185219) -->
+ <!-- no translation found for bluetooth_a2dp_codec_sample_rate_titles:2 (2909915718994807056) -->
+ <!-- no translation found for bluetooth_a2dp_codec_sample_rate_titles:3 (3347287377354164611) -->
+ <!-- no translation found for bluetooth_a2dp_codec_sample_rate_titles:4 (1234212100239985373) -->
+ <!-- no translation found for bluetooth_a2dp_codec_sample_rate_summaries:0 (7224433008148687313) -->
+ <!-- no translation found for bluetooth_a2dp_codec_sample_rate_summaries:1 (4482862757811638365) -->
+ <!-- no translation found for bluetooth_a2dp_codec_sample_rate_summaries:2 (354495328188724404) -->
+ <!-- no translation found for bluetooth_a2dp_codec_sample_rate_summaries:3 (7329816882213695083) -->
+ <!-- no translation found for bluetooth_a2dp_codec_sample_rate_summaries:4 (6967397666254430476) -->
+ <!-- no translation found for bluetooth_a2dp_codec_bits_per_sample_titles:0 (6694044160540313386) -->
+ <!-- no translation found for bluetooth_a2dp_codec_bits_per_sample_titles:1 (5618929009984956469) -->
+ <!-- no translation found for bluetooth_a2dp_codec_bits_per_sample_titles:2 (3412640499234627248) -->
+ <!-- no translation found for bluetooth_a2dp_codec_bits_per_sample_titles:3 (121583001492929387) -->
+ <!-- no translation found for bluetooth_a2dp_codec_bits_per_sample_summaries:0 (5091076677792306320) -->
+ <!-- no translation found for bluetooth_a2dp_codec_bits_per_sample_summaries:1 (4726688794884191540) -->
+ <!-- no translation found for bluetooth_a2dp_codec_bits_per_sample_summaries:2 (305344756485516870) -->
+ <!-- no translation found for bluetooth_a2dp_codec_bits_per_sample_summaries:3 (244568657919675099) -->
+ <!-- no translation found for bluetooth_a2dp_codec_channel_mode_titles:0 (13423709606339855) -->
+ <!-- no translation found for bluetooth_a2dp_codec_channel_mode_titles:1 (4106832974775067314) -->
+ <!-- no translation found for bluetooth_a2dp_codec_channel_mode_titles:2 (5571632958424639155) -->
+ <!-- no translation found for bluetooth_a2dp_codec_channel_mode_summaries:0 (8128478683963250130) -->
+ <!-- no translation found for bluetooth_a2dp_codec_channel_mode_summaries:1 (8900559293912978337) -->
+ <!-- no translation found for bluetooth_a2dp_codec_channel_mode_summaries:2 (8883739882299884241) -->
+ <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_titles:0 (2944889121850394020) -->
+ <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_titles:1 (138837449700903545) -->
+ <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_titles:2 (4777177307869441982) -->
+ <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_summaries:0 (172302906231378902) -->
+ <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_summaries:1 (9091111147684472529) -->
+ <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_summaries:2 (3367904477834831032) -->
<string-array name="select_logd_size_titles">
<item msgid="8665206199209698501">"Isključeno"</item>
<item msgid="1593289376502312923">"64 kB"</item>
diff --git a/packages/SettingsLib/res/values-b+sr+Latn/strings.xml b/packages/SettingsLib/res/values-b+sr+Latn/strings.xml
index cad5980..fc436e9 100644
--- a/packages/SettingsLib/res/values-b+sr+Latn/strings.xml
+++ b/packages/SettingsLib/res/values-b+sr+Latn/strings.xml
@@ -170,6 +170,26 @@
<string name="wifi_allow_scan_with_traffic" msgid="3601853081178265786">"Uvek dozvoli skeniranje Wi‑Fi-ja u romingu"</string>
<string name="mobile_data_always_on" msgid="7745605759775320362">"Podaci za mobilne uređaje su uvek aktivni"</string>
<string name="bluetooth_disable_absolute_volume" msgid="2660673801947898809">"Onemogući glavno podešavanje jačine zvuka"</string>
+ <!-- no translation found for bluetooth_select_a2dp_codec_type (90597356942154882) -->
+ <skip />
+ <!-- no translation found for bluetooth_select_a2dp_codec_type_dialog_title (6470824182074383881) -->
+ <skip />
+ <!-- no translation found for bluetooth_select_a2dp_codec_sample_rate (4788245703824623062) -->
+ <skip />
+ <!-- no translation found for bluetooth_select_a2dp_codec_sample_rate_dialog_title (4263851572248033749) -->
+ <skip />
+ <!-- no translation found for bluetooth_select_a2dp_codec_bits_per_sample (2099645202720164141) -->
+ <skip />
+ <!-- no translation found for bluetooth_select_a2dp_codec_bits_per_sample_dialog_title (2096170505745650345) -->
+ <skip />
+ <!-- no translation found for bluetooth_select_a2dp_codec_channel_mode (884855779449390540) -->
+ <skip />
+ <!-- no translation found for bluetooth_select_a2dp_codec_channel_mode_dialog_title (4073812880900816325) -->
+ <skip />
+ <!-- no translation found for bluetooth_select_a2dp_codec_ldac_playback_quality (4846872213548295632) -->
+ <skip />
+ <!-- no translation found for bluetooth_select_a2dp_codec_ldac_playback_quality_dialog_title (3940973633342423717) -->
+ <skip />
<string name="wifi_display_certification_summary" msgid="1155182309166746973">"Prikaz opcija za sertifikaciju bežičnog ekrana"</string>
<string name="wifi_verbose_logging_summary" msgid="6615071616111731958">"Povećava nivo evidentiranja za Wi‑Fi. Prikaz po SSID RSSI-u u biraču Wi‑Fi mreže"</string>
<string name="wifi_aggressive_handover_summary" msgid="6328455667642570371">"Kada se omogući, Wi‑Fi će biti agresivniji pri prebacivanju mreže za prenos podataka na Mobilnu, kada je Wi‑Fi signal slab"</string>
diff --git a/packages/SettingsLib/res/values-be-rBY/arrays.xml b/packages/SettingsLib/res/values-be-rBY/arrays.xml
index 44d3bf2..2e2bb1a 100644
--- a/packages/SettingsLib/res/values-be-rBY/arrays.xml
+++ b/packages/SettingsLib/res/values-be-rBY/arrays.xml
@@ -58,6 +58,46 @@
<item msgid="3878793616631049349">"Выкарыстанне праверкі HDCP только для змесціва, абароненага DRM"</item>
<item msgid="45075631231212732">"Заўсёды выкарыстоўваць праверку HDCP"</item>
</string-array>
+ <!-- no translation found for bluetooth_a2dp_codec_titles:0 (1852387125374225729) -->
+ <!-- no translation found for bluetooth_a2dp_codec_titles:1 (7539690996561263909) -->
+ <!-- no translation found for bluetooth_a2dp_codec_titles:2 (4260844283202960798) -->
+ <!-- no translation found for bluetooth_a2dp_codec_titles:3 (7279983368484312990) -->
+ <!-- no translation found for bluetooth_a2dp_codec_titles:4 (2301339338870319651) -->
+ <!-- no translation found for bluetooth_a2dp_codec_summaries:0 (9072025520360316957) -->
+ <!-- no translation found for bluetooth_a2dp_codec_summaries:1 (6898329690939802290) -->
+ <!-- no translation found for bluetooth_a2dp_codec_summaries:2 (1190434429082395888) -->
+ <!-- no translation found for bluetooth_a2dp_codec_summaries:3 (649699003004233053) -->
+ <!-- no translation found for bluetooth_a2dp_codec_summaries:4 (508106435710925399) -->
+ <!-- no translation found for bluetooth_a2dp_codec_sample_rate_titles:0 (7102940318360468759) -->
+ <!-- no translation found for bluetooth_a2dp_codec_sample_rate_titles:1 (8895532488906185219) -->
+ <!-- no translation found for bluetooth_a2dp_codec_sample_rate_titles:2 (2909915718994807056) -->
+ <!-- no translation found for bluetooth_a2dp_codec_sample_rate_titles:3 (3347287377354164611) -->
+ <!-- no translation found for bluetooth_a2dp_codec_sample_rate_titles:4 (1234212100239985373) -->
+ <!-- no translation found for bluetooth_a2dp_codec_sample_rate_summaries:0 (7224433008148687313) -->
+ <!-- no translation found for bluetooth_a2dp_codec_sample_rate_summaries:1 (4482862757811638365) -->
+ <!-- no translation found for bluetooth_a2dp_codec_sample_rate_summaries:2 (354495328188724404) -->
+ <!-- no translation found for bluetooth_a2dp_codec_sample_rate_summaries:3 (7329816882213695083) -->
+ <!-- no translation found for bluetooth_a2dp_codec_sample_rate_summaries:4 (6967397666254430476) -->
+ <!-- no translation found for bluetooth_a2dp_codec_bits_per_sample_titles:0 (6694044160540313386) -->
+ <!-- no translation found for bluetooth_a2dp_codec_bits_per_sample_titles:1 (5618929009984956469) -->
+ <!-- no translation found for bluetooth_a2dp_codec_bits_per_sample_titles:2 (3412640499234627248) -->
+ <!-- no translation found for bluetooth_a2dp_codec_bits_per_sample_titles:3 (121583001492929387) -->
+ <!-- no translation found for bluetooth_a2dp_codec_bits_per_sample_summaries:0 (5091076677792306320) -->
+ <!-- no translation found for bluetooth_a2dp_codec_bits_per_sample_summaries:1 (4726688794884191540) -->
+ <!-- no translation found for bluetooth_a2dp_codec_bits_per_sample_summaries:2 (305344756485516870) -->
+ <!-- no translation found for bluetooth_a2dp_codec_bits_per_sample_summaries:3 (244568657919675099) -->
+ <!-- no translation found for bluetooth_a2dp_codec_channel_mode_titles:0 (13423709606339855) -->
+ <!-- no translation found for bluetooth_a2dp_codec_channel_mode_titles:1 (4106832974775067314) -->
+ <!-- no translation found for bluetooth_a2dp_codec_channel_mode_titles:2 (5571632958424639155) -->
+ <!-- no translation found for bluetooth_a2dp_codec_channel_mode_summaries:0 (8128478683963250130) -->
+ <!-- no translation found for bluetooth_a2dp_codec_channel_mode_summaries:1 (8900559293912978337) -->
+ <!-- no translation found for bluetooth_a2dp_codec_channel_mode_summaries:2 (8883739882299884241) -->
+ <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_titles:0 (2944889121850394020) -->
+ <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_titles:1 (138837449700903545) -->
+ <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_titles:2 (4777177307869441982) -->
+ <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_summaries:0 (172302906231378902) -->
+ <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_summaries:1 (9091111147684472529) -->
+ <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_summaries:2 (3367904477834831032) -->
<string-array name="select_logd_size_titles">
<item msgid="8665206199209698501">"Выкл."</item>
<item msgid="1593289376502312923">"64K"</item>
diff --git a/packages/SettingsLib/res/values-be-rBY/strings.xml b/packages/SettingsLib/res/values-be-rBY/strings.xml
index ba5b100..0a4d8c3 100644
--- a/packages/SettingsLib/res/values-be-rBY/strings.xml
+++ b/packages/SettingsLib/res/values-be-rBY/strings.xml
@@ -170,6 +170,26 @@
<string name="wifi_allow_scan_with_traffic" msgid="3601853081178265786">"Заўсёды дазваляць роўмінгавае сканіраванне Wi‑Fi"</string>
<string name="mobile_data_always_on" msgid="7745605759775320362">"Перадача даных мабільнай сувязі заўсёды актыўна"</string>
<string name="bluetooth_disable_absolute_volume" msgid="2660673801947898809">"Адключыць абсалютны гук"</string>
+ <!-- no translation found for bluetooth_select_a2dp_codec_type (90597356942154882) -->
+ <skip />
+ <!-- no translation found for bluetooth_select_a2dp_codec_type_dialog_title (6470824182074383881) -->
+ <skip />
+ <!-- no translation found for bluetooth_select_a2dp_codec_sample_rate (4788245703824623062) -->
+ <skip />
+ <!-- no translation found for bluetooth_select_a2dp_codec_sample_rate_dialog_title (4263851572248033749) -->
+ <skip />
+ <!-- no translation found for bluetooth_select_a2dp_codec_bits_per_sample (2099645202720164141) -->
+ <skip />
+ <!-- no translation found for bluetooth_select_a2dp_codec_bits_per_sample_dialog_title (2096170505745650345) -->
+ <skip />
+ <!-- no translation found for bluetooth_select_a2dp_codec_channel_mode (884855779449390540) -->
+ <skip />
+ <!-- no translation found for bluetooth_select_a2dp_codec_channel_mode_dialog_title (4073812880900816325) -->
+ <skip />
+ <!-- no translation found for bluetooth_select_a2dp_codec_ldac_playback_quality (4846872213548295632) -->
+ <skip />
+ <!-- no translation found for bluetooth_select_a2dp_codec_ldac_playback_quality_dialog_title (3940973633342423717) -->
+ <skip />
<string name="wifi_display_certification_summary" msgid="1155182309166746973">"Паказаць опцыі сертыфікацыі бесправаднога дысплея"</string>
<string name="wifi_verbose_logging_summary" msgid="6615071616111731958">"Падвыс. узровень дэтал-цыі журнала Wi‑Fi у залежн. ад SSID RSSI у Wi‑Fi Picker"</string>
<string name="wifi_aggressive_handover_summary" msgid="6328455667642570371">"Калі ўкл., прылада будзе больш інтэнсіўна імкнуцца перайсці з падлуч. да Wi-Fi на падлуч. да маб. сеткі, калі сігнал Wi‑Fi слабы"</string>
diff --git a/packages/SettingsLib/res/values-bg/arrays.xml b/packages/SettingsLib/res/values-bg/arrays.xml
index b9e3352..248aee1 100644
--- a/packages/SettingsLib/res/values-bg/arrays.xml
+++ b/packages/SettingsLib/res/values-bg/arrays.xml
@@ -58,6 +58,46 @@
<item msgid="3878793616631049349">"Да се използва проверка с HDCP само за DRM съдържание"</item>
<item msgid="45075631231212732">"Винаги да се използва проверка с HDCP"</item>
</string-array>
+ <!-- no translation found for bluetooth_a2dp_codec_titles:0 (1852387125374225729) -->
+ <!-- no translation found for bluetooth_a2dp_codec_titles:1 (7539690996561263909) -->
+ <!-- no translation found for bluetooth_a2dp_codec_titles:2 (4260844283202960798) -->
+ <!-- no translation found for bluetooth_a2dp_codec_titles:3 (7279983368484312990) -->
+ <!-- no translation found for bluetooth_a2dp_codec_titles:4 (2301339338870319651) -->
+ <!-- no translation found for bluetooth_a2dp_codec_summaries:0 (9072025520360316957) -->
+ <!-- no translation found for bluetooth_a2dp_codec_summaries:1 (6898329690939802290) -->
+ <!-- no translation found for bluetooth_a2dp_codec_summaries:2 (1190434429082395888) -->
+ <!-- no translation found for bluetooth_a2dp_codec_summaries:3 (649699003004233053) -->
+ <!-- no translation found for bluetooth_a2dp_codec_summaries:4 (508106435710925399) -->
+ <!-- no translation found for bluetooth_a2dp_codec_sample_rate_titles:0 (7102940318360468759) -->
+ <!-- no translation found for bluetooth_a2dp_codec_sample_rate_titles:1 (8895532488906185219) -->
+ <!-- no translation found for bluetooth_a2dp_codec_sample_rate_titles:2 (2909915718994807056) -->
+ <!-- no translation found for bluetooth_a2dp_codec_sample_rate_titles:3 (3347287377354164611) -->
+ <!-- no translation found for bluetooth_a2dp_codec_sample_rate_titles:4 (1234212100239985373) -->
+ <!-- no translation found for bluetooth_a2dp_codec_sample_rate_summaries:0 (7224433008148687313) -->
+ <!-- no translation found for bluetooth_a2dp_codec_sample_rate_summaries:1 (4482862757811638365) -->
+ <!-- no translation found for bluetooth_a2dp_codec_sample_rate_summaries:2 (354495328188724404) -->
+ <!-- no translation found for bluetooth_a2dp_codec_sample_rate_summaries:3 (7329816882213695083) -->
+ <!-- no translation found for bluetooth_a2dp_codec_sample_rate_summaries:4 (6967397666254430476) -->
+ <!-- no translation found for bluetooth_a2dp_codec_bits_per_sample_titles:0 (6694044160540313386) -->
+ <!-- no translation found for bluetooth_a2dp_codec_bits_per_sample_titles:1 (5618929009984956469) -->
+ <!-- no translation found for bluetooth_a2dp_codec_bits_per_sample_titles:2 (3412640499234627248) -->
+ <!-- no translation found for bluetooth_a2dp_codec_bits_per_sample_titles:3 (121583001492929387) -->
+ <!-- no translation found for bluetooth_a2dp_codec_bits_per_sample_summaries:0 (5091076677792306320) -->
+ <!-- no translation found for bluetooth_a2dp_codec_bits_per_sample_summaries:1 (4726688794884191540) -->
+ <!-- no translation found for bluetooth_a2dp_codec_bits_per_sample_summaries:2 (305344756485516870) -->
+ <!-- no translation found for bluetooth_a2dp_codec_bits_per_sample_summaries:3 (244568657919675099) -->
+ <!-- no translation found for bluetooth_a2dp_codec_channel_mode_titles:0 (13423709606339855) -->
+ <!-- no translation found for bluetooth_a2dp_codec_channel_mode_titles:1 (4106832974775067314) -->
+ <!-- no translation found for bluetooth_a2dp_codec_channel_mode_titles:2 (5571632958424639155) -->
+ <!-- no translation found for bluetooth_a2dp_codec_channel_mode_summaries:0 (8128478683963250130) -->
+ <!-- no translation found for bluetooth_a2dp_codec_channel_mode_summaries:1 (8900559293912978337) -->
+ <!-- no translation found for bluetooth_a2dp_codec_channel_mode_summaries:2 (8883739882299884241) -->
+ <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_titles:0 (2944889121850394020) -->
+ <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_titles:1 (138837449700903545) -->
+ <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_titles:2 (4777177307869441982) -->
+ <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_summaries:0 (172302906231378902) -->
+ <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_summaries:1 (9091111147684472529) -->
+ <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_summaries:2 (3367904477834831032) -->
<string-array name="select_logd_size_titles">
<item msgid="8665206199209698501">"Изключено"</item>
<item msgid="1593289376502312923">"64 КБ"</item>
diff --git a/packages/SettingsLib/res/values-bg/strings.xml b/packages/SettingsLib/res/values-bg/strings.xml
index b32388e..592fde7 100644
--- a/packages/SettingsLib/res/values-bg/strings.xml
+++ b/packages/SettingsLib/res/values-bg/strings.xml
@@ -170,6 +170,26 @@
<string name="wifi_allow_scan_with_traffic" msgid="3601853081178265786">"Сканирането за роуминг на Wi-Fi да е разрешено винаги"</string>
<string name="mobile_data_always_on" msgid="7745605759775320362">"Винаги активни клетъчни данни"</string>
<string name="bluetooth_disable_absolute_volume" msgid="2660673801947898809">"Деактивиране на пълната сила на звука"</string>
+ <!-- no translation found for bluetooth_select_a2dp_codec_type (90597356942154882) -->
+ <skip />
+ <!-- no translation found for bluetooth_select_a2dp_codec_type_dialog_title (6470824182074383881) -->
+ <skip />
+ <!-- no translation found for bluetooth_select_a2dp_codec_sample_rate (4788245703824623062) -->
+ <skip />
+ <!-- no translation found for bluetooth_select_a2dp_codec_sample_rate_dialog_title (4263851572248033749) -->
+ <skip />
+ <!-- no translation found for bluetooth_select_a2dp_codec_bits_per_sample (2099645202720164141) -->
+ <skip />
+ <!-- no translation found for bluetooth_select_a2dp_codec_bits_per_sample_dialog_title (2096170505745650345) -->
+ <skip />
+ <!-- no translation found for bluetooth_select_a2dp_codec_channel_mode (884855779449390540) -->
+ <skip />
+ <!-- no translation found for bluetooth_select_a2dp_codec_channel_mode_dialog_title (4073812880900816325) -->
+ <skip />
+ <!-- no translation found for bluetooth_select_a2dp_codec_ldac_playback_quality (4846872213548295632) -->
+ <skip />
+ <!-- no translation found for bluetooth_select_a2dp_codec_ldac_playback_quality_dialog_title (3940973633342423717) -->
+ <skip />
<string name="wifi_display_certification_summary" msgid="1155182309166746973">"Показване на опциите за сертифициране на безжичния дисплей"</string>
<string name="wifi_verbose_logging_summary" msgid="6615071616111731958">"По-подробно регистр. на Wi‑Fi – данни за RSSI на SSID в инстр. за избор на Wi‑Fi"</string>
<string name="wifi_aggressive_handover_summary" msgid="6328455667642570371">"При активиране предаването на връзката за данни от Wi-Fi към мобилната мрежа ще е по-агресивно, когато Wi-Fi сигналът е слаб"</string>
diff --git a/packages/SettingsLib/res/values-bn-rBD/arrays.xml b/packages/SettingsLib/res/values-bn-rBD/arrays.xml
index d9a3b04..73272eb9 100644
--- a/packages/SettingsLib/res/values-bn-rBD/arrays.xml
+++ b/packages/SettingsLib/res/values-bn-rBD/arrays.xml
@@ -58,6 +58,46 @@
<item msgid="3878793616631049349">"শুধুমাত্র DRM সামগ্রীর জন্য HDCP চেক করা ব্যবহার করুন"</item>
<item msgid="45075631231212732">"সর্বদা HDCP পরীক্ষণ ব্যবহার করুন"</item>
</string-array>
+ <!-- no translation found for bluetooth_a2dp_codec_titles:0 (1852387125374225729) -->
+ <!-- no translation found for bluetooth_a2dp_codec_titles:1 (7539690996561263909) -->
+ <!-- no translation found for bluetooth_a2dp_codec_titles:2 (4260844283202960798) -->
+ <!-- no translation found for bluetooth_a2dp_codec_titles:3 (7279983368484312990) -->
+ <!-- no translation found for bluetooth_a2dp_codec_titles:4 (2301339338870319651) -->
+ <!-- no translation found for bluetooth_a2dp_codec_summaries:0 (9072025520360316957) -->
+ <!-- no translation found for bluetooth_a2dp_codec_summaries:1 (6898329690939802290) -->
+ <!-- no translation found for bluetooth_a2dp_codec_summaries:2 (1190434429082395888) -->
+ <!-- no translation found for bluetooth_a2dp_codec_summaries:3 (649699003004233053) -->
+ <!-- no translation found for bluetooth_a2dp_codec_summaries:4 (508106435710925399) -->
+ <!-- no translation found for bluetooth_a2dp_codec_sample_rate_titles:0 (7102940318360468759) -->
+ <!-- no translation found for bluetooth_a2dp_codec_sample_rate_titles:1 (8895532488906185219) -->
+ <!-- no translation found for bluetooth_a2dp_codec_sample_rate_titles:2 (2909915718994807056) -->
+ <!-- no translation found for bluetooth_a2dp_codec_sample_rate_titles:3 (3347287377354164611) -->
+ <!-- no translation found for bluetooth_a2dp_codec_sample_rate_titles:4 (1234212100239985373) -->
+ <!-- no translation found for bluetooth_a2dp_codec_sample_rate_summaries:0 (7224433008148687313) -->
+ <!-- no translation found for bluetooth_a2dp_codec_sample_rate_summaries:1 (4482862757811638365) -->
+ <!-- no translation found for bluetooth_a2dp_codec_sample_rate_summaries:2 (354495328188724404) -->
+ <!-- no translation found for bluetooth_a2dp_codec_sample_rate_summaries:3 (7329816882213695083) -->
+ <!-- no translation found for bluetooth_a2dp_codec_sample_rate_summaries:4 (6967397666254430476) -->
+ <!-- no translation found for bluetooth_a2dp_codec_bits_per_sample_titles:0 (6694044160540313386) -->
+ <!-- no translation found for bluetooth_a2dp_codec_bits_per_sample_titles:1 (5618929009984956469) -->
+ <!-- no translation found for bluetooth_a2dp_codec_bits_per_sample_titles:2 (3412640499234627248) -->
+ <!-- no translation found for bluetooth_a2dp_codec_bits_per_sample_titles:3 (121583001492929387) -->
+ <!-- no translation found for bluetooth_a2dp_codec_bits_per_sample_summaries:0 (5091076677792306320) -->
+ <!-- no translation found for bluetooth_a2dp_codec_bits_per_sample_summaries:1 (4726688794884191540) -->
+ <!-- no translation found for bluetooth_a2dp_codec_bits_per_sample_summaries:2 (305344756485516870) -->
+ <!-- no translation found for bluetooth_a2dp_codec_bits_per_sample_summaries:3 (244568657919675099) -->
+ <!-- no translation found for bluetooth_a2dp_codec_channel_mode_titles:0 (13423709606339855) -->
+ <!-- no translation found for bluetooth_a2dp_codec_channel_mode_titles:1 (4106832974775067314) -->
+ <!-- no translation found for bluetooth_a2dp_codec_channel_mode_titles:2 (5571632958424639155) -->
+ <!-- no translation found for bluetooth_a2dp_codec_channel_mode_summaries:0 (8128478683963250130) -->
+ <!-- no translation found for bluetooth_a2dp_codec_channel_mode_summaries:1 (8900559293912978337) -->
+ <!-- no translation found for bluetooth_a2dp_codec_channel_mode_summaries:2 (8883739882299884241) -->
+ <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_titles:0 (2944889121850394020) -->
+ <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_titles:1 (138837449700903545) -->
+ <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_titles:2 (4777177307869441982) -->
+ <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_summaries:0 (172302906231378902) -->
+ <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_summaries:1 (9091111147684472529) -->
+ <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_summaries:2 (3367904477834831032) -->
<string-array name="select_logd_size_titles">
<item msgid="8665206199209698501">"বন্ধ আছে"</item>
<item msgid="1593289376502312923">"৬৪K"</item>
diff --git a/packages/SettingsLib/res/values-bn-rBD/strings.xml b/packages/SettingsLib/res/values-bn-rBD/strings.xml
index 3ee2642e..75177f3 100644
--- a/packages/SettingsLib/res/values-bn-rBD/strings.xml
+++ b/packages/SettingsLib/res/values-bn-rBD/strings.xml
@@ -170,6 +170,26 @@
<string name="wifi_allow_scan_with_traffic" msgid="3601853081178265786">"সর্বদা Wifi রোম স্ক্যানকে অনুমতি দিন"</string>
<string name="mobile_data_always_on" msgid="7745605759775320362">"সেলুলার ডেটা সর্বদাই সক্রিয় থাকে"</string>
<string name="bluetooth_disable_absolute_volume" msgid="2660673801947898809">"চূড়ান্ত ভলিউম অক্ষম করুন"</string>
+ <!-- no translation found for bluetooth_select_a2dp_codec_type (90597356942154882) -->
+ <skip />
+ <!-- no translation found for bluetooth_select_a2dp_codec_type_dialog_title (6470824182074383881) -->
+ <skip />
+ <!-- no translation found for bluetooth_select_a2dp_codec_sample_rate (4788245703824623062) -->
+ <skip />
+ <!-- no translation found for bluetooth_select_a2dp_codec_sample_rate_dialog_title (4263851572248033749) -->
+ <skip />
+ <!-- no translation found for bluetooth_select_a2dp_codec_bits_per_sample (2099645202720164141) -->
+ <skip />
+ <!-- no translation found for bluetooth_select_a2dp_codec_bits_per_sample_dialog_title (2096170505745650345) -->
+ <skip />
+ <!-- no translation found for bluetooth_select_a2dp_codec_channel_mode (884855779449390540) -->
+ <skip />
+ <!-- no translation found for bluetooth_select_a2dp_codec_channel_mode_dialog_title (4073812880900816325) -->
+ <skip />
+ <!-- no translation found for bluetooth_select_a2dp_codec_ldac_playback_quality (4846872213548295632) -->
+ <skip />
+ <!-- no translation found for bluetooth_select_a2dp_codec_ldac_playback_quality_dialog_title (3940973633342423717) -->
+ <skip />
<string name="wifi_display_certification_summary" msgid="1155182309166746973">"ওয়্যারলেস প্রদর্শন সার্টিফিকেশন জন্য বিকল্পগুলি দেখান"</string>
<string name="wifi_verbose_logging_summary" msgid="6615071616111731958">"ওয়াই-ফাই লগিং স্তর বাড়ান, ওয়াই-ফাই চয়নকারীতে SSID RSSI অনুযায়ী দেখান"</string>
<string name="wifi_aggressive_handover_summary" msgid="6328455667642570371">"সক্ষম করা থাকলে, নিম্নমানের ওয়াই-ফাই সিগন্যালের ক্ষেত্রে, সেলুলার-এ ডেটা সংযোগ প্রদান করতে ওয়াই-ফাই আরো বেশি শক্তিশালীভাবে কাজ করবে"</string>
diff --git a/packages/SettingsLib/res/values-bs-rBA/arrays.xml b/packages/SettingsLib/res/values-bs-rBA/arrays.xml
index 3d99ead..c8f59cf 100644
--- a/packages/SettingsLib/res/values-bs-rBA/arrays.xml
+++ b/packages/SettingsLib/res/values-bs-rBA/arrays.xml
@@ -58,6 +58,46 @@
<item msgid="3878793616631049349">"Koristi HDCP provjeru samo za DRM sadržaj"</item>
<item msgid="45075631231212732">"Uvijek koristi HDCP provjeru"</item>
</string-array>
+ <!-- no translation found for bluetooth_a2dp_codec_titles:0 (1852387125374225729) -->
+ <!-- no translation found for bluetooth_a2dp_codec_titles:1 (7539690996561263909) -->
+ <!-- no translation found for bluetooth_a2dp_codec_titles:2 (4260844283202960798) -->
+ <!-- no translation found for bluetooth_a2dp_codec_titles:3 (7279983368484312990) -->
+ <!-- no translation found for bluetooth_a2dp_codec_titles:4 (2301339338870319651) -->
+ <!-- no translation found for bluetooth_a2dp_codec_summaries:0 (9072025520360316957) -->
+ <!-- no translation found for bluetooth_a2dp_codec_summaries:1 (6898329690939802290) -->
+ <!-- no translation found for bluetooth_a2dp_codec_summaries:2 (1190434429082395888) -->
+ <!-- no translation found for bluetooth_a2dp_codec_summaries:3 (649699003004233053) -->
+ <!-- no translation found for bluetooth_a2dp_codec_summaries:4 (508106435710925399) -->
+ <!-- no translation found for bluetooth_a2dp_codec_sample_rate_titles:0 (7102940318360468759) -->
+ <!-- no translation found for bluetooth_a2dp_codec_sample_rate_titles:1 (8895532488906185219) -->
+ <!-- no translation found for bluetooth_a2dp_codec_sample_rate_titles:2 (2909915718994807056) -->
+ <!-- no translation found for bluetooth_a2dp_codec_sample_rate_titles:3 (3347287377354164611) -->
+ <!-- no translation found for bluetooth_a2dp_codec_sample_rate_titles:4 (1234212100239985373) -->
+ <!-- no translation found for bluetooth_a2dp_codec_sample_rate_summaries:0 (7224433008148687313) -->
+ <!-- no translation found for bluetooth_a2dp_codec_sample_rate_summaries:1 (4482862757811638365) -->
+ <!-- no translation found for bluetooth_a2dp_codec_sample_rate_summaries:2 (354495328188724404) -->
+ <!-- no translation found for bluetooth_a2dp_codec_sample_rate_summaries:3 (7329816882213695083) -->
+ <!-- no translation found for bluetooth_a2dp_codec_sample_rate_summaries:4 (6967397666254430476) -->
+ <!-- no translation found for bluetooth_a2dp_codec_bits_per_sample_titles:0 (6694044160540313386) -->
+ <!-- no translation found for bluetooth_a2dp_codec_bits_per_sample_titles:1 (5618929009984956469) -->
+ <!-- no translation found for bluetooth_a2dp_codec_bits_per_sample_titles:2 (3412640499234627248) -->
+ <!-- no translation found for bluetooth_a2dp_codec_bits_per_sample_titles:3 (121583001492929387) -->
+ <!-- no translation found for bluetooth_a2dp_codec_bits_per_sample_summaries:0 (5091076677792306320) -->
+ <!-- no translation found for bluetooth_a2dp_codec_bits_per_sample_summaries:1 (4726688794884191540) -->
+ <!-- no translation found for bluetooth_a2dp_codec_bits_per_sample_summaries:2 (305344756485516870) -->
+ <!-- no translation found for bluetooth_a2dp_codec_bits_per_sample_summaries:3 (244568657919675099) -->
+ <!-- no translation found for bluetooth_a2dp_codec_channel_mode_titles:0 (13423709606339855) -->
+ <!-- no translation found for bluetooth_a2dp_codec_channel_mode_titles:1 (4106832974775067314) -->
+ <!-- no translation found for bluetooth_a2dp_codec_channel_mode_titles:2 (5571632958424639155) -->
+ <!-- no translation found for bluetooth_a2dp_codec_channel_mode_summaries:0 (8128478683963250130) -->
+ <!-- no translation found for bluetooth_a2dp_codec_channel_mode_summaries:1 (8900559293912978337) -->
+ <!-- no translation found for bluetooth_a2dp_codec_channel_mode_summaries:2 (8883739882299884241) -->
+ <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_titles:0 (2944889121850394020) -->
+ <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_titles:1 (138837449700903545) -->
+ <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_titles:2 (4777177307869441982) -->
+ <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_summaries:0 (172302906231378902) -->
+ <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_summaries:1 (9091111147684472529) -->
+ <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_summaries:2 (3367904477834831032) -->
<string-array name="select_logd_size_titles">
<item msgid="8665206199209698501">"Isključeno"</item>
<item msgid="1593289376502312923">"64K"</item>
diff --git a/packages/SettingsLib/res/values-bs-rBA/strings.xml b/packages/SettingsLib/res/values-bs-rBA/strings.xml
index b207129..a240170 100644
--- a/packages/SettingsLib/res/values-bs-rBA/strings.xml
+++ b/packages/SettingsLib/res/values-bs-rBA/strings.xml
@@ -170,6 +170,26 @@
<string name="wifi_allow_scan_with_traffic" msgid="3601853081178265786">"Uvijek dopustiti Wi-Fi lutajuće skeniranje"</string>
<string name="mobile_data_always_on" msgid="7745605759775320362">"Mobilni podaci uvijek aktivni"</string>
<string name="bluetooth_disable_absolute_volume" msgid="2660673801947898809">"Onemogućite apsolutnu jačinu zvuka"</string>
+ <!-- no translation found for bluetooth_select_a2dp_codec_type (90597356942154882) -->
+ <skip />
+ <!-- no translation found for bluetooth_select_a2dp_codec_type_dialog_title (6470824182074383881) -->
+ <skip />
+ <!-- no translation found for bluetooth_select_a2dp_codec_sample_rate (4788245703824623062) -->
+ <skip />
+ <!-- no translation found for bluetooth_select_a2dp_codec_sample_rate_dialog_title (4263851572248033749) -->
+ <skip />
+ <!-- no translation found for bluetooth_select_a2dp_codec_bits_per_sample (2099645202720164141) -->
+ <skip />
+ <!-- no translation found for bluetooth_select_a2dp_codec_bits_per_sample_dialog_title (2096170505745650345) -->
+ <skip />
+ <!-- no translation found for bluetooth_select_a2dp_codec_channel_mode (884855779449390540) -->
+ <skip />
+ <!-- no translation found for bluetooth_select_a2dp_codec_channel_mode_dialog_title (4073812880900816325) -->
+ <skip />
+ <!-- no translation found for bluetooth_select_a2dp_codec_ldac_playback_quality (4846872213548295632) -->
+ <skip />
+ <!-- no translation found for bluetooth_select_a2dp_codec_ldac_playback_quality_dialog_title (3940973633342423717) -->
+ <skip />
<string name="wifi_display_certification_summary" msgid="1155182309166746973">"Pokaži opcije za certifikaciju Bežičnog prikaza"</string>
<string name="wifi_verbose_logging_summary" msgid="6615071616111731958">"Povećajte nivo Wi-Fi zapisivanja, pokazati po SSID RSSI Wi-Fi Picker"</string>
<string name="wifi_aggressive_handover_summary" msgid="6328455667642570371">"Kada je omogućeno, Wi-Fi će biti agresivniji u predavanju podatkovne veze mobilnoj, kada je Wi-Fi signal slab"</string>
diff --git a/packages/SettingsLib/res/values-ca/arrays.xml b/packages/SettingsLib/res/values-ca/arrays.xml
index 4c9ad46..909dfa3 100644
--- a/packages/SettingsLib/res/values-ca/arrays.xml
+++ b/packages/SettingsLib/res/values-ca/arrays.xml
@@ -58,6 +58,46 @@
<item msgid="3878793616631049349">"Utilitza la comprovació HDCP només per a contingut DRM"</item>
<item msgid="45075631231212732">"Utilitza sempre la comprovació HDCP"</item>
</string-array>
+ <!-- no translation found for bluetooth_a2dp_codec_titles:0 (1852387125374225729) -->
+ <!-- no translation found for bluetooth_a2dp_codec_titles:1 (7539690996561263909) -->
+ <!-- no translation found for bluetooth_a2dp_codec_titles:2 (4260844283202960798) -->
+ <!-- no translation found for bluetooth_a2dp_codec_titles:3 (7279983368484312990) -->
+ <!-- no translation found for bluetooth_a2dp_codec_titles:4 (2301339338870319651) -->
+ <!-- no translation found for bluetooth_a2dp_codec_summaries:0 (9072025520360316957) -->
+ <!-- no translation found for bluetooth_a2dp_codec_summaries:1 (6898329690939802290) -->
+ <!-- no translation found for bluetooth_a2dp_codec_summaries:2 (1190434429082395888) -->
+ <!-- no translation found for bluetooth_a2dp_codec_summaries:3 (649699003004233053) -->
+ <!-- no translation found for bluetooth_a2dp_codec_summaries:4 (508106435710925399) -->
+ <!-- no translation found for bluetooth_a2dp_codec_sample_rate_titles:0 (7102940318360468759) -->
+ <!-- no translation found for bluetooth_a2dp_codec_sample_rate_titles:1 (8895532488906185219) -->
+ <!-- no translation found for bluetooth_a2dp_codec_sample_rate_titles:2 (2909915718994807056) -->
+ <!-- no translation found for bluetooth_a2dp_codec_sample_rate_titles:3 (3347287377354164611) -->
+ <!-- no translation found for bluetooth_a2dp_codec_sample_rate_titles:4 (1234212100239985373) -->
+ <!-- no translation found for bluetooth_a2dp_codec_sample_rate_summaries:0 (7224433008148687313) -->
+ <!-- no translation found for bluetooth_a2dp_codec_sample_rate_summaries:1 (4482862757811638365) -->
+ <!-- no translation found for bluetooth_a2dp_codec_sample_rate_summaries:2 (354495328188724404) -->
+ <!-- no translation found for bluetooth_a2dp_codec_sample_rate_summaries:3 (7329816882213695083) -->
+ <!-- no translation found for bluetooth_a2dp_codec_sample_rate_summaries:4 (6967397666254430476) -->
+ <!-- no translation found for bluetooth_a2dp_codec_bits_per_sample_titles:0 (6694044160540313386) -->
+ <!-- no translation found for bluetooth_a2dp_codec_bits_per_sample_titles:1 (5618929009984956469) -->
+ <!-- no translation found for bluetooth_a2dp_codec_bits_per_sample_titles:2 (3412640499234627248) -->
+ <!-- no translation found for bluetooth_a2dp_codec_bits_per_sample_titles:3 (121583001492929387) -->
+ <!-- no translation found for bluetooth_a2dp_codec_bits_per_sample_summaries:0 (5091076677792306320) -->
+ <!-- no translation found for bluetooth_a2dp_codec_bits_per_sample_summaries:1 (4726688794884191540) -->
+ <!-- no translation found for bluetooth_a2dp_codec_bits_per_sample_summaries:2 (305344756485516870) -->
+ <!-- no translation found for bluetooth_a2dp_codec_bits_per_sample_summaries:3 (244568657919675099) -->
+ <!-- no translation found for bluetooth_a2dp_codec_channel_mode_titles:0 (13423709606339855) -->
+ <!-- no translation found for bluetooth_a2dp_codec_channel_mode_titles:1 (4106832974775067314) -->
+ <!-- no translation found for bluetooth_a2dp_codec_channel_mode_titles:2 (5571632958424639155) -->
+ <!-- no translation found for bluetooth_a2dp_codec_channel_mode_summaries:0 (8128478683963250130) -->
+ <!-- no translation found for bluetooth_a2dp_codec_channel_mode_summaries:1 (8900559293912978337) -->
+ <!-- no translation found for bluetooth_a2dp_codec_channel_mode_summaries:2 (8883739882299884241) -->
+ <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_titles:0 (2944889121850394020) -->
+ <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_titles:1 (138837449700903545) -->
+ <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_titles:2 (4777177307869441982) -->
+ <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_summaries:0 (172302906231378902) -->
+ <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_summaries:1 (9091111147684472529) -->
+ <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_summaries:2 (3367904477834831032) -->
<string-array name="select_logd_size_titles">
<item msgid="8665206199209698501">"No"</item>
<item msgid="1593289376502312923">"64 K"</item>
diff --git a/packages/SettingsLib/res/values-ca/strings.xml b/packages/SettingsLib/res/values-ca/strings.xml
index c360f87..d141f98 100644
--- a/packages/SettingsLib/res/values-ca/strings.xml
+++ b/packages/SettingsLib/res/values-ca/strings.xml
@@ -170,6 +170,26 @@
<string name="wifi_allow_scan_with_traffic" msgid="3601853081178265786">"Permet sempre cerca de Wi-Fi en ininerància"</string>
<string name="mobile_data_always_on" msgid="7745605759775320362">"Dades mòbils sempre actives"</string>
<string name="bluetooth_disable_absolute_volume" msgid="2660673801947898809">"Desactiva el volum absolut"</string>
+ <!-- no translation found for bluetooth_select_a2dp_codec_type (90597356942154882) -->
+ <skip />
+ <!-- no translation found for bluetooth_select_a2dp_codec_type_dialog_title (6470824182074383881) -->
+ <skip />
+ <!-- no translation found for bluetooth_select_a2dp_codec_sample_rate (4788245703824623062) -->
+ <skip />
+ <!-- no translation found for bluetooth_select_a2dp_codec_sample_rate_dialog_title (4263851572248033749) -->
+ <skip />
+ <!-- no translation found for bluetooth_select_a2dp_codec_bits_per_sample (2099645202720164141) -->
+ <skip />
+ <!-- no translation found for bluetooth_select_a2dp_codec_bits_per_sample_dialog_title (2096170505745650345) -->
+ <skip />
+ <!-- no translation found for bluetooth_select_a2dp_codec_channel_mode (884855779449390540) -->
+ <skip />
+ <!-- no translation found for bluetooth_select_a2dp_codec_channel_mode_dialog_title (4073812880900816325) -->
+ <skip />
+ <!-- no translation found for bluetooth_select_a2dp_codec_ldac_playback_quality (4846872213548295632) -->
+ <skip />
+ <!-- no translation found for bluetooth_select_a2dp_codec_ldac_playback_quality_dialog_title (3940973633342423717) -->
+ <skip />
<string name="wifi_display_certification_summary" msgid="1155182309166746973">"Mostra les opcions de certificació de pantalla sense fil"</string>
<string name="wifi_verbose_logging_summary" msgid="6615071616111731958">"Augmenta nivell de registre Wi‑Fi i mostra\'l per SSID RSSI al Selector de Wi‑Fi"</string>
<string name="wifi_aggressive_handover_summary" msgid="6328455667642570371">"Si s\'activa, la Wi-Fi serà més agressiva en transferir la connexió de dades al mòbil, si el senyal de la Wi-Fi no és estable"</string>
diff --git a/packages/SettingsLib/res/values-cs/arrays.xml b/packages/SettingsLib/res/values-cs/arrays.xml
index cf738c8..5c1b027 100644
--- a/packages/SettingsLib/res/values-cs/arrays.xml
+++ b/packages/SettingsLib/res/values-cs/arrays.xml
@@ -58,6 +58,46 @@
<item msgid="3878793616631049349">"Použít kontrolu HDCP pouze pro obsah DRM"</item>
<item msgid="45075631231212732">"Vždy používat kontrolu HDCP"</item>
</string-array>
+ <!-- no translation found for bluetooth_a2dp_codec_titles:0 (1852387125374225729) -->
+ <!-- no translation found for bluetooth_a2dp_codec_titles:1 (7539690996561263909) -->
+ <!-- no translation found for bluetooth_a2dp_codec_titles:2 (4260844283202960798) -->
+ <!-- no translation found for bluetooth_a2dp_codec_titles:3 (7279983368484312990) -->
+ <!-- no translation found for bluetooth_a2dp_codec_titles:4 (2301339338870319651) -->
+ <!-- no translation found for bluetooth_a2dp_codec_summaries:0 (9072025520360316957) -->
+ <!-- no translation found for bluetooth_a2dp_codec_summaries:1 (6898329690939802290) -->
+ <!-- no translation found for bluetooth_a2dp_codec_summaries:2 (1190434429082395888) -->
+ <!-- no translation found for bluetooth_a2dp_codec_summaries:3 (649699003004233053) -->
+ <!-- no translation found for bluetooth_a2dp_codec_summaries:4 (508106435710925399) -->
+ <!-- no translation found for bluetooth_a2dp_codec_sample_rate_titles:0 (7102940318360468759) -->
+ <!-- no translation found for bluetooth_a2dp_codec_sample_rate_titles:1 (8895532488906185219) -->
+ <!-- no translation found for bluetooth_a2dp_codec_sample_rate_titles:2 (2909915718994807056) -->
+ <!-- no translation found for bluetooth_a2dp_codec_sample_rate_titles:3 (3347287377354164611) -->
+ <!-- no translation found for bluetooth_a2dp_codec_sample_rate_titles:4 (1234212100239985373) -->
+ <!-- no translation found for bluetooth_a2dp_codec_sample_rate_summaries:0 (7224433008148687313) -->
+ <!-- no translation found for bluetooth_a2dp_codec_sample_rate_summaries:1 (4482862757811638365) -->
+ <!-- no translation found for bluetooth_a2dp_codec_sample_rate_summaries:2 (354495328188724404) -->
+ <!-- no translation found for bluetooth_a2dp_codec_sample_rate_summaries:3 (7329816882213695083) -->
+ <!-- no translation found for bluetooth_a2dp_codec_sample_rate_summaries:4 (6967397666254430476) -->
+ <!-- no translation found for bluetooth_a2dp_codec_bits_per_sample_titles:0 (6694044160540313386) -->
+ <!-- no translation found for bluetooth_a2dp_codec_bits_per_sample_titles:1 (5618929009984956469) -->
+ <!-- no translation found for bluetooth_a2dp_codec_bits_per_sample_titles:2 (3412640499234627248) -->
+ <!-- no translation found for bluetooth_a2dp_codec_bits_per_sample_titles:3 (121583001492929387) -->
+ <!-- no translation found for bluetooth_a2dp_codec_bits_per_sample_summaries:0 (5091076677792306320) -->
+ <!-- no translation found for bluetooth_a2dp_codec_bits_per_sample_summaries:1 (4726688794884191540) -->
+ <!-- no translation found for bluetooth_a2dp_codec_bits_per_sample_summaries:2 (305344756485516870) -->
+ <!-- no translation found for bluetooth_a2dp_codec_bits_per_sample_summaries:3 (244568657919675099) -->
+ <!-- no translation found for bluetooth_a2dp_codec_channel_mode_titles:0 (13423709606339855) -->
+ <!-- no translation found for bluetooth_a2dp_codec_channel_mode_titles:1 (4106832974775067314) -->
+ <!-- no translation found for bluetooth_a2dp_codec_channel_mode_titles:2 (5571632958424639155) -->
+ <!-- no translation found for bluetooth_a2dp_codec_channel_mode_summaries:0 (8128478683963250130) -->
+ <!-- no translation found for bluetooth_a2dp_codec_channel_mode_summaries:1 (8900559293912978337) -->
+ <!-- no translation found for bluetooth_a2dp_codec_channel_mode_summaries:2 (8883739882299884241) -->
+ <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_titles:0 (2944889121850394020) -->
+ <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_titles:1 (138837449700903545) -->
+ <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_titles:2 (4777177307869441982) -->
+ <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_summaries:0 (172302906231378902) -->
+ <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_summaries:1 (9091111147684472529) -->
+ <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_summaries:2 (3367904477834831032) -->
<string-array name="select_logd_size_titles">
<item msgid="8665206199209698501">"Vypnuto"</item>
<item msgid="1593289376502312923">"64 kB"</item>
diff --git a/packages/SettingsLib/res/values-cs/strings.xml b/packages/SettingsLib/res/values-cs/strings.xml
index 159a939..19c71a8 100644
--- a/packages/SettingsLib/res/values-cs/strings.xml
+++ b/packages/SettingsLib/res/values-cs/strings.xml
@@ -170,6 +170,26 @@
<string name="wifi_allow_scan_with_traffic" msgid="3601853081178265786">"Vždy povolit Wi-Fi roaming"</string>
<string name="mobile_data_always_on" msgid="7745605759775320362">"Mobilní data jsou vždy aktivní"</string>
<string name="bluetooth_disable_absolute_volume" msgid="2660673801947898809">"Zakázat absolutní hlasitost"</string>
+ <!-- no translation found for bluetooth_select_a2dp_codec_type (90597356942154882) -->
+ <skip />
+ <!-- no translation found for bluetooth_select_a2dp_codec_type_dialog_title (6470824182074383881) -->
+ <skip />
+ <!-- no translation found for bluetooth_select_a2dp_codec_sample_rate (4788245703824623062) -->
+ <skip />
+ <!-- no translation found for bluetooth_select_a2dp_codec_sample_rate_dialog_title (4263851572248033749) -->
+ <skip />
+ <!-- no translation found for bluetooth_select_a2dp_codec_bits_per_sample (2099645202720164141) -->
+ <skip />
+ <!-- no translation found for bluetooth_select_a2dp_codec_bits_per_sample_dialog_title (2096170505745650345) -->
+ <skip />
+ <!-- no translation found for bluetooth_select_a2dp_codec_channel_mode (884855779449390540) -->
+ <skip />
+ <!-- no translation found for bluetooth_select_a2dp_codec_channel_mode_dialog_title (4073812880900816325) -->
+ <skip />
+ <!-- no translation found for bluetooth_select_a2dp_codec_ldac_playback_quality (4846872213548295632) -->
+ <skip />
+ <!-- no translation found for bluetooth_select_a2dp_codec_ldac_playback_quality_dialog_title (3940973633342423717) -->
+ <skip />
<string name="wifi_display_certification_summary" msgid="1155182309166746973">"Zobrazit možnosti certifikace bezdrátového displeje"</string>
<string name="wifi_verbose_logging_summary" msgid="6615071616111731958">"Zvýšit úroveň protokolování Wi‑Fi zobrazenou v SSID a RSSI při výběru sítě Wi‑Fi."</string>
<string name="wifi_aggressive_handover_summary" msgid="6328455667642570371">"Pokud je tato možnost zapnuta, bude síť Wi-Fi agresivnější při předávání datového připojení mobilní síti při slabém signálu Wi-Fi."</string>
diff --git a/packages/SettingsLib/res/values-da/arrays.xml b/packages/SettingsLib/res/values-da/arrays.xml
index 2f82cf1..a6b1388 100644
--- a/packages/SettingsLib/res/values-da/arrays.xml
+++ b/packages/SettingsLib/res/values-da/arrays.xml
@@ -58,6 +58,46 @@
<item msgid="3878793616631049349">"Brug kun HDCP-kontrol ved DRM-indhold"</item>
<item msgid="45075631231212732">"Brug altid HDCP-kontrol"</item>
</string-array>
+ <!-- no translation found for bluetooth_a2dp_codec_titles:0 (1852387125374225729) -->
+ <!-- no translation found for bluetooth_a2dp_codec_titles:1 (7539690996561263909) -->
+ <!-- no translation found for bluetooth_a2dp_codec_titles:2 (4260844283202960798) -->
+ <!-- no translation found for bluetooth_a2dp_codec_titles:3 (7279983368484312990) -->
+ <!-- no translation found for bluetooth_a2dp_codec_titles:4 (2301339338870319651) -->
+ <!-- no translation found for bluetooth_a2dp_codec_summaries:0 (9072025520360316957) -->
+ <!-- no translation found for bluetooth_a2dp_codec_summaries:1 (6898329690939802290) -->
+ <!-- no translation found for bluetooth_a2dp_codec_summaries:2 (1190434429082395888) -->
+ <!-- no translation found for bluetooth_a2dp_codec_summaries:3 (649699003004233053) -->
+ <!-- no translation found for bluetooth_a2dp_codec_summaries:4 (508106435710925399) -->
+ <!-- no translation found for bluetooth_a2dp_codec_sample_rate_titles:0 (7102940318360468759) -->
+ <!-- no translation found for bluetooth_a2dp_codec_sample_rate_titles:1 (8895532488906185219) -->
+ <!-- no translation found for bluetooth_a2dp_codec_sample_rate_titles:2 (2909915718994807056) -->
+ <!-- no translation found for bluetooth_a2dp_codec_sample_rate_titles:3 (3347287377354164611) -->
+ <!-- no translation found for bluetooth_a2dp_codec_sample_rate_titles:4 (1234212100239985373) -->
+ <!-- no translation found for bluetooth_a2dp_codec_sample_rate_summaries:0 (7224433008148687313) -->
+ <!-- no translation found for bluetooth_a2dp_codec_sample_rate_summaries:1 (4482862757811638365) -->
+ <!-- no translation found for bluetooth_a2dp_codec_sample_rate_summaries:2 (354495328188724404) -->
+ <!-- no translation found for bluetooth_a2dp_codec_sample_rate_summaries:3 (7329816882213695083) -->
+ <!-- no translation found for bluetooth_a2dp_codec_sample_rate_summaries:4 (6967397666254430476) -->
+ <!-- no translation found for bluetooth_a2dp_codec_bits_per_sample_titles:0 (6694044160540313386) -->
+ <!-- no translation found for bluetooth_a2dp_codec_bits_per_sample_titles:1 (5618929009984956469) -->
+ <!-- no translation found for bluetooth_a2dp_codec_bits_per_sample_titles:2 (3412640499234627248) -->
+ <!-- no translation found for bluetooth_a2dp_codec_bits_per_sample_titles:3 (121583001492929387) -->
+ <!-- no translation found for bluetooth_a2dp_codec_bits_per_sample_summaries:0 (5091076677792306320) -->
+ <!-- no translation found for bluetooth_a2dp_codec_bits_per_sample_summaries:1 (4726688794884191540) -->
+ <!-- no translation found for bluetooth_a2dp_codec_bits_per_sample_summaries:2 (305344756485516870) -->
+ <!-- no translation found for bluetooth_a2dp_codec_bits_per_sample_summaries:3 (244568657919675099) -->
+ <!-- no translation found for bluetooth_a2dp_codec_channel_mode_titles:0 (13423709606339855) -->
+ <!-- no translation found for bluetooth_a2dp_codec_channel_mode_titles:1 (4106832974775067314) -->
+ <!-- no translation found for bluetooth_a2dp_codec_channel_mode_titles:2 (5571632958424639155) -->
+ <!-- no translation found for bluetooth_a2dp_codec_channel_mode_summaries:0 (8128478683963250130) -->
+ <!-- no translation found for bluetooth_a2dp_codec_channel_mode_summaries:1 (8900559293912978337) -->
+ <!-- no translation found for bluetooth_a2dp_codec_channel_mode_summaries:2 (8883739882299884241) -->
+ <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_titles:0 (2944889121850394020) -->
+ <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_titles:1 (138837449700903545) -->
+ <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_titles:2 (4777177307869441982) -->
+ <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_summaries:0 (172302906231378902) -->
+ <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_summaries:1 (9091111147684472529) -->
+ <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_summaries:2 (3367904477834831032) -->
<string-array name="select_logd_size_titles">
<item msgid="8665206199209698501">"Fra"</item>
<item msgid="1593289376502312923">"64 kB"</item>
diff --git a/packages/SettingsLib/res/values-da/strings.xml b/packages/SettingsLib/res/values-da/strings.xml
index 49f1899..31e747a 100644
--- a/packages/SettingsLib/res/values-da/strings.xml
+++ b/packages/SettingsLib/res/values-da/strings.xml
@@ -170,6 +170,26 @@
<string name="wifi_allow_scan_with_traffic" msgid="3601853081178265786">"Tillad altid scanning af Wi-Fi-roaming"</string>
<string name="mobile_data_always_on" msgid="7745605759775320362">"Mobildata altid aktiveret"</string>
<string name="bluetooth_disable_absolute_volume" msgid="2660673801947898809">"Deaktiver absolut lydstyrke"</string>
+ <!-- no translation found for bluetooth_select_a2dp_codec_type (90597356942154882) -->
+ <skip />
+ <!-- no translation found for bluetooth_select_a2dp_codec_type_dialog_title (6470824182074383881) -->
+ <skip />
+ <!-- no translation found for bluetooth_select_a2dp_codec_sample_rate (4788245703824623062) -->
+ <skip />
+ <!-- no translation found for bluetooth_select_a2dp_codec_sample_rate_dialog_title (4263851572248033749) -->
+ <skip />
+ <!-- no translation found for bluetooth_select_a2dp_codec_bits_per_sample (2099645202720164141) -->
+ <skip />
+ <!-- no translation found for bluetooth_select_a2dp_codec_bits_per_sample_dialog_title (2096170505745650345) -->
+ <skip />
+ <!-- no translation found for bluetooth_select_a2dp_codec_channel_mode (884855779449390540) -->
+ <skip />
+ <!-- no translation found for bluetooth_select_a2dp_codec_channel_mode_dialog_title (4073812880900816325) -->
+ <skip />
+ <!-- no translation found for bluetooth_select_a2dp_codec_ldac_playback_quality (4846872213548295632) -->
+ <skip />
+ <!-- no translation found for bluetooth_select_a2dp_codec_ldac_playback_quality_dialog_title (3940973633342423717) -->
+ <skip />
<string name="wifi_display_certification_summary" msgid="1155182309166746973">"Vis valgmuligheder for certificering af trådløs skærm"</string>
<string name="wifi_verbose_logging_summary" msgid="6615071616111731958">"Øg mængden af Wi‑Fi-logføring. Vis opdelt efter SSID RSSI i Wi‑Fi-vælgeren"</string>
<string name="wifi_aggressive_handover_summary" msgid="6328455667642570371">"Når dette er aktiveret, gennemtvinges en overdragelse af dataforbindelsen fra Wi-Fi til mobilnetværk, når Wi-Fi-signalet er svagt"</string>
diff --git a/packages/SettingsLib/res/values-de/arrays.xml b/packages/SettingsLib/res/values-de/arrays.xml
index f5423ba..328f1fe 100644
--- a/packages/SettingsLib/res/values-de/arrays.xml
+++ b/packages/SettingsLib/res/values-de/arrays.xml
@@ -58,6 +58,46 @@
<item msgid="3878793616631049349">"HDCP-Prüfung nur für DRM-Inhalte verwenden"</item>
<item msgid="45075631231212732">"HDCP-Prüfung immer verwenden"</item>
</string-array>
+ <!-- no translation found for bluetooth_a2dp_codec_titles:0 (1852387125374225729) -->
+ <!-- no translation found for bluetooth_a2dp_codec_titles:1 (7539690996561263909) -->
+ <!-- no translation found for bluetooth_a2dp_codec_titles:2 (4260844283202960798) -->
+ <!-- no translation found for bluetooth_a2dp_codec_titles:3 (7279983368484312990) -->
+ <!-- no translation found for bluetooth_a2dp_codec_titles:4 (2301339338870319651) -->
+ <!-- no translation found for bluetooth_a2dp_codec_summaries:0 (9072025520360316957) -->
+ <!-- no translation found for bluetooth_a2dp_codec_summaries:1 (6898329690939802290) -->
+ <!-- no translation found for bluetooth_a2dp_codec_summaries:2 (1190434429082395888) -->
+ <!-- no translation found for bluetooth_a2dp_codec_summaries:3 (649699003004233053) -->
+ <!-- no translation found for bluetooth_a2dp_codec_summaries:4 (508106435710925399) -->
+ <!-- no translation found for bluetooth_a2dp_codec_sample_rate_titles:0 (7102940318360468759) -->
+ <!-- no translation found for bluetooth_a2dp_codec_sample_rate_titles:1 (8895532488906185219) -->
+ <!-- no translation found for bluetooth_a2dp_codec_sample_rate_titles:2 (2909915718994807056) -->
+ <!-- no translation found for bluetooth_a2dp_codec_sample_rate_titles:3 (3347287377354164611) -->
+ <!-- no translation found for bluetooth_a2dp_codec_sample_rate_titles:4 (1234212100239985373) -->
+ <!-- no translation found for bluetooth_a2dp_codec_sample_rate_summaries:0 (7224433008148687313) -->
+ <!-- no translation found for bluetooth_a2dp_codec_sample_rate_summaries:1 (4482862757811638365) -->
+ <!-- no translation found for bluetooth_a2dp_codec_sample_rate_summaries:2 (354495328188724404) -->
+ <!-- no translation found for bluetooth_a2dp_codec_sample_rate_summaries:3 (7329816882213695083) -->
+ <!-- no translation found for bluetooth_a2dp_codec_sample_rate_summaries:4 (6967397666254430476) -->
+ <!-- no translation found for bluetooth_a2dp_codec_bits_per_sample_titles:0 (6694044160540313386) -->
+ <!-- no translation found for bluetooth_a2dp_codec_bits_per_sample_titles:1 (5618929009984956469) -->
+ <!-- no translation found for bluetooth_a2dp_codec_bits_per_sample_titles:2 (3412640499234627248) -->
+ <!-- no translation found for bluetooth_a2dp_codec_bits_per_sample_titles:3 (121583001492929387) -->
+ <!-- no translation found for bluetooth_a2dp_codec_bits_per_sample_summaries:0 (5091076677792306320) -->
+ <!-- no translation found for bluetooth_a2dp_codec_bits_per_sample_summaries:1 (4726688794884191540) -->
+ <!-- no translation found for bluetooth_a2dp_codec_bits_per_sample_summaries:2 (305344756485516870) -->
+ <!-- no translation found for bluetooth_a2dp_codec_bits_per_sample_summaries:3 (244568657919675099) -->
+ <!-- no translation found for bluetooth_a2dp_codec_channel_mode_titles:0 (13423709606339855) -->
+ <!-- no translation found for bluetooth_a2dp_codec_channel_mode_titles:1 (4106832974775067314) -->
+ <!-- no translation found for bluetooth_a2dp_codec_channel_mode_titles:2 (5571632958424639155) -->
+ <!-- no translation found for bluetooth_a2dp_codec_channel_mode_summaries:0 (8128478683963250130) -->
+ <!-- no translation found for bluetooth_a2dp_codec_channel_mode_summaries:1 (8900559293912978337) -->
+ <!-- no translation found for bluetooth_a2dp_codec_channel_mode_summaries:2 (8883739882299884241) -->
+ <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_titles:0 (2944889121850394020) -->
+ <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_titles:1 (138837449700903545) -->
+ <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_titles:2 (4777177307869441982) -->
+ <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_summaries:0 (172302906231378902) -->
+ <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_summaries:1 (9091111147684472529) -->
+ <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_summaries:2 (3367904477834831032) -->
<string-array name="select_logd_size_titles">
<item msgid="8665206199209698501">"Aus"</item>
<item msgid="1593289376502312923">"64.000"</item>
diff --git a/packages/SettingsLib/res/values-de/strings.xml b/packages/SettingsLib/res/values-de/strings.xml
index 95ac313..65f72a2 100644
--- a/packages/SettingsLib/res/values-de/strings.xml
+++ b/packages/SettingsLib/res/values-de/strings.xml
@@ -170,6 +170,26 @@
<string name="wifi_allow_scan_with_traffic" msgid="3601853081178265786">"WLAN-Roamingsuchen immer zulassen"</string>
<string name="mobile_data_always_on" msgid="7745605759775320362">"Mobile Datennutzung immer aktiviert"</string>
<string name="bluetooth_disable_absolute_volume" msgid="2660673801947898809">"Maximallautstärke deaktivieren"</string>
+ <!-- no translation found for bluetooth_select_a2dp_codec_type (90597356942154882) -->
+ <skip />
+ <!-- no translation found for bluetooth_select_a2dp_codec_type_dialog_title (6470824182074383881) -->
+ <skip />
+ <!-- no translation found for bluetooth_select_a2dp_codec_sample_rate (4788245703824623062) -->
+ <skip />
+ <!-- no translation found for bluetooth_select_a2dp_codec_sample_rate_dialog_title (4263851572248033749) -->
+ <skip />
+ <!-- no translation found for bluetooth_select_a2dp_codec_bits_per_sample (2099645202720164141) -->
+ <skip />
+ <!-- no translation found for bluetooth_select_a2dp_codec_bits_per_sample_dialog_title (2096170505745650345) -->
+ <skip />
+ <!-- no translation found for bluetooth_select_a2dp_codec_channel_mode (884855779449390540) -->
+ <skip />
+ <!-- no translation found for bluetooth_select_a2dp_codec_channel_mode_dialog_title (4073812880900816325) -->
+ <skip />
+ <!-- no translation found for bluetooth_select_a2dp_codec_ldac_playback_quality (4846872213548295632) -->
+ <skip />
+ <!-- no translation found for bluetooth_select_a2dp_codec_ldac_playback_quality_dialog_title (3940973633342423717) -->
+ <skip />
<string name="wifi_display_certification_summary" msgid="1155182309166746973">"Optionen zur Zertifizierung für kabellose Übertragung anzeigen"</string>
<string name="wifi_verbose_logging_summary" msgid="6615071616111731958">"Level für WLAN-Protokollierung erhöhen, in WiFi Picker pro SSID-RSSI anzeigen"</string>
<string name="wifi_aggressive_handover_summary" msgid="6328455667642570371">"Wenn diese Option aktiviert ist, ist WLAN bei schwachem Signal bei der Übergabe der Datenverbindung an den Mobilfunk aggressiver."</string>
diff --git a/packages/SettingsLib/res/values-el/arrays.xml b/packages/SettingsLib/res/values-el/arrays.xml
index 9a8d48e..74f59f16 100644
--- a/packages/SettingsLib/res/values-el/arrays.xml
+++ b/packages/SettingsLib/res/values-el/arrays.xml
@@ -58,6 +58,46 @@
<item msgid="3878793616631049349">"Χρήση ελέγχου HDCP μόνο για περιεχόμενο DRM"</item>
<item msgid="45075631231212732">"Να χρησιμοποιείται πάντα έλεγχος HDCP"</item>
</string-array>
+ <!-- no translation found for bluetooth_a2dp_codec_titles:0 (1852387125374225729) -->
+ <!-- no translation found for bluetooth_a2dp_codec_titles:1 (7539690996561263909) -->
+ <!-- no translation found for bluetooth_a2dp_codec_titles:2 (4260844283202960798) -->
+ <!-- no translation found for bluetooth_a2dp_codec_titles:3 (7279983368484312990) -->
+ <!-- no translation found for bluetooth_a2dp_codec_titles:4 (2301339338870319651) -->
+ <!-- no translation found for bluetooth_a2dp_codec_summaries:0 (9072025520360316957) -->
+ <!-- no translation found for bluetooth_a2dp_codec_summaries:1 (6898329690939802290) -->
+ <!-- no translation found for bluetooth_a2dp_codec_summaries:2 (1190434429082395888) -->
+ <!-- no translation found for bluetooth_a2dp_codec_summaries:3 (649699003004233053) -->
+ <!-- no translation found for bluetooth_a2dp_codec_summaries:4 (508106435710925399) -->
+ <!-- no translation found for bluetooth_a2dp_codec_sample_rate_titles:0 (7102940318360468759) -->
+ <!-- no translation found for bluetooth_a2dp_codec_sample_rate_titles:1 (8895532488906185219) -->
+ <!-- no translation found for bluetooth_a2dp_codec_sample_rate_titles:2 (2909915718994807056) -->
+ <!-- no translation found for bluetooth_a2dp_codec_sample_rate_titles:3 (3347287377354164611) -->
+ <!-- no translation found for bluetooth_a2dp_codec_sample_rate_titles:4 (1234212100239985373) -->
+ <!-- no translation found for bluetooth_a2dp_codec_sample_rate_summaries:0 (7224433008148687313) -->
+ <!-- no translation found for bluetooth_a2dp_codec_sample_rate_summaries:1 (4482862757811638365) -->
+ <!-- no translation found for bluetooth_a2dp_codec_sample_rate_summaries:2 (354495328188724404) -->
+ <!-- no translation found for bluetooth_a2dp_codec_sample_rate_summaries:3 (7329816882213695083) -->
+ <!-- no translation found for bluetooth_a2dp_codec_sample_rate_summaries:4 (6967397666254430476) -->
+ <!-- no translation found for bluetooth_a2dp_codec_bits_per_sample_titles:0 (6694044160540313386) -->
+ <!-- no translation found for bluetooth_a2dp_codec_bits_per_sample_titles:1 (5618929009984956469) -->
+ <!-- no translation found for bluetooth_a2dp_codec_bits_per_sample_titles:2 (3412640499234627248) -->
+ <!-- no translation found for bluetooth_a2dp_codec_bits_per_sample_titles:3 (121583001492929387) -->
+ <!-- no translation found for bluetooth_a2dp_codec_bits_per_sample_summaries:0 (5091076677792306320) -->
+ <!-- no translation found for bluetooth_a2dp_codec_bits_per_sample_summaries:1 (4726688794884191540) -->
+ <!-- no translation found for bluetooth_a2dp_codec_bits_per_sample_summaries:2 (305344756485516870) -->
+ <!-- no translation found for bluetooth_a2dp_codec_bits_per_sample_summaries:3 (244568657919675099) -->
+ <!-- no translation found for bluetooth_a2dp_codec_channel_mode_titles:0 (13423709606339855) -->
+ <!-- no translation found for bluetooth_a2dp_codec_channel_mode_titles:1 (4106832974775067314) -->
+ <!-- no translation found for bluetooth_a2dp_codec_channel_mode_titles:2 (5571632958424639155) -->
+ <!-- no translation found for bluetooth_a2dp_codec_channel_mode_summaries:0 (8128478683963250130) -->
+ <!-- no translation found for bluetooth_a2dp_codec_channel_mode_summaries:1 (8900559293912978337) -->
+ <!-- no translation found for bluetooth_a2dp_codec_channel_mode_summaries:2 (8883739882299884241) -->
+ <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_titles:0 (2944889121850394020) -->
+ <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_titles:1 (138837449700903545) -->
+ <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_titles:2 (4777177307869441982) -->
+ <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_summaries:0 (172302906231378902) -->
+ <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_summaries:1 (9091111147684472529) -->
+ <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_summaries:2 (3367904477834831032) -->
<string-array name="select_logd_size_titles">
<item msgid="8665206199209698501">"Ανενεργό"</item>
<item msgid="1593289376502312923">"64 K"</item>
diff --git a/packages/SettingsLib/res/values-el/strings.xml b/packages/SettingsLib/res/values-el/strings.xml
index f331080..f56f1aa 100644
--- a/packages/SettingsLib/res/values-el/strings.xml
+++ b/packages/SettingsLib/res/values-el/strings.xml
@@ -170,6 +170,26 @@
<string name="wifi_allow_scan_with_traffic" msgid="3601853081178265786">"Να επιτρέπεται πάντα η σάρωση Wi-Fi κατά την περιαγωγή"</string>
<string name="mobile_data_always_on" msgid="7745605759775320362">"Πάντα ενεργά δεδομένα κινητής τηλεφωνίας"</string>
<string name="bluetooth_disable_absolute_volume" msgid="2660673801947898809">"Απενεργοποίηση απόλυτης έντασης"</string>
+ <!-- no translation found for bluetooth_select_a2dp_codec_type (90597356942154882) -->
+ <skip />
+ <!-- no translation found for bluetooth_select_a2dp_codec_type_dialog_title (6470824182074383881) -->
+ <skip />
+ <!-- no translation found for bluetooth_select_a2dp_codec_sample_rate (4788245703824623062) -->
+ <skip />
+ <!-- no translation found for bluetooth_select_a2dp_codec_sample_rate_dialog_title (4263851572248033749) -->
+ <skip />
+ <!-- no translation found for bluetooth_select_a2dp_codec_bits_per_sample (2099645202720164141) -->
+ <skip />
+ <!-- no translation found for bluetooth_select_a2dp_codec_bits_per_sample_dialog_title (2096170505745650345) -->
+ <skip />
+ <!-- no translation found for bluetooth_select_a2dp_codec_channel_mode (884855779449390540) -->
+ <skip />
+ <!-- no translation found for bluetooth_select_a2dp_codec_channel_mode_dialog_title (4073812880900816325) -->
+ <skip />
+ <!-- no translation found for bluetooth_select_a2dp_codec_ldac_playback_quality (4846872213548295632) -->
+ <skip />
+ <!-- no translation found for bluetooth_select_a2dp_codec_ldac_playback_quality_dialog_title (3940973633342423717) -->
+ <skip />
<string name="wifi_display_certification_summary" msgid="1155182309166746973">"Εμφάνιση επιλογών για πιστοποίηση ασύρματης οθόνης"</string>
<string name="wifi_verbose_logging_summary" msgid="6615071616111731958">"Αύξηση επιπέδου καταγ. Wi-Fi, εμφάνιση ανά SSID RSSI στο εργαλείο επιλογής Wi-Fi"</string>
<string name="wifi_aggressive_handover_summary" msgid="6328455667642570371">"Όταν είναι ενεργό, το Wi-Fi θα μεταβιβάζει πιο επιθετικά τη σύνδ.δεδομένων σε δίκτυο κινητής τηλ., όταν το σήμα Wi-Fi είναι χαμηλό"</string>
diff --git a/packages/SettingsLib/res/values-en-rAU/arrays.xml b/packages/SettingsLib/res/values-en-rAU/arrays.xml
index 6093051..c3cd50e 100644
--- a/packages/SettingsLib/res/values-en-rAU/arrays.xml
+++ b/packages/SettingsLib/res/values-en-rAU/arrays.xml
@@ -58,6 +58,46 @@
<item msgid="3878793616631049349">"Use HDCP checking for DRM content only"</item>
<item msgid="45075631231212732">"Always use HDCP checking"</item>
</string-array>
+ <!-- no translation found for bluetooth_a2dp_codec_titles:0 (1852387125374225729) -->
+ <!-- no translation found for bluetooth_a2dp_codec_titles:1 (7539690996561263909) -->
+ <!-- no translation found for bluetooth_a2dp_codec_titles:2 (4260844283202960798) -->
+ <!-- no translation found for bluetooth_a2dp_codec_titles:3 (7279983368484312990) -->
+ <!-- no translation found for bluetooth_a2dp_codec_titles:4 (2301339338870319651) -->
+ <!-- no translation found for bluetooth_a2dp_codec_summaries:0 (9072025520360316957) -->
+ <!-- no translation found for bluetooth_a2dp_codec_summaries:1 (6898329690939802290) -->
+ <!-- no translation found for bluetooth_a2dp_codec_summaries:2 (1190434429082395888) -->
+ <!-- no translation found for bluetooth_a2dp_codec_summaries:3 (649699003004233053) -->
+ <!-- no translation found for bluetooth_a2dp_codec_summaries:4 (508106435710925399) -->
+ <!-- no translation found for bluetooth_a2dp_codec_sample_rate_titles:0 (7102940318360468759) -->
+ <!-- no translation found for bluetooth_a2dp_codec_sample_rate_titles:1 (8895532488906185219) -->
+ <!-- no translation found for bluetooth_a2dp_codec_sample_rate_titles:2 (2909915718994807056) -->
+ <!-- no translation found for bluetooth_a2dp_codec_sample_rate_titles:3 (3347287377354164611) -->
+ <!-- no translation found for bluetooth_a2dp_codec_sample_rate_titles:4 (1234212100239985373) -->
+ <!-- no translation found for bluetooth_a2dp_codec_sample_rate_summaries:0 (7224433008148687313) -->
+ <!-- no translation found for bluetooth_a2dp_codec_sample_rate_summaries:1 (4482862757811638365) -->
+ <!-- no translation found for bluetooth_a2dp_codec_sample_rate_summaries:2 (354495328188724404) -->
+ <!-- no translation found for bluetooth_a2dp_codec_sample_rate_summaries:3 (7329816882213695083) -->
+ <!-- no translation found for bluetooth_a2dp_codec_sample_rate_summaries:4 (6967397666254430476) -->
+ <!-- no translation found for bluetooth_a2dp_codec_bits_per_sample_titles:0 (6694044160540313386) -->
+ <!-- no translation found for bluetooth_a2dp_codec_bits_per_sample_titles:1 (5618929009984956469) -->
+ <!-- no translation found for bluetooth_a2dp_codec_bits_per_sample_titles:2 (3412640499234627248) -->
+ <!-- no translation found for bluetooth_a2dp_codec_bits_per_sample_titles:3 (121583001492929387) -->
+ <!-- no translation found for bluetooth_a2dp_codec_bits_per_sample_summaries:0 (5091076677792306320) -->
+ <!-- no translation found for bluetooth_a2dp_codec_bits_per_sample_summaries:1 (4726688794884191540) -->
+ <!-- no translation found for bluetooth_a2dp_codec_bits_per_sample_summaries:2 (305344756485516870) -->
+ <!-- no translation found for bluetooth_a2dp_codec_bits_per_sample_summaries:3 (244568657919675099) -->
+ <!-- no translation found for bluetooth_a2dp_codec_channel_mode_titles:0 (13423709606339855) -->
+ <!-- no translation found for bluetooth_a2dp_codec_channel_mode_titles:1 (4106832974775067314) -->
+ <!-- no translation found for bluetooth_a2dp_codec_channel_mode_titles:2 (5571632958424639155) -->
+ <!-- no translation found for bluetooth_a2dp_codec_channel_mode_summaries:0 (8128478683963250130) -->
+ <!-- no translation found for bluetooth_a2dp_codec_channel_mode_summaries:1 (8900559293912978337) -->
+ <!-- no translation found for bluetooth_a2dp_codec_channel_mode_summaries:2 (8883739882299884241) -->
+ <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_titles:0 (2944889121850394020) -->
+ <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_titles:1 (138837449700903545) -->
+ <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_titles:2 (4777177307869441982) -->
+ <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_summaries:0 (172302906231378902) -->
+ <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_summaries:1 (9091111147684472529) -->
+ <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_summaries:2 (3367904477834831032) -->
<string-array name="select_logd_size_titles">
<item msgid="8665206199209698501">"Off"</item>
<item msgid="1593289376502312923">"64 K"</item>
diff --git a/packages/SettingsLib/res/values-en-rAU/strings.xml b/packages/SettingsLib/res/values-en-rAU/strings.xml
index e27822f..8c56ede 100644
--- a/packages/SettingsLib/res/values-en-rAU/strings.xml
+++ b/packages/SettingsLib/res/values-en-rAU/strings.xml
@@ -170,6 +170,26 @@
<string name="wifi_allow_scan_with_traffic" msgid="3601853081178265786">"Always allow Wi‑Fi Roam Scans"</string>
<string name="mobile_data_always_on" msgid="7745605759775320362">"Mobile data always active"</string>
<string name="bluetooth_disable_absolute_volume" msgid="2660673801947898809">"Disable absolute volume"</string>
+ <!-- no translation found for bluetooth_select_a2dp_codec_type (90597356942154882) -->
+ <skip />
+ <!-- no translation found for bluetooth_select_a2dp_codec_type_dialog_title (6470824182074383881) -->
+ <skip />
+ <!-- no translation found for bluetooth_select_a2dp_codec_sample_rate (4788245703824623062) -->
+ <skip />
+ <!-- no translation found for bluetooth_select_a2dp_codec_sample_rate_dialog_title (4263851572248033749) -->
+ <skip />
+ <!-- no translation found for bluetooth_select_a2dp_codec_bits_per_sample (2099645202720164141) -->
+ <skip />
+ <!-- no translation found for bluetooth_select_a2dp_codec_bits_per_sample_dialog_title (2096170505745650345) -->
+ <skip />
+ <!-- no translation found for bluetooth_select_a2dp_codec_channel_mode (884855779449390540) -->
+ <skip />
+ <!-- no translation found for bluetooth_select_a2dp_codec_channel_mode_dialog_title (4073812880900816325) -->
+ <skip />
+ <!-- no translation found for bluetooth_select_a2dp_codec_ldac_playback_quality (4846872213548295632) -->
+ <skip />
+ <!-- no translation found for bluetooth_select_a2dp_codec_ldac_playback_quality_dialog_title (3940973633342423717) -->
+ <skip />
<string name="wifi_display_certification_summary" msgid="1155182309166746973">"Show options for wireless display certification"</string>
<string name="wifi_verbose_logging_summary" msgid="6615071616111731958">"Increase Wi‑Fi logging level, show per SSID RSSI in Wi‑Fi Picker"</string>
<string name="wifi_aggressive_handover_summary" msgid="6328455667642570371">"When enabled, Wi‑Fi will be more aggressive in handing over the data connection to Mobile, when Wi‑Fi signal is low"</string>
diff --git a/packages/SettingsLib/res/values-en-rGB/arrays.xml b/packages/SettingsLib/res/values-en-rGB/arrays.xml
index 6093051..c3cd50e 100644
--- a/packages/SettingsLib/res/values-en-rGB/arrays.xml
+++ b/packages/SettingsLib/res/values-en-rGB/arrays.xml
@@ -58,6 +58,46 @@
<item msgid="3878793616631049349">"Use HDCP checking for DRM content only"</item>
<item msgid="45075631231212732">"Always use HDCP checking"</item>
</string-array>
+ <!-- no translation found for bluetooth_a2dp_codec_titles:0 (1852387125374225729) -->
+ <!-- no translation found for bluetooth_a2dp_codec_titles:1 (7539690996561263909) -->
+ <!-- no translation found for bluetooth_a2dp_codec_titles:2 (4260844283202960798) -->
+ <!-- no translation found for bluetooth_a2dp_codec_titles:3 (7279983368484312990) -->
+ <!-- no translation found for bluetooth_a2dp_codec_titles:4 (2301339338870319651) -->
+ <!-- no translation found for bluetooth_a2dp_codec_summaries:0 (9072025520360316957) -->
+ <!-- no translation found for bluetooth_a2dp_codec_summaries:1 (6898329690939802290) -->
+ <!-- no translation found for bluetooth_a2dp_codec_summaries:2 (1190434429082395888) -->
+ <!-- no translation found for bluetooth_a2dp_codec_summaries:3 (649699003004233053) -->
+ <!-- no translation found for bluetooth_a2dp_codec_summaries:4 (508106435710925399) -->
+ <!-- no translation found for bluetooth_a2dp_codec_sample_rate_titles:0 (7102940318360468759) -->
+ <!-- no translation found for bluetooth_a2dp_codec_sample_rate_titles:1 (8895532488906185219) -->
+ <!-- no translation found for bluetooth_a2dp_codec_sample_rate_titles:2 (2909915718994807056) -->
+ <!-- no translation found for bluetooth_a2dp_codec_sample_rate_titles:3 (3347287377354164611) -->
+ <!-- no translation found for bluetooth_a2dp_codec_sample_rate_titles:4 (1234212100239985373) -->
+ <!-- no translation found for bluetooth_a2dp_codec_sample_rate_summaries:0 (7224433008148687313) -->
+ <!-- no translation found for bluetooth_a2dp_codec_sample_rate_summaries:1 (4482862757811638365) -->
+ <!-- no translation found for bluetooth_a2dp_codec_sample_rate_summaries:2 (354495328188724404) -->
+ <!-- no translation found for bluetooth_a2dp_codec_sample_rate_summaries:3 (7329816882213695083) -->
+ <!-- no translation found for bluetooth_a2dp_codec_sample_rate_summaries:4 (6967397666254430476) -->
+ <!-- no translation found for bluetooth_a2dp_codec_bits_per_sample_titles:0 (6694044160540313386) -->
+ <!-- no translation found for bluetooth_a2dp_codec_bits_per_sample_titles:1 (5618929009984956469) -->
+ <!-- no translation found for bluetooth_a2dp_codec_bits_per_sample_titles:2 (3412640499234627248) -->
+ <!-- no translation found for bluetooth_a2dp_codec_bits_per_sample_titles:3 (121583001492929387) -->
+ <!-- no translation found for bluetooth_a2dp_codec_bits_per_sample_summaries:0 (5091076677792306320) -->
+ <!-- no translation found for bluetooth_a2dp_codec_bits_per_sample_summaries:1 (4726688794884191540) -->
+ <!-- no translation found for bluetooth_a2dp_codec_bits_per_sample_summaries:2 (305344756485516870) -->
+ <!-- no translation found for bluetooth_a2dp_codec_bits_per_sample_summaries:3 (244568657919675099) -->
+ <!-- no translation found for bluetooth_a2dp_codec_channel_mode_titles:0 (13423709606339855) -->
+ <!-- no translation found for bluetooth_a2dp_codec_channel_mode_titles:1 (4106832974775067314) -->
+ <!-- no translation found for bluetooth_a2dp_codec_channel_mode_titles:2 (5571632958424639155) -->
+ <!-- no translation found for bluetooth_a2dp_codec_channel_mode_summaries:0 (8128478683963250130) -->
+ <!-- no translation found for bluetooth_a2dp_codec_channel_mode_summaries:1 (8900559293912978337) -->
+ <!-- no translation found for bluetooth_a2dp_codec_channel_mode_summaries:2 (8883739882299884241) -->
+ <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_titles:0 (2944889121850394020) -->
+ <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_titles:1 (138837449700903545) -->
+ <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_titles:2 (4777177307869441982) -->
+ <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_summaries:0 (172302906231378902) -->
+ <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_summaries:1 (9091111147684472529) -->
+ <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_summaries:2 (3367904477834831032) -->
<string-array name="select_logd_size_titles">
<item msgid="8665206199209698501">"Off"</item>
<item msgid="1593289376502312923">"64 K"</item>
diff --git a/packages/SettingsLib/res/values-en-rGB/strings.xml b/packages/SettingsLib/res/values-en-rGB/strings.xml
index e27822f..8c56ede 100644
--- a/packages/SettingsLib/res/values-en-rGB/strings.xml
+++ b/packages/SettingsLib/res/values-en-rGB/strings.xml
@@ -170,6 +170,26 @@
<string name="wifi_allow_scan_with_traffic" msgid="3601853081178265786">"Always allow Wi‑Fi Roam Scans"</string>
<string name="mobile_data_always_on" msgid="7745605759775320362">"Mobile data always active"</string>
<string name="bluetooth_disable_absolute_volume" msgid="2660673801947898809">"Disable absolute volume"</string>
+ <!-- no translation found for bluetooth_select_a2dp_codec_type (90597356942154882) -->
+ <skip />
+ <!-- no translation found for bluetooth_select_a2dp_codec_type_dialog_title (6470824182074383881) -->
+ <skip />
+ <!-- no translation found for bluetooth_select_a2dp_codec_sample_rate (4788245703824623062) -->
+ <skip />
+ <!-- no translation found for bluetooth_select_a2dp_codec_sample_rate_dialog_title (4263851572248033749) -->
+ <skip />
+ <!-- no translation found for bluetooth_select_a2dp_codec_bits_per_sample (2099645202720164141) -->
+ <skip />
+ <!-- no translation found for bluetooth_select_a2dp_codec_bits_per_sample_dialog_title (2096170505745650345) -->
+ <skip />
+ <!-- no translation found for bluetooth_select_a2dp_codec_channel_mode (884855779449390540) -->
+ <skip />
+ <!-- no translation found for bluetooth_select_a2dp_codec_channel_mode_dialog_title (4073812880900816325) -->
+ <skip />
+ <!-- no translation found for bluetooth_select_a2dp_codec_ldac_playback_quality (4846872213548295632) -->
+ <skip />
+ <!-- no translation found for bluetooth_select_a2dp_codec_ldac_playback_quality_dialog_title (3940973633342423717) -->
+ <skip />
<string name="wifi_display_certification_summary" msgid="1155182309166746973">"Show options for wireless display certification"</string>
<string name="wifi_verbose_logging_summary" msgid="6615071616111731958">"Increase Wi‑Fi logging level, show per SSID RSSI in Wi‑Fi Picker"</string>
<string name="wifi_aggressive_handover_summary" msgid="6328455667642570371">"When enabled, Wi‑Fi will be more aggressive in handing over the data connection to Mobile, when Wi‑Fi signal is low"</string>
diff --git a/packages/SettingsLib/res/values-en-rIN/arrays.xml b/packages/SettingsLib/res/values-en-rIN/arrays.xml
index 6093051..c3cd50e 100644
--- a/packages/SettingsLib/res/values-en-rIN/arrays.xml
+++ b/packages/SettingsLib/res/values-en-rIN/arrays.xml
@@ -58,6 +58,46 @@
<item msgid="3878793616631049349">"Use HDCP checking for DRM content only"</item>
<item msgid="45075631231212732">"Always use HDCP checking"</item>
</string-array>
+ <!-- no translation found for bluetooth_a2dp_codec_titles:0 (1852387125374225729) -->
+ <!-- no translation found for bluetooth_a2dp_codec_titles:1 (7539690996561263909) -->
+ <!-- no translation found for bluetooth_a2dp_codec_titles:2 (4260844283202960798) -->
+ <!-- no translation found for bluetooth_a2dp_codec_titles:3 (7279983368484312990) -->
+ <!-- no translation found for bluetooth_a2dp_codec_titles:4 (2301339338870319651) -->
+ <!-- no translation found for bluetooth_a2dp_codec_summaries:0 (9072025520360316957) -->
+ <!-- no translation found for bluetooth_a2dp_codec_summaries:1 (6898329690939802290) -->
+ <!-- no translation found for bluetooth_a2dp_codec_summaries:2 (1190434429082395888) -->
+ <!-- no translation found for bluetooth_a2dp_codec_summaries:3 (649699003004233053) -->
+ <!-- no translation found for bluetooth_a2dp_codec_summaries:4 (508106435710925399) -->
+ <!-- no translation found for bluetooth_a2dp_codec_sample_rate_titles:0 (7102940318360468759) -->
+ <!-- no translation found for bluetooth_a2dp_codec_sample_rate_titles:1 (8895532488906185219) -->
+ <!-- no translation found for bluetooth_a2dp_codec_sample_rate_titles:2 (2909915718994807056) -->
+ <!-- no translation found for bluetooth_a2dp_codec_sample_rate_titles:3 (3347287377354164611) -->
+ <!-- no translation found for bluetooth_a2dp_codec_sample_rate_titles:4 (1234212100239985373) -->
+ <!-- no translation found for bluetooth_a2dp_codec_sample_rate_summaries:0 (7224433008148687313) -->
+ <!-- no translation found for bluetooth_a2dp_codec_sample_rate_summaries:1 (4482862757811638365) -->
+ <!-- no translation found for bluetooth_a2dp_codec_sample_rate_summaries:2 (354495328188724404) -->
+ <!-- no translation found for bluetooth_a2dp_codec_sample_rate_summaries:3 (7329816882213695083) -->
+ <!-- no translation found for bluetooth_a2dp_codec_sample_rate_summaries:4 (6967397666254430476) -->
+ <!-- no translation found for bluetooth_a2dp_codec_bits_per_sample_titles:0 (6694044160540313386) -->
+ <!-- no translation found for bluetooth_a2dp_codec_bits_per_sample_titles:1 (5618929009984956469) -->
+ <!-- no translation found for bluetooth_a2dp_codec_bits_per_sample_titles:2 (3412640499234627248) -->
+ <!-- no translation found for bluetooth_a2dp_codec_bits_per_sample_titles:3 (121583001492929387) -->
+ <!-- no translation found for bluetooth_a2dp_codec_bits_per_sample_summaries:0 (5091076677792306320) -->
+ <!-- no translation found for bluetooth_a2dp_codec_bits_per_sample_summaries:1 (4726688794884191540) -->
+ <!-- no translation found for bluetooth_a2dp_codec_bits_per_sample_summaries:2 (305344756485516870) -->
+ <!-- no translation found for bluetooth_a2dp_codec_bits_per_sample_summaries:3 (244568657919675099) -->
+ <!-- no translation found for bluetooth_a2dp_codec_channel_mode_titles:0 (13423709606339855) -->
+ <!-- no translation found for bluetooth_a2dp_codec_channel_mode_titles:1 (4106832974775067314) -->
+ <!-- no translation found for bluetooth_a2dp_codec_channel_mode_titles:2 (5571632958424639155) -->
+ <!-- no translation found for bluetooth_a2dp_codec_channel_mode_summaries:0 (8128478683963250130) -->
+ <!-- no translation found for bluetooth_a2dp_codec_channel_mode_summaries:1 (8900559293912978337) -->
+ <!-- no translation found for bluetooth_a2dp_codec_channel_mode_summaries:2 (8883739882299884241) -->
+ <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_titles:0 (2944889121850394020) -->
+ <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_titles:1 (138837449700903545) -->
+ <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_titles:2 (4777177307869441982) -->
+ <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_summaries:0 (172302906231378902) -->
+ <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_summaries:1 (9091111147684472529) -->
+ <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_summaries:2 (3367904477834831032) -->
<string-array name="select_logd_size_titles">
<item msgid="8665206199209698501">"Off"</item>
<item msgid="1593289376502312923">"64 K"</item>
diff --git a/packages/SettingsLib/res/values-en-rIN/strings.xml b/packages/SettingsLib/res/values-en-rIN/strings.xml
index e27822f..8c56ede 100644
--- a/packages/SettingsLib/res/values-en-rIN/strings.xml
+++ b/packages/SettingsLib/res/values-en-rIN/strings.xml
@@ -170,6 +170,26 @@
<string name="wifi_allow_scan_with_traffic" msgid="3601853081178265786">"Always allow Wi‑Fi Roam Scans"</string>
<string name="mobile_data_always_on" msgid="7745605759775320362">"Mobile data always active"</string>
<string name="bluetooth_disable_absolute_volume" msgid="2660673801947898809">"Disable absolute volume"</string>
+ <!-- no translation found for bluetooth_select_a2dp_codec_type (90597356942154882) -->
+ <skip />
+ <!-- no translation found for bluetooth_select_a2dp_codec_type_dialog_title (6470824182074383881) -->
+ <skip />
+ <!-- no translation found for bluetooth_select_a2dp_codec_sample_rate (4788245703824623062) -->
+ <skip />
+ <!-- no translation found for bluetooth_select_a2dp_codec_sample_rate_dialog_title (4263851572248033749) -->
+ <skip />
+ <!-- no translation found for bluetooth_select_a2dp_codec_bits_per_sample (2099645202720164141) -->
+ <skip />
+ <!-- no translation found for bluetooth_select_a2dp_codec_bits_per_sample_dialog_title (2096170505745650345) -->
+ <skip />
+ <!-- no translation found for bluetooth_select_a2dp_codec_channel_mode (884855779449390540) -->
+ <skip />
+ <!-- no translation found for bluetooth_select_a2dp_codec_channel_mode_dialog_title (4073812880900816325) -->
+ <skip />
+ <!-- no translation found for bluetooth_select_a2dp_codec_ldac_playback_quality (4846872213548295632) -->
+ <skip />
+ <!-- no translation found for bluetooth_select_a2dp_codec_ldac_playback_quality_dialog_title (3940973633342423717) -->
+ <skip />
<string name="wifi_display_certification_summary" msgid="1155182309166746973">"Show options for wireless display certification"</string>
<string name="wifi_verbose_logging_summary" msgid="6615071616111731958">"Increase Wi‑Fi logging level, show per SSID RSSI in Wi‑Fi Picker"</string>
<string name="wifi_aggressive_handover_summary" msgid="6328455667642570371">"When enabled, Wi‑Fi will be more aggressive in handing over the data connection to Mobile, when Wi‑Fi signal is low"</string>
diff --git a/packages/SettingsLib/res/values-es-rUS/arrays.xml b/packages/SettingsLib/res/values-es-rUS/arrays.xml
index c88b38a..7c02ce3 100644
--- a/packages/SettingsLib/res/values-es-rUS/arrays.xml
+++ b/packages/SettingsLib/res/values-es-rUS/arrays.xml
@@ -58,6 +58,46 @@
<item msgid="3878793616631049349">"Usar comprobación HDCP para contenido DRM solamente"</item>
<item msgid="45075631231212732">"Siempre utilizar comprobación HDCP"</item>
</string-array>
+ <!-- no translation found for bluetooth_a2dp_codec_titles:0 (1852387125374225729) -->
+ <!-- no translation found for bluetooth_a2dp_codec_titles:1 (7539690996561263909) -->
+ <!-- no translation found for bluetooth_a2dp_codec_titles:2 (4260844283202960798) -->
+ <!-- no translation found for bluetooth_a2dp_codec_titles:3 (7279983368484312990) -->
+ <!-- no translation found for bluetooth_a2dp_codec_titles:4 (2301339338870319651) -->
+ <!-- no translation found for bluetooth_a2dp_codec_summaries:0 (9072025520360316957) -->
+ <!-- no translation found for bluetooth_a2dp_codec_summaries:1 (6898329690939802290) -->
+ <!-- no translation found for bluetooth_a2dp_codec_summaries:2 (1190434429082395888) -->
+ <!-- no translation found for bluetooth_a2dp_codec_summaries:3 (649699003004233053) -->
+ <!-- no translation found for bluetooth_a2dp_codec_summaries:4 (508106435710925399) -->
+ <!-- no translation found for bluetooth_a2dp_codec_sample_rate_titles:0 (7102940318360468759) -->
+ <!-- no translation found for bluetooth_a2dp_codec_sample_rate_titles:1 (8895532488906185219) -->
+ <!-- no translation found for bluetooth_a2dp_codec_sample_rate_titles:2 (2909915718994807056) -->
+ <!-- no translation found for bluetooth_a2dp_codec_sample_rate_titles:3 (3347287377354164611) -->
+ <!-- no translation found for bluetooth_a2dp_codec_sample_rate_titles:4 (1234212100239985373) -->
+ <!-- no translation found for bluetooth_a2dp_codec_sample_rate_summaries:0 (7224433008148687313) -->
+ <!-- no translation found for bluetooth_a2dp_codec_sample_rate_summaries:1 (4482862757811638365) -->
+ <!-- no translation found for bluetooth_a2dp_codec_sample_rate_summaries:2 (354495328188724404) -->
+ <!-- no translation found for bluetooth_a2dp_codec_sample_rate_summaries:3 (7329816882213695083) -->
+ <!-- no translation found for bluetooth_a2dp_codec_sample_rate_summaries:4 (6967397666254430476) -->
+ <!-- no translation found for bluetooth_a2dp_codec_bits_per_sample_titles:0 (6694044160540313386) -->
+ <!-- no translation found for bluetooth_a2dp_codec_bits_per_sample_titles:1 (5618929009984956469) -->
+ <!-- no translation found for bluetooth_a2dp_codec_bits_per_sample_titles:2 (3412640499234627248) -->
+ <!-- no translation found for bluetooth_a2dp_codec_bits_per_sample_titles:3 (121583001492929387) -->
+ <!-- no translation found for bluetooth_a2dp_codec_bits_per_sample_summaries:0 (5091076677792306320) -->
+ <!-- no translation found for bluetooth_a2dp_codec_bits_per_sample_summaries:1 (4726688794884191540) -->
+ <!-- no translation found for bluetooth_a2dp_codec_bits_per_sample_summaries:2 (305344756485516870) -->
+ <!-- no translation found for bluetooth_a2dp_codec_bits_per_sample_summaries:3 (244568657919675099) -->
+ <!-- no translation found for bluetooth_a2dp_codec_channel_mode_titles:0 (13423709606339855) -->
+ <!-- no translation found for bluetooth_a2dp_codec_channel_mode_titles:1 (4106832974775067314) -->
+ <!-- no translation found for bluetooth_a2dp_codec_channel_mode_titles:2 (5571632958424639155) -->
+ <!-- no translation found for bluetooth_a2dp_codec_channel_mode_summaries:0 (8128478683963250130) -->
+ <!-- no translation found for bluetooth_a2dp_codec_channel_mode_summaries:1 (8900559293912978337) -->
+ <!-- no translation found for bluetooth_a2dp_codec_channel_mode_summaries:2 (8883739882299884241) -->
+ <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_titles:0 (2944889121850394020) -->
+ <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_titles:1 (138837449700903545) -->
+ <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_titles:2 (4777177307869441982) -->
+ <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_summaries:0 (172302906231378902) -->
+ <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_summaries:1 (9091111147684472529) -->
+ <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_summaries:2 (3367904477834831032) -->
<string-array name="select_logd_size_titles">
<item msgid="8665206199209698501">"Desactivado"</item>
<item msgid="1593289376502312923">"64 K"</item>
diff --git a/packages/SettingsLib/res/values-es-rUS/strings.xml b/packages/SettingsLib/res/values-es-rUS/strings.xml
index 9127b2a..dbd2bff 100644
--- a/packages/SettingsLib/res/values-es-rUS/strings.xml
+++ b/packages/SettingsLib/res/values-es-rUS/strings.xml
@@ -170,6 +170,26 @@
<string name="wifi_allow_scan_with_traffic" msgid="3601853081178265786">"Permitir siempre búsquedas de Wi-Fi"</string>
<string name="mobile_data_always_on" msgid="7745605759775320362">"Datos móviles siempre activos"</string>
<string name="bluetooth_disable_absolute_volume" msgid="2660673801947898809">"Inhabilitar volumen absoluto"</string>
+ <!-- no translation found for bluetooth_select_a2dp_codec_type (90597356942154882) -->
+ <skip />
+ <!-- no translation found for bluetooth_select_a2dp_codec_type_dialog_title (6470824182074383881) -->
+ <skip />
+ <!-- no translation found for bluetooth_select_a2dp_codec_sample_rate (4788245703824623062) -->
+ <skip />
+ <!-- no translation found for bluetooth_select_a2dp_codec_sample_rate_dialog_title (4263851572248033749) -->
+ <skip />
+ <!-- no translation found for bluetooth_select_a2dp_codec_bits_per_sample (2099645202720164141) -->
+ <skip />
+ <!-- no translation found for bluetooth_select_a2dp_codec_bits_per_sample_dialog_title (2096170505745650345) -->
+ <skip />
+ <!-- no translation found for bluetooth_select_a2dp_codec_channel_mode (884855779449390540) -->
+ <skip />
+ <!-- no translation found for bluetooth_select_a2dp_codec_channel_mode_dialog_title (4073812880900816325) -->
+ <skip />
+ <!-- no translation found for bluetooth_select_a2dp_codec_ldac_playback_quality (4846872213548295632) -->
+ <skip />
+ <!-- no translation found for bluetooth_select_a2dp_codec_ldac_playback_quality_dialog_title (3940973633342423717) -->
+ <skip />
<string name="wifi_display_certification_summary" msgid="1155182309166746973">"Mostrar opciones de certificación de pantalla inalámbrica"</string>
<string name="wifi_verbose_logging_summary" msgid="6615071616111731958">"Aumentar nivel de registro Wi-Fi; mostrar por SSID RSSI en el selector de Wi-Fi"</string>
<string name="wifi_aggressive_handover_summary" msgid="6328455667642570371">"Si está habilitada, la conexión Wi‑Fi será más intensa al transferir la conexión de datos al celular (si la señal Wi‑Fi es débil)."</string>
diff --git a/packages/SettingsLib/res/values-es/arrays.xml b/packages/SettingsLib/res/values-es/arrays.xml
index 3dc392a..ed3ab94 100644
--- a/packages/SettingsLib/res/values-es/arrays.xml
+++ b/packages/SettingsLib/res/values-es/arrays.xml
@@ -58,6 +58,46 @@
<item msgid="3878793616631049349">"Utilizar comprobación de HDCP solo para contenido DRM"</item>
<item msgid="45075631231212732">"Utilizar siempre comprobación de HDCP"</item>
</string-array>
+ <!-- no translation found for bluetooth_a2dp_codec_titles:0 (1852387125374225729) -->
+ <!-- no translation found for bluetooth_a2dp_codec_titles:1 (7539690996561263909) -->
+ <!-- no translation found for bluetooth_a2dp_codec_titles:2 (4260844283202960798) -->
+ <!-- no translation found for bluetooth_a2dp_codec_titles:3 (7279983368484312990) -->
+ <!-- no translation found for bluetooth_a2dp_codec_titles:4 (2301339338870319651) -->
+ <!-- no translation found for bluetooth_a2dp_codec_summaries:0 (9072025520360316957) -->
+ <!-- no translation found for bluetooth_a2dp_codec_summaries:1 (6898329690939802290) -->
+ <!-- no translation found for bluetooth_a2dp_codec_summaries:2 (1190434429082395888) -->
+ <!-- no translation found for bluetooth_a2dp_codec_summaries:3 (649699003004233053) -->
+ <!-- no translation found for bluetooth_a2dp_codec_summaries:4 (508106435710925399) -->
+ <!-- no translation found for bluetooth_a2dp_codec_sample_rate_titles:0 (7102940318360468759) -->
+ <!-- no translation found for bluetooth_a2dp_codec_sample_rate_titles:1 (8895532488906185219) -->
+ <!-- no translation found for bluetooth_a2dp_codec_sample_rate_titles:2 (2909915718994807056) -->
+ <!-- no translation found for bluetooth_a2dp_codec_sample_rate_titles:3 (3347287377354164611) -->
+ <!-- no translation found for bluetooth_a2dp_codec_sample_rate_titles:4 (1234212100239985373) -->
+ <!-- no translation found for bluetooth_a2dp_codec_sample_rate_summaries:0 (7224433008148687313) -->
+ <!-- no translation found for bluetooth_a2dp_codec_sample_rate_summaries:1 (4482862757811638365) -->
+ <!-- no translation found for bluetooth_a2dp_codec_sample_rate_summaries:2 (354495328188724404) -->
+ <!-- no translation found for bluetooth_a2dp_codec_sample_rate_summaries:3 (7329816882213695083) -->
+ <!-- no translation found for bluetooth_a2dp_codec_sample_rate_summaries:4 (6967397666254430476) -->
+ <!-- no translation found for bluetooth_a2dp_codec_bits_per_sample_titles:0 (6694044160540313386) -->
+ <!-- no translation found for bluetooth_a2dp_codec_bits_per_sample_titles:1 (5618929009984956469) -->
+ <!-- no translation found for bluetooth_a2dp_codec_bits_per_sample_titles:2 (3412640499234627248) -->
+ <!-- no translation found for bluetooth_a2dp_codec_bits_per_sample_titles:3 (121583001492929387) -->
+ <!-- no translation found for bluetooth_a2dp_codec_bits_per_sample_summaries:0 (5091076677792306320) -->
+ <!-- no translation found for bluetooth_a2dp_codec_bits_per_sample_summaries:1 (4726688794884191540) -->
+ <!-- no translation found for bluetooth_a2dp_codec_bits_per_sample_summaries:2 (305344756485516870) -->
+ <!-- no translation found for bluetooth_a2dp_codec_bits_per_sample_summaries:3 (244568657919675099) -->
+ <!-- no translation found for bluetooth_a2dp_codec_channel_mode_titles:0 (13423709606339855) -->
+ <!-- no translation found for bluetooth_a2dp_codec_channel_mode_titles:1 (4106832974775067314) -->
+ <!-- no translation found for bluetooth_a2dp_codec_channel_mode_titles:2 (5571632958424639155) -->
+ <!-- no translation found for bluetooth_a2dp_codec_channel_mode_summaries:0 (8128478683963250130) -->
+ <!-- no translation found for bluetooth_a2dp_codec_channel_mode_summaries:1 (8900559293912978337) -->
+ <!-- no translation found for bluetooth_a2dp_codec_channel_mode_summaries:2 (8883739882299884241) -->
+ <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_titles:0 (2944889121850394020) -->
+ <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_titles:1 (138837449700903545) -->
+ <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_titles:2 (4777177307869441982) -->
+ <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_summaries:0 (172302906231378902) -->
+ <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_summaries:1 (9091111147684472529) -->
+ <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_summaries:2 (3367904477834831032) -->
<string-array name="select_logd_size_titles">
<item msgid="8665206199209698501">"No"</item>
<item msgid="1593289376502312923">"64 K"</item>
diff --git a/packages/SettingsLib/res/values-es/strings.xml b/packages/SettingsLib/res/values-es/strings.xml
index 2d89b00..de275a2 100644
--- a/packages/SettingsLib/res/values-es/strings.xml
+++ b/packages/SettingsLib/res/values-es/strings.xml
@@ -170,6 +170,26 @@
<string name="wifi_allow_scan_with_traffic" msgid="3601853081178265786">"Permitir siempre búsquedas de Wi-Fi"</string>
<string name="mobile_data_always_on" msgid="7745605759775320362">"Datos móviles siempre activos"</string>
<string name="bluetooth_disable_absolute_volume" msgid="2660673801947898809">"Inhabilitar volumen absoluto"</string>
+ <!-- no translation found for bluetooth_select_a2dp_codec_type (90597356942154882) -->
+ <skip />
+ <!-- no translation found for bluetooth_select_a2dp_codec_type_dialog_title (6470824182074383881) -->
+ <skip />
+ <!-- no translation found for bluetooth_select_a2dp_codec_sample_rate (4788245703824623062) -->
+ <skip />
+ <!-- no translation found for bluetooth_select_a2dp_codec_sample_rate_dialog_title (4263851572248033749) -->
+ <skip />
+ <!-- no translation found for bluetooth_select_a2dp_codec_bits_per_sample (2099645202720164141) -->
+ <skip />
+ <!-- no translation found for bluetooth_select_a2dp_codec_bits_per_sample_dialog_title (2096170505745650345) -->
+ <skip />
+ <!-- no translation found for bluetooth_select_a2dp_codec_channel_mode (884855779449390540) -->
+ <skip />
+ <!-- no translation found for bluetooth_select_a2dp_codec_channel_mode_dialog_title (4073812880900816325) -->
+ <skip />
+ <!-- no translation found for bluetooth_select_a2dp_codec_ldac_playback_quality (4846872213548295632) -->
+ <skip />
+ <!-- no translation found for bluetooth_select_a2dp_codec_ldac_playback_quality_dialog_title (3940973633342423717) -->
+ <skip />
<string name="wifi_display_certification_summary" msgid="1155182309166746973">"Mostrar opciones para la certificación de la pantalla inalámbrica"</string>
<string name="wifi_verbose_logging_summary" msgid="6615071616111731958">"Aumentar el nivel de logging de Wi-Fi, mostrar por SSID RSSI en el selector Wi-Fi"</string>
<string name="wifi_aggressive_handover_summary" msgid="6328455667642570371">"Si está habilitada, la conexión Wi‑Fi será más agresiva al transferir la conexión de datos al móvil (si la señal Wi‑Fi no es estable)"</string>
diff --git a/packages/SettingsLib/res/values-et-rEE/arrays.xml b/packages/SettingsLib/res/values-et-rEE/arrays.xml
index 7bb6e34..0c8c94e 100644
--- a/packages/SettingsLib/res/values-et-rEE/arrays.xml
+++ b/packages/SettingsLib/res/values-et-rEE/arrays.xml
@@ -58,6 +58,46 @@
<item msgid="3878793616631049349">"Kasuta HDCP-kontrolli ainult DRM-sisu korral"</item>
<item msgid="45075631231212732">"Kasuta alati HDCP-kontrollimist"</item>
</string-array>
+ <!-- no translation found for bluetooth_a2dp_codec_titles:0 (1852387125374225729) -->
+ <!-- no translation found for bluetooth_a2dp_codec_titles:1 (7539690996561263909) -->
+ <!-- no translation found for bluetooth_a2dp_codec_titles:2 (4260844283202960798) -->
+ <!-- no translation found for bluetooth_a2dp_codec_titles:3 (7279983368484312990) -->
+ <!-- no translation found for bluetooth_a2dp_codec_titles:4 (2301339338870319651) -->
+ <!-- no translation found for bluetooth_a2dp_codec_summaries:0 (9072025520360316957) -->
+ <!-- no translation found for bluetooth_a2dp_codec_summaries:1 (6898329690939802290) -->
+ <!-- no translation found for bluetooth_a2dp_codec_summaries:2 (1190434429082395888) -->
+ <!-- no translation found for bluetooth_a2dp_codec_summaries:3 (649699003004233053) -->
+ <!-- no translation found for bluetooth_a2dp_codec_summaries:4 (508106435710925399) -->
+ <!-- no translation found for bluetooth_a2dp_codec_sample_rate_titles:0 (7102940318360468759) -->
+ <!-- no translation found for bluetooth_a2dp_codec_sample_rate_titles:1 (8895532488906185219) -->
+ <!-- no translation found for bluetooth_a2dp_codec_sample_rate_titles:2 (2909915718994807056) -->
+ <!-- no translation found for bluetooth_a2dp_codec_sample_rate_titles:3 (3347287377354164611) -->
+ <!-- no translation found for bluetooth_a2dp_codec_sample_rate_titles:4 (1234212100239985373) -->
+ <!-- no translation found for bluetooth_a2dp_codec_sample_rate_summaries:0 (7224433008148687313) -->
+ <!-- no translation found for bluetooth_a2dp_codec_sample_rate_summaries:1 (4482862757811638365) -->
+ <!-- no translation found for bluetooth_a2dp_codec_sample_rate_summaries:2 (354495328188724404) -->
+ <!-- no translation found for bluetooth_a2dp_codec_sample_rate_summaries:3 (7329816882213695083) -->
+ <!-- no translation found for bluetooth_a2dp_codec_sample_rate_summaries:4 (6967397666254430476) -->
+ <!-- no translation found for bluetooth_a2dp_codec_bits_per_sample_titles:0 (6694044160540313386) -->
+ <!-- no translation found for bluetooth_a2dp_codec_bits_per_sample_titles:1 (5618929009984956469) -->
+ <!-- no translation found for bluetooth_a2dp_codec_bits_per_sample_titles:2 (3412640499234627248) -->
+ <!-- no translation found for bluetooth_a2dp_codec_bits_per_sample_titles:3 (121583001492929387) -->
+ <!-- no translation found for bluetooth_a2dp_codec_bits_per_sample_summaries:0 (5091076677792306320) -->
+ <!-- no translation found for bluetooth_a2dp_codec_bits_per_sample_summaries:1 (4726688794884191540) -->
+ <!-- no translation found for bluetooth_a2dp_codec_bits_per_sample_summaries:2 (305344756485516870) -->
+ <!-- no translation found for bluetooth_a2dp_codec_bits_per_sample_summaries:3 (244568657919675099) -->
+ <!-- no translation found for bluetooth_a2dp_codec_channel_mode_titles:0 (13423709606339855) -->
+ <!-- no translation found for bluetooth_a2dp_codec_channel_mode_titles:1 (4106832974775067314) -->
+ <!-- no translation found for bluetooth_a2dp_codec_channel_mode_titles:2 (5571632958424639155) -->
+ <!-- no translation found for bluetooth_a2dp_codec_channel_mode_summaries:0 (8128478683963250130) -->
+ <!-- no translation found for bluetooth_a2dp_codec_channel_mode_summaries:1 (8900559293912978337) -->
+ <!-- no translation found for bluetooth_a2dp_codec_channel_mode_summaries:2 (8883739882299884241) -->
+ <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_titles:0 (2944889121850394020) -->
+ <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_titles:1 (138837449700903545) -->
+ <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_titles:2 (4777177307869441982) -->
+ <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_summaries:0 (172302906231378902) -->
+ <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_summaries:1 (9091111147684472529) -->
+ <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_summaries:2 (3367904477834831032) -->
<string-array name="select_logd_size_titles">
<item msgid="8665206199209698501">"Väljas"</item>
<item msgid="1593289376502312923">"64 000"</item>
diff --git a/packages/SettingsLib/res/values-et-rEE/strings.xml b/packages/SettingsLib/res/values-et-rEE/strings.xml
index f979db8..1e630ee 100644
--- a/packages/SettingsLib/res/values-et-rEE/strings.xml
+++ b/packages/SettingsLib/res/values-et-rEE/strings.xml
@@ -170,6 +170,26 @@
<string name="wifi_allow_scan_with_traffic" msgid="3601853081178265786">"Luba alati WiFi-rändluse skannimine"</string>
<string name="mobile_data_always_on" msgid="7745605759775320362">"Mobiilne andmeside on alati aktiivne"</string>
<string name="bluetooth_disable_absolute_volume" msgid="2660673801947898809">"Keela absoluutne helitugevus"</string>
+ <!-- no translation found for bluetooth_select_a2dp_codec_type (90597356942154882) -->
+ <skip />
+ <!-- no translation found for bluetooth_select_a2dp_codec_type_dialog_title (6470824182074383881) -->
+ <skip />
+ <!-- no translation found for bluetooth_select_a2dp_codec_sample_rate (4788245703824623062) -->
+ <skip />
+ <!-- no translation found for bluetooth_select_a2dp_codec_sample_rate_dialog_title (4263851572248033749) -->
+ <skip />
+ <!-- no translation found for bluetooth_select_a2dp_codec_bits_per_sample (2099645202720164141) -->
+ <skip />
+ <!-- no translation found for bluetooth_select_a2dp_codec_bits_per_sample_dialog_title (2096170505745650345) -->
+ <skip />
+ <!-- no translation found for bluetooth_select_a2dp_codec_channel_mode (884855779449390540) -->
+ <skip />
+ <!-- no translation found for bluetooth_select_a2dp_codec_channel_mode_dialog_title (4073812880900816325) -->
+ <skip />
+ <!-- no translation found for bluetooth_select_a2dp_codec_ldac_playback_quality (4846872213548295632) -->
+ <skip />
+ <!-- no translation found for bluetooth_select_a2dp_codec_ldac_playback_quality_dialog_title (3940973633342423717) -->
+ <skip />
<string name="wifi_display_certification_summary" msgid="1155182309166746973">"Juhtmeta ekraaniühenduse sertifitseerimisvalikute kuvamine"</string>
<string name="wifi_verbose_logging_summary" msgid="6615071616111731958">"Suurenda WiFi logimistaset, kuva WiFi valijas SSID RSSI järgi"</string>
<string name="wifi_aggressive_handover_summary" msgid="6328455667642570371">"Kui see on lubatud, siis püüab WiFi nõrga WiFi-signaali korral agressiivsemalt anda andmeside ühenduse üle mobiilsele andmesidele"</string>
diff --git a/packages/SettingsLib/res/values-eu-rES/arrays.xml b/packages/SettingsLib/res/values-eu-rES/arrays.xml
index 82df3e8..a38ac5b9 100644
--- a/packages/SettingsLib/res/values-eu-rES/arrays.xml
+++ b/packages/SettingsLib/res/values-eu-rES/arrays.xml
@@ -58,6 +58,46 @@
<item msgid="3878793616631049349">"Erabili HDCP egiaztapena DRM edukirako soilik"</item>
<item msgid="45075631231212732">"Erabili beti HDCP egiaztapena"</item>
</string-array>
+ <!-- no translation found for bluetooth_a2dp_codec_titles:0 (1852387125374225729) -->
+ <!-- no translation found for bluetooth_a2dp_codec_titles:1 (7539690996561263909) -->
+ <!-- no translation found for bluetooth_a2dp_codec_titles:2 (4260844283202960798) -->
+ <!-- no translation found for bluetooth_a2dp_codec_titles:3 (7279983368484312990) -->
+ <!-- no translation found for bluetooth_a2dp_codec_titles:4 (2301339338870319651) -->
+ <!-- no translation found for bluetooth_a2dp_codec_summaries:0 (9072025520360316957) -->
+ <!-- no translation found for bluetooth_a2dp_codec_summaries:1 (6898329690939802290) -->
+ <!-- no translation found for bluetooth_a2dp_codec_summaries:2 (1190434429082395888) -->
+ <!-- no translation found for bluetooth_a2dp_codec_summaries:3 (649699003004233053) -->
+ <!-- no translation found for bluetooth_a2dp_codec_summaries:4 (508106435710925399) -->
+ <!-- no translation found for bluetooth_a2dp_codec_sample_rate_titles:0 (7102940318360468759) -->
+ <!-- no translation found for bluetooth_a2dp_codec_sample_rate_titles:1 (8895532488906185219) -->
+ <!-- no translation found for bluetooth_a2dp_codec_sample_rate_titles:2 (2909915718994807056) -->
+ <!-- no translation found for bluetooth_a2dp_codec_sample_rate_titles:3 (3347287377354164611) -->
+ <!-- no translation found for bluetooth_a2dp_codec_sample_rate_titles:4 (1234212100239985373) -->
+ <!-- no translation found for bluetooth_a2dp_codec_sample_rate_summaries:0 (7224433008148687313) -->
+ <!-- no translation found for bluetooth_a2dp_codec_sample_rate_summaries:1 (4482862757811638365) -->
+ <!-- no translation found for bluetooth_a2dp_codec_sample_rate_summaries:2 (354495328188724404) -->
+ <!-- no translation found for bluetooth_a2dp_codec_sample_rate_summaries:3 (7329816882213695083) -->
+ <!-- no translation found for bluetooth_a2dp_codec_sample_rate_summaries:4 (6967397666254430476) -->
+ <!-- no translation found for bluetooth_a2dp_codec_bits_per_sample_titles:0 (6694044160540313386) -->
+ <!-- no translation found for bluetooth_a2dp_codec_bits_per_sample_titles:1 (5618929009984956469) -->
+ <!-- no translation found for bluetooth_a2dp_codec_bits_per_sample_titles:2 (3412640499234627248) -->
+ <!-- no translation found for bluetooth_a2dp_codec_bits_per_sample_titles:3 (121583001492929387) -->
+ <!-- no translation found for bluetooth_a2dp_codec_bits_per_sample_summaries:0 (5091076677792306320) -->
+ <!-- no translation found for bluetooth_a2dp_codec_bits_per_sample_summaries:1 (4726688794884191540) -->
+ <!-- no translation found for bluetooth_a2dp_codec_bits_per_sample_summaries:2 (305344756485516870) -->
+ <!-- no translation found for bluetooth_a2dp_codec_bits_per_sample_summaries:3 (244568657919675099) -->
+ <!-- no translation found for bluetooth_a2dp_codec_channel_mode_titles:0 (13423709606339855) -->
+ <!-- no translation found for bluetooth_a2dp_codec_channel_mode_titles:1 (4106832974775067314) -->
+ <!-- no translation found for bluetooth_a2dp_codec_channel_mode_titles:2 (5571632958424639155) -->
+ <!-- no translation found for bluetooth_a2dp_codec_channel_mode_summaries:0 (8128478683963250130) -->
+ <!-- no translation found for bluetooth_a2dp_codec_channel_mode_summaries:1 (8900559293912978337) -->
+ <!-- no translation found for bluetooth_a2dp_codec_channel_mode_summaries:2 (8883739882299884241) -->
+ <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_titles:0 (2944889121850394020) -->
+ <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_titles:1 (138837449700903545) -->
+ <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_titles:2 (4777177307869441982) -->
+ <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_summaries:0 (172302906231378902) -->
+ <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_summaries:1 (9091111147684472529) -->
+ <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_summaries:2 (3367904477834831032) -->
<string-array name="select_logd_size_titles">
<item msgid="8665206199209698501">"Desaktibatuta"</item>
<item msgid="1593289376502312923">"64 K"</item>
diff --git a/packages/SettingsLib/res/values-eu-rES/strings.xml b/packages/SettingsLib/res/values-eu-rES/strings.xml
index 3e08c77..68baa33 100644
--- a/packages/SettingsLib/res/values-eu-rES/strings.xml
+++ b/packages/SettingsLib/res/values-eu-rES/strings.xml
@@ -170,6 +170,26 @@
<string name="wifi_allow_scan_with_traffic" msgid="3601853081178265786">"Onartu beti ibiltaritzan Wi-Fi sareak bilatzea"</string>
<string name="mobile_data_always_on" msgid="7745605759775320362">"Mugikorreko datuak beti aktibo"</string>
<string name="bluetooth_disable_absolute_volume" msgid="2660673801947898809">"Desgaitu bolumen absolutua"</string>
+ <!-- no translation found for bluetooth_select_a2dp_codec_type (90597356942154882) -->
+ <skip />
+ <!-- no translation found for bluetooth_select_a2dp_codec_type_dialog_title (6470824182074383881) -->
+ <skip />
+ <!-- no translation found for bluetooth_select_a2dp_codec_sample_rate (4788245703824623062) -->
+ <skip />
+ <!-- no translation found for bluetooth_select_a2dp_codec_sample_rate_dialog_title (4263851572248033749) -->
+ <skip />
+ <!-- no translation found for bluetooth_select_a2dp_codec_bits_per_sample (2099645202720164141) -->
+ <skip />
+ <!-- no translation found for bluetooth_select_a2dp_codec_bits_per_sample_dialog_title (2096170505745650345) -->
+ <skip />
+ <!-- no translation found for bluetooth_select_a2dp_codec_channel_mode (884855779449390540) -->
+ <skip />
+ <!-- no translation found for bluetooth_select_a2dp_codec_channel_mode_dialog_title (4073812880900816325) -->
+ <skip />
+ <!-- no translation found for bluetooth_select_a2dp_codec_ldac_playback_quality (4846872213548295632) -->
+ <skip />
+ <!-- no translation found for bluetooth_select_a2dp_codec_ldac_playback_quality_dialog_title (3940973633342423717) -->
+ <skip />
<string name="wifi_display_certification_summary" msgid="1155182309166746973">"Erakutsi hari gabeko bistaratze-egiaztapenaren aukerak"</string>
<string name="wifi_verbose_logging_summary" msgid="6615071616111731958">"Erakutsi datu gehiago Wi-Fi sareetan saioa hasterakoan. Erakutsi sarearen identifikatzailea eta seinalearen indarra Wi‑Fi sareen hautagailuan."</string>
<string name="wifi_aggressive_handover_summary" msgid="6328455667642570371">"Aukera hori gaituz gero, gailua errazago aldatuko da datu mugikorren konexiora Wi-Fi seinalea ahultzen dela nabaritutakoan"</string>
diff --git a/packages/SettingsLib/res/values-fa/arrays.xml b/packages/SettingsLib/res/values-fa/arrays.xml
index 8d01d6b..14680f5 100644
--- a/packages/SettingsLib/res/values-fa/arrays.xml
+++ b/packages/SettingsLib/res/values-fa/arrays.xml
@@ -58,6 +58,46 @@
<item msgid="3878793616631049349">"استفاده از بررسی HDCP فقط برای محتوای DRM"</item>
<item msgid="45075631231212732">"همیشه از بررسی HDCP استفاده شود"</item>
</string-array>
+ <!-- no translation found for bluetooth_a2dp_codec_titles:0 (1852387125374225729) -->
+ <!-- no translation found for bluetooth_a2dp_codec_titles:1 (7539690996561263909) -->
+ <!-- no translation found for bluetooth_a2dp_codec_titles:2 (4260844283202960798) -->
+ <!-- no translation found for bluetooth_a2dp_codec_titles:3 (7279983368484312990) -->
+ <!-- no translation found for bluetooth_a2dp_codec_titles:4 (2301339338870319651) -->
+ <!-- no translation found for bluetooth_a2dp_codec_summaries:0 (9072025520360316957) -->
+ <!-- no translation found for bluetooth_a2dp_codec_summaries:1 (6898329690939802290) -->
+ <!-- no translation found for bluetooth_a2dp_codec_summaries:2 (1190434429082395888) -->
+ <!-- no translation found for bluetooth_a2dp_codec_summaries:3 (649699003004233053) -->
+ <!-- no translation found for bluetooth_a2dp_codec_summaries:4 (508106435710925399) -->
+ <!-- no translation found for bluetooth_a2dp_codec_sample_rate_titles:0 (7102940318360468759) -->
+ <!-- no translation found for bluetooth_a2dp_codec_sample_rate_titles:1 (8895532488906185219) -->
+ <!-- no translation found for bluetooth_a2dp_codec_sample_rate_titles:2 (2909915718994807056) -->
+ <!-- no translation found for bluetooth_a2dp_codec_sample_rate_titles:3 (3347287377354164611) -->
+ <!-- no translation found for bluetooth_a2dp_codec_sample_rate_titles:4 (1234212100239985373) -->
+ <!-- no translation found for bluetooth_a2dp_codec_sample_rate_summaries:0 (7224433008148687313) -->
+ <!-- no translation found for bluetooth_a2dp_codec_sample_rate_summaries:1 (4482862757811638365) -->
+ <!-- no translation found for bluetooth_a2dp_codec_sample_rate_summaries:2 (354495328188724404) -->
+ <!-- no translation found for bluetooth_a2dp_codec_sample_rate_summaries:3 (7329816882213695083) -->
+ <!-- no translation found for bluetooth_a2dp_codec_sample_rate_summaries:4 (6967397666254430476) -->
+ <!-- no translation found for bluetooth_a2dp_codec_bits_per_sample_titles:0 (6694044160540313386) -->
+ <!-- no translation found for bluetooth_a2dp_codec_bits_per_sample_titles:1 (5618929009984956469) -->
+ <!-- no translation found for bluetooth_a2dp_codec_bits_per_sample_titles:2 (3412640499234627248) -->
+ <!-- no translation found for bluetooth_a2dp_codec_bits_per_sample_titles:3 (121583001492929387) -->
+ <!-- no translation found for bluetooth_a2dp_codec_bits_per_sample_summaries:0 (5091076677792306320) -->
+ <!-- no translation found for bluetooth_a2dp_codec_bits_per_sample_summaries:1 (4726688794884191540) -->
+ <!-- no translation found for bluetooth_a2dp_codec_bits_per_sample_summaries:2 (305344756485516870) -->
+ <!-- no translation found for bluetooth_a2dp_codec_bits_per_sample_summaries:3 (244568657919675099) -->
+ <!-- no translation found for bluetooth_a2dp_codec_channel_mode_titles:0 (13423709606339855) -->
+ <!-- no translation found for bluetooth_a2dp_codec_channel_mode_titles:1 (4106832974775067314) -->
+ <!-- no translation found for bluetooth_a2dp_codec_channel_mode_titles:2 (5571632958424639155) -->
+ <!-- no translation found for bluetooth_a2dp_codec_channel_mode_summaries:0 (8128478683963250130) -->
+ <!-- no translation found for bluetooth_a2dp_codec_channel_mode_summaries:1 (8900559293912978337) -->
+ <!-- no translation found for bluetooth_a2dp_codec_channel_mode_summaries:2 (8883739882299884241) -->
+ <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_titles:0 (2944889121850394020) -->
+ <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_titles:1 (138837449700903545) -->
+ <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_titles:2 (4777177307869441982) -->
+ <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_summaries:0 (172302906231378902) -->
+ <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_summaries:1 (9091111147684472529) -->
+ <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_summaries:2 (3367904477834831032) -->
<string-array name="select_logd_size_titles">
<item msgid="8665206199209698501">"خاموش"</item>
<item msgid="1593289376502312923">"۶۴ هزار"</item>
diff --git a/packages/SettingsLib/res/values-fa/strings.xml b/packages/SettingsLib/res/values-fa/strings.xml
index 4a741f07..c84c8f9 100644
--- a/packages/SettingsLib/res/values-fa/strings.xml
+++ b/packages/SettingsLib/res/values-fa/strings.xml
@@ -170,6 +170,26 @@
<string name="wifi_allow_scan_with_traffic" msgid="3601853081178265786">"اسکنهای رومینگ Wi‑Fi همیشه مجاز است"</string>
<string name="mobile_data_always_on" msgid="7745605759775320362">"داده سلولی همیشه فعال"</string>
<string name="bluetooth_disable_absolute_volume" msgid="2660673801947898809">"غیرفعال کردن میزان صدای مطلق"</string>
+ <!-- no translation found for bluetooth_select_a2dp_codec_type (90597356942154882) -->
+ <skip />
+ <!-- no translation found for bluetooth_select_a2dp_codec_type_dialog_title (6470824182074383881) -->
+ <skip />
+ <!-- no translation found for bluetooth_select_a2dp_codec_sample_rate (4788245703824623062) -->
+ <skip />
+ <!-- no translation found for bluetooth_select_a2dp_codec_sample_rate_dialog_title (4263851572248033749) -->
+ <skip />
+ <!-- no translation found for bluetooth_select_a2dp_codec_bits_per_sample (2099645202720164141) -->
+ <skip />
+ <!-- no translation found for bluetooth_select_a2dp_codec_bits_per_sample_dialog_title (2096170505745650345) -->
+ <skip />
+ <!-- no translation found for bluetooth_select_a2dp_codec_channel_mode (884855779449390540) -->
+ <skip />
+ <!-- no translation found for bluetooth_select_a2dp_codec_channel_mode_dialog_title (4073812880900816325) -->
+ <skip />
+ <!-- no translation found for bluetooth_select_a2dp_codec_ldac_playback_quality (4846872213548295632) -->
+ <skip />
+ <!-- no translation found for bluetooth_select_a2dp_codec_ldac_playback_quality_dialog_title (3940973633342423717) -->
+ <skip />
<string name="wifi_display_certification_summary" msgid="1155182309166746973">"نمایش گزینهها برای گواهینامه نمایش بیسیم"</string>
<string name="wifi_verbose_logging_summary" msgid="6615071616111731958">"افزایش سطح گزارشگیری Wi‑Fi، نمایش به ازای SSID RSSI در انتخابکننده Wi‑Fi"</string>
<string name="wifi_aggressive_handover_summary" msgid="6328455667642570371">"وقتی فعال است، در شرایط پایین بودن سیگنال، Wi‑Fi برای واگذار کردن اتصال داده به شبکه سلولی فعالتر خواهد بود."</string>
diff --git a/packages/SettingsLib/res/values-fi/arrays.xml b/packages/SettingsLib/res/values-fi/arrays.xml
index 4368848..4abdbbf 100644
--- a/packages/SettingsLib/res/values-fi/arrays.xml
+++ b/packages/SettingsLib/res/values-fi/arrays.xml
@@ -58,6 +58,46 @@
<item msgid="3878793616631049349">"Käytä HDCP-tarkistusta vain DRM-suojatulle sisällölle"</item>
<item msgid="45075631231212732">"Käytä aina HDCP-tarkistusta"</item>
</string-array>
+ <!-- no translation found for bluetooth_a2dp_codec_titles:0 (1852387125374225729) -->
+ <!-- no translation found for bluetooth_a2dp_codec_titles:1 (7539690996561263909) -->
+ <!-- no translation found for bluetooth_a2dp_codec_titles:2 (4260844283202960798) -->
+ <!-- no translation found for bluetooth_a2dp_codec_titles:3 (7279983368484312990) -->
+ <!-- no translation found for bluetooth_a2dp_codec_titles:4 (2301339338870319651) -->
+ <!-- no translation found for bluetooth_a2dp_codec_summaries:0 (9072025520360316957) -->
+ <!-- no translation found for bluetooth_a2dp_codec_summaries:1 (6898329690939802290) -->
+ <!-- no translation found for bluetooth_a2dp_codec_summaries:2 (1190434429082395888) -->
+ <!-- no translation found for bluetooth_a2dp_codec_summaries:3 (649699003004233053) -->
+ <!-- no translation found for bluetooth_a2dp_codec_summaries:4 (508106435710925399) -->
+ <!-- no translation found for bluetooth_a2dp_codec_sample_rate_titles:0 (7102940318360468759) -->
+ <!-- no translation found for bluetooth_a2dp_codec_sample_rate_titles:1 (8895532488906185219) -->
+ <!-- no translation found for bluetooth_a2dp_codec_sample_rate_titles:2 (2909915718994807056) -->
+ <!-- no translation found for bluetooth_a2dp_codec_sample_rate_titles:3 (3347287377354164611) -->
+ <!-- no translation found for bluetooth_a2dp_codec_sample_rate_titles:4 (1234212100239985373) -->
+ <!-- no translation found for bluetooth_a2dp_codec_sample_rate_summaries:0 (7224433008148687313) -->
+ <!-- no translation found for bluetooth_a2dp_codec_sample_rate_summaries:1 (4482862757811638365) -->
+ <!-- no translation found for bluetooth_a2dp_codec_sample_rate_summaries:2 (354495328188724404) -->
+ <!-- no translation found for bluetooth_a2dp_codec_sample_rate_summaries:3 (7329816882213695083) -->
+ <!-- no translation found for bluetooth_a2dp_codec_sample_rate_summaries:4 (6967397666254430476) -->
+ <!-- no translation found for bluetooth_a2dp_codec_bits_per_sample_titles:0 (6694044160540313386) -->
+ <!-- no translation found for bluetooth_a2dp_codec_bits_per_sample_titles:1 (5618929009984956469) -->
+ <!-- no translation found for bluetooth_a2dp_codec_bits_per_sample_titles:2 (3412640499234627248) -->
+ <!-- no translation found for bluetooth_a2dp_codec_bits_per_sample_titles:3 (121583001492929387) -->
+ <!-- no translation found for bluetooth_a2dp_codec_bits_per_sample_summaries:0 (5091076677792306320) -->
+ <!-- no translation found for bluetooth_a2dp_codec_bits_per_sample_summaries:1 (4726688794884191540) -->
+ <!-- no translation found for bluetooth_a2dp_codec_bits_per_sample_summaries:2 (305344756485516870) -->
+ <!-- no translation found for bluetooth_a2dp_codec_bits_per_sample_summaries:3 (244568657919675099) -->
+ <!-- no translation found for bluetooth_a2dp_codec_channel_mode_titles:0 (13423709606339855) -->
+ <!-- no translation found for bluetooth_a2dp_codec_channel_mode_titles:1 (4106832974775067314) -->
+ <!-- no translation found for bluetooth_a2dp_codec_channel_mode_titles:2 (5571632958424639155) -->
+ <!-- no translation found for bluetooth_a2dp_codec_channel_mode_summaries:0 (8128478683963250130) -->
+ <!-- no translation found for bluetooth_a2dp_codec_channel_mode_summaries:1 (8900559293912978337) -->
+ <!-- no translation found for bluetooth_a2dp_codec_channel_mode_summaries:2 (8883739882299884241) -->
+ <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_titles:0 (2944889121850394020) -->
+ <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_titles:1 (138837449700903545) -->
+ <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_titles:2 (4777177307869441982) -->
+ <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_summaries:0 (172302906231378902) -->
+ <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_summaries:1 (9091111147684472529) -->
+ <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_summaries:2 (3367904477834831032) -->
<string-array name="select_logd_size_titles">
<item msgid="8665206199209698501">"Ei käytössä"</item>
<item msgid="1593289376502312923">"64 kt"</item>
diff --git a/packages/SettingsLib/res/values-fi/strings.xml b/packages/SettingsLib/res/values-fi/strings.xml
index 648f7b3..79909ab 100644
--- a/packages/SettingsLib/res/values-fi/strings.xml
+++ b/packages/SettingsLib/res/values-fi/strings.xml
@@ -170,6 +170,26 @@
<string name="wifi_allow_scan_with_traffic" msgid="3601853081178265786">"Salli Wi-Fi-verkkovierailuskannaus aina"</string>
<string name="mobile_data_always_on" msgid="7745605759775320362">"Mobiilidata on aina käytössä"</string>
<string name="bluetooth_disable_absolute_volume" msgid="2660673801947898809">"Poista yleinen äänenvoimakkuuden säätö käytöstä"</string>
+ <!-- no translation found for bluetooth_select_a2dp_codec_type (90597356942154882) -->
+ <skip />
+ <!-- no translation found for bluetooth_select_a2dp_codec_type_dialog_title (6470824182074383881) -->
+ <skip />
+ <!-- no translation found for bluetooth_select_a2dp_codec_sample_rate (4788245703824623062) -->
+ <skip />
+ <!-- no translation found for bluetooth_select_a2dp_codec_sample_rate_dialog_title (4263851572248033749) -->
+ <skip />
+ <!-- no translation found for bluetooth_select_a2dp_codec_bits_per_sample (2099645202720164141) -->
+ <skip />
+ <!-- no translation found for bluetooth_select_a2dp_codec_bits_per_sample_dialog_title (2096170505745650345) -->
+ <skip />
+ <!-- no translation found for bluetooth_select_a2dp_codec_channel_mode (884855779449390540) -->
+ <skip />
+ <!-- no translation found for bluetooth_select_a2dp_codec_channel_mode_dialog_title (4073812880900816325) -->
+ <skip />
+ <!-- no translation found for bluetooth_select_a2dp_codec_ldac_playback_quality (4846872213548295632) -->
+ <skip />
+ <!-- no translation found for bluetooth_select_a2dp_codec_ldac_playback_quality_dialog_title (3940973633342423717) -->
+ <skip />
<string name="wifi_display_certification_summary" msgid="1155182309166746973">"Näytä langattoman näytön sertifiointiin liittyvät asetukset"</string>
<string name="wifi_verbose_logging_summary" msgid="6615071616111731958">"Lisää Wi‑Fin lokikirjaustasoa, näytä SSID RSSI -kohtaisesti Wi‑Fi-valitsimessa."</string>
<string name="wifi_aggressive_handover_summary" msgid="6328455667642570371">"Kun asetus on käytössä, Wi-Fi siirtää datayhteyden aggressiivisemmin matkapuhelinverkolle, jos Wi-Fi-signaali on heikko."</string>
diff --git a/packages/SettingsLib/res/values-fr-rCA/arrays.xml b/packages/SettingsLib/res/values-fr-rCA/arrays.xml
index 7515ecf..064f45f 100644
--- a/packages/SettingsLib/res/values-fr-rCA/arrays.xml
+++ b/packages/SettingsLib/res/values-fr-rCA/arrays.xml
@@ -58,6 +58,46 @@
<item msgid="3878793616631049349">"Utiliser la vérification HDCP uniquement pour le contenu GDN"</item>
<item msgid="45075631231212732">"Toujours utiliser la vérification HDCP"</item>
</string-array>
+ <!-- no translation found for bluetooth_a2dp_codec_titles:0 (1852387125374225729) -->
+ <!-- no translation found for bluetooth_a2dp_codec_titles:1 (7539690996561263909) -->
+ <!-- no translation found for bluetooth_a2dp_codec_titles:2 (4260844283202960798) -->
+ <!-- no translation found for bluetooth_a2dp_codec_titles:3 (7279983368484312990) -->
+ <!-- no translation found for bluetooth_a2dp_codec_titles:4 (2301339338870319651) -->
+ <!-- no translation found for bluetooth_a2dp_codec_summaries:0 (9072025520360316957) -->
+ <!-- no translation found for bluetooth_a2dp_codec_summaries:1 (6898329690939802290) -->
+ <!-- no translation found for bluetooth_a2dp_codec_summaries:2 (1190434429082395888) -->
+ <!-- no translation found for bluetooth_a2dp_codec_summaries:3 (649699003004233053) -->
+ <!-- no translation found for bluetooth_a2dp_codec_summaries:4 (508106435710925399) -->
+ <!-- no translation found for bluetooth_a2dp_codec_sample_rate_titles:0 (7102940318360468759) -->
+ <!-- no translation found for bluetooth_a2dp_codec_sample_rate_titles:1 (8895532488906185219) -->
+ <!-- no translation found for bluetooth_a2dp_codec_sample_rate_titles:2 (2909915718994807056) -->
+ <!-- no translation found for bluetooth_a2dp_codec_sample_rate_titles:3 (3347287377354164611) -->
+ <!-- no translation found for bluetooth_a2dp_codec_sample_rate_titles:4 (1234212100239985373) -->
+ <!-- no translation found for bluetooth_a2dp_codec_sample_rate_summaries:0 (7224433008148687313) -->
+ <!-- no translation found for bluetooth_a2dp_codec_sample_rate_summaries:1 (4482862757811638365) -->
+ <!-- no translation found for bluetooth_a2dp_codec_sample_rate_summaries:2 (354495328188724404) -->
+ <!-- no translation found for bluetooth_a2dp_codec_sample_rate_summaries:3 (7329816882213695083) -->
+ <!-- no translation found for bluetooth_a2dp_codec_sample_rate_summaries:4 (6967397666254430476) -->
+ <!-- no translation found for bluetooth_a2dp_codec_bits_per_sample_titles:0 (6694044160540313386) -->
+ <!-- no translation found for bluetooth_a2dp_codec_bits_per_sample_titles:1 (5618929009984956469) -->
+ <!-- no translation found for bluetooth_a2dp_codec_bits_per_sample_titles:2 (3412640499234627248) -->
+ <!-- no translation found for bluetooth_a2dp_codec_bits_per_sample_titles:3 (121583001492929387) -->
+ <!-- no translation found for bluetooth_a2dp_codec_bits_per_sample_summaries:0 (5091076677792306320) -->
+ <!-- no translation found for bluetooth_a2dp_codec_bits_per_sample_summaries:1 (4726688794884191540) -->
+ <!-- no translation found for bluetooth_a2dp_codec_bits_per_sample_summaries:2 (305344756485516870) -->
+ <!-- no translation found for bluetooth_a2dp_codec_bits_per_sample_summaries:3 (244568657919675099) -->
+ <!-- no translation found for bluetooth_a2dp_codec_channel_mode_titles:0 (13423709606339855) -->
+ <!-- no translation found for bluetooth_a2dp_codec_channel_mode_titles:1 (4106832974775067314) -->
+ <!-- no translation found for bluetooth_a2dp_codec_channel_mode_titles:2 (5571632958424639155) -->
+ <!-- no translation found for bluetooth_a2dp_codec_channel_mode_summaries:0 (8128478683963250130) -->
+ <!-- no translation found for bluetooth_a2dp_codec_channel_mode_summaries:1 (8900559293912978337) -->
+ <!-- no translation found for bluetooth_a2dp_codec_channel_mode_summaries:2 (8883739882299884241) -->
+ <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_titles:0 (2944889121850394020) -->
+ <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_titles:1 (138837449700903545) -->
+ <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_titles:2 (4777177307869441982) -->
+ <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_summaries:0 (172302906231378902) -->
+ <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_summaries:1 (9091111147684472529) -->
+ <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_summaries:2 (3367904477834831032) -->
<string-array name="select_logd_size_titles">
<item msgid="8665206199209698501">"Désactivé"</item>
<item msgid="1593289376502312923">"64 ko"</item>
diff --git a/packages/SettingsLib/res/values-fr-rCA/strings.xml b/packages/SettingsLib/res/values-fr-rCA/strings.xml
index afd343c..77ed339 100644
--- a/packages/SettingsLib/res/values-fr-rCA/strings.xml
+++ b/packages/SettingsLib/res/values-fr-rCA/strings.xml
@@ -170,6 +170,26 @@
<string name="wifi_allow_scan_with_traffic" msgid="3601853081178265786">"Toujours autoriser la détection de réseaux Wi-Fi en itinérance"</string>
<string name="mobile_data_always_on" msgid="7745605759775320362">"Données cellulaires toujours actives"</string>
<string name="bluetooth_disable_absolute_volume" msgid="2660673801947898809">"Désactiver le volume absolu"</string>
+ <!-- no translation found for bluetooth_select_a2dp_codec_type (90597356942154882) -->
+ <skip />
+ <!-- no translation found for bluetooth_select_a2dp_codec_type_dialog_title (6470824182074383881) -->
+ <skip />
+ <!-- no translation found for bluetooth_select_a2dp_codec_sample_rate (4788245703824623062) -->
+ <skip />
+ <!-- no translation found for bluetooth_select_a2dp_codec_sample_rate_dialog_title (4263851572248033749) -->
+ <skip />
+ <!-- no translation found for bluetooth_select_a2dp_codec_bits_per_sample (2099645202720164141) -->
+ <skip />
+ <!-- no translation found for bluetooth_select_a2dp_codec_bits_per_sample_dialog_title (2096170505745650345) -->
+ <skip />
+ <!-- no translation found for bluetooth_select_a2dp_codec_channel_mode (884855779449390540) -->
+ <skip />
+ <!-- no translation found for bluetooth_select_a2dp_codec_channel_mode_dialog_title (4073812880900816325) -->
+ <skip />
+ <!-- no translation found for bluetooth_select_a2dp_codec_ldac_playback_quality (4846872213548295632) -->
+ <skip />
+ <!-- no translation found for bluetooth_select_a2dp_codec_ldac_playback_quality_dialog_title (3940973633342423717) -->
+ <skip />
<string name="wifi_display_certification_summary" msgid="1155182309166746973">"Afficher les options pour la certification d\'affichage sans fil"</string>
<string name="wifi_verbose_logging_summary" msgid="6615071616111731958">"Détailler davantage les données Wi-Fi, afficher par SSID RSSI dans sélect. Wi-Fi"</string>
<string name="wifi_aggressive_handover_summary" msgid="6328455667642570371">"Si cette option est activée, le passage du Wi-Fi aux données cellulaires est forcé lorsque le signal Wi-Fi est faible"</string>
diff --git a/packages/SettingsLib/res/values-fr/arrays.xml b/packages/SettingsLib/res/values-fr/arrays.xml
index 59ad1fc..8ad3754 100644
--- a/packages/SettingsLib/res/values-fr/arrays.xml
+++ b/packages/SettingsLib/res/values-fr/arrays.xml
@@ -58,6 +58,46 @@
<item msgid="3878793616631049349">"Utiliser la vérification HDCP uniquement pour le contenu DRM"</item>
<item msgid="45075631231212732">"Toujours utiliser la vérification HDCP"</item>
</string-array>
+ <!-- no translation found for bluetooth_a2dp_codec_titles:0 (1852387125374225729) -->
+ <!-- no translation found for bluetooth_a2dp_codec_titles:1 (7539690996561263909) -->
+ <!-- no translation found for bluetooth_a2dp_codec_titles:2 (4260844283202960798) -->
+ <!-- no translation found for bluetooth_a2dp_codec_titles:3 (7279983368484312990) -->
+ <!-- no translation found for bluetooth_a2dp_codec_titles:4 (2301339338870319651) -->
+ <!-- no translation found for bluetooth_a2dp_codec_summaries:0 (9072025520360316957) -->
+ <!-- no translation found for bluetooth_a2dp_codec_summaries:1 (6898329690939802290) -->
+ <!-- no translation found for bluetooth_a2dp_codec_summaries:2 (1190434429082395888) -->
+ <!-- no translation found for bluetooth_a2dp_codec_summaries:3 (649699003004233053) -->
+ <!-- no translation found for bluetooth_a2dp_codec_summaries:4 (508106435710925399) -->
+ <!-- no translation found for bluetooth_a2dp_codec_sample_rate_titles:0 (7102940318360468759) -->
+ <!-- no translation found for bluetooth_a2dp_codec_sample_rate_titles:1 (8895532488906185219) -->
+ <!-- no translation found for bluetooth_a2dp_codec_sample_rate_titles:2 (2909915718994807056) -->
+ <!-- no translation found for bluetooth_a2dp_codec_sample_rate_titles:3 (3347287377354164611) -->
+ <!-- no translation found for bluetooth_a2dp_codec_sample_rate_titles:4 (1234212100239985373) -->
+ <!-- no translation found for bluetooth_a2dp_codec_sample_rate_summaries:0 (7224433008148687313) -->
+ <!-- no translation found for bluetooth_a2dp_codec_sample_rate_summaries:1 (4482862757811638365) -->
+ <!-- no translation found for bluetooth_a2dp_codec_sample_rate_summaries:2 (354495328188724404) -->
+ <!-- no translation found for bluetooth_a2dp_codec_sample_rate_summaries:3 (7329816882213695083) -->
+ <!-- no translation found for bluetooth_a2dp_codec_sample_rate_summaries:4 (6967397666254430476) -->
+ <!-- no translation found for bluetooth_a2dp_codec_bits_per_sample_titles:0 (6694044160540313386) -->
+ <!-- no translation found for bluetooth_a2dp_codec_bits_per_sample_titles:1 (5618929009984956469) -->
+ <!-- no translation found for bluetooth_a2dp_codec_bits_per_sample_titles:2 (3412640499234627248) -->
+ <!-- no translation found for bluetooth_a2dp_codec_bits_per_sample_titles:3 (121583001492929387) -->
+ <!-- no translation found for bluetooth_a2dp_codec_bits_per_sample_summaries:0 (5091076677792306320) -->
+ <!-- no translation found for bluetooth_a2dp_codec_bits_per_sample_summaries:1 (4726688794884191540) -->
+ <!-- no translation found for bluetooth_a2dp_codec_bits_per_sample_summaries:2 (305344756485516870) -->
+ <!-- no translation found for bluetooth_a2dp_codec_bits_per_sample_summaries:3 (244568657919675099) -->
+ <!-- no translation found for bluetooth_a2dp_codec_channel_mode_titles:0 (13423709606339855) -->
+ <!-- no translation found for bluetooth_a2dp_codec_channel_mode_titles:1 (4106832974775067314) -->
+ <!-- no translation found for bluetooth_a2dp_codec_channel_mode_titles:2 (5571632958424639155) -->
+ <!-- no translation found for bluetooth_a2dp_codec_channel_mode_summaries:0 (8128478683963250130) -->
+ <!-- no translation found for bluetooth_a2dp_codec_channel_mode_summaries:1 (8900559293912978337) -->
+ <!-- no translation found for bluetooth_a2dp_codec_channel_mode_summaries:2 (8883739882299884241) -->
+ <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_titles:0 (2944889121850394020) -->
+ <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_titles:1 (138837449700903545) -->
+ <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_titles:2 (4777177307869441982) -->
+ <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_summaries:0 (172302906231378902) -->
+ <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_summaries:1 (9091111147684472529) -->
+ <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_summaries:2 (3367904477834831032) -->
<string-array name="select_logd_size_titles">
<item msgid="8665206199209698501">"Désactivé"</item>
<item msgid="1593289376502312923">"64 Ko"</item>
diff --git a/packages/SettingsLib/res/values-fr/strings.xml b/packages/SettingsLib/res/values-fr/strings.xml
index 4d9d90c..e15cc3d 100644
--- a/packages/SettingsLib/res/values-fr/strings.xml
+++ b/packages/SettingsLib/res/values-fr/strings.xml
@@ -170,6 +170,26 @@
<string name="wifi_allow_scan_with_traffic" msgid="3601853081178265786">"Toujours autoriser la détection de réseaux Wi-Fi en itinérance"</string>
<string name="mobile_data_always_on" msgid="7745605759775320362">"Données mobiles toujours actives"</string>
<string name="bluetooth_disable_absolute_volume" msgid="2660673801947898809">"Désactiver le volume absolu"</string>
+ <!-- no translation found for bluetooth_select_a2dp_codec_type (90597356942154882) -->
+ <skip />
+ <!-- no translation found for bluetooth_select_a2dp_codec_type_dialog_title (6470824182074383881) -->
+ <skip />
+ <!-- no translation found for bluetooth_select_a2dp_codec_sample_rate (4788245703824623062) -->
+ <skip />
+ <!-- no translation found for bluetooth_select_a2dp_codec_sample_rate_dialog_title (4263851572248033749) -->
+ <skip />
+ <!-- no translation found for bluetooth_select_a2dp_codec_bits_per_sample (2099645202720164141) -->
+ <skip />
+ <!-- no translation found for bluetooth_select_a2dp_codec_bits_per_sample_dialog_title (2096170505745650345) -->
+ <skip />
+ <!-- no translation found for bluetooth_select_a2dp_codec_channel_mode (884855779449390540) -->
+ <skip />
+ <!-- no translation found for bluetooth_select_a2dp_codec_channel_mode_dialog_title (4073812880900816325) -->
+ <skip />
+ <!-- no translation found for bluetooth_select_a2dp_codec_ldac_playback_quality (4846872213548295632) -->
+ <skip />
+ <!-- no translation found for bluetooth_select_a2dp_codec_ldac_playback_quality_dialog_title (3940973633342423717) -->
+ <skip />
<string name="wifi_display_certification_summary" msgid="1155182309166746973">"Afficher les options de la certification de l\'affichage sans fil"</string>
<string name="wifi_verbose_logging_summary" msgid="6615071616111731958">"Détailler plus infos Wi-Fi, afficher par RSSI de SSID dans outil sélection Wi-Fi"</string>
<string name="wifi_aggressive_handover_summary" msgid="6328455667642570371">"Si cette option est activée, le passage du Wi-Fi aux données mobiles est forcé en cas de signal Wi-Fi faible."</string>
diff --git a/packages/SettingsLib/res/values-gl-rES/arrays.xml b/packages/SettingsLib/res/values-gl-rES/arrays.xml
index 1a9f6079..a7c8d32 100644
--- a/packages/SettingsLib/res/values-gl-rES/arrays.xml
+++ b/packages/SettingsLib/res/values-gl-rES/arrays.xml
@@ -58,6 +58,46 @@
<item msgid="3878793616631049349">"Utiliza a comprobación HDCP só para contido DRM"</item>
<item msgid="45075631231212732">"Utilizar sempre a comprobación HDCP"</item>
</string-array>
+ <!-- no translation found for bluetooth_a2dp_codec_titles:0 (1852387125374225729) -->
+ <!-- no translation found for bluetooth_a2dp_codec_titles:1 (7539690996561263909) -->
+ <!-- no translation found for bluetooth_a2dp_codec_titles:2 (4260844283202960798) -->
+ <!-- no translation found for bluetooth_a2dp_codec_titles:3 (7279983368484312990) -->
+ <!-- no translation found for bluetooth_a2dp_codec_titles:4 (2301339338870319651) -->
+ <!-- no translation found for bluetooth_a2dp_codec_summaries:0 (9072025520360316957) -->
+ <!-- no translation found for bluetooth_a2dp_codec_summaries:1 (6898329690939802290) -->
+ <!-- no translation found for bluetooth_a2dp_codec_summaries:2 (1190434429082395888) -->
+ <!-- no translation found for bluetooth_a2dp_codec_summaries:3 (649699003004233053) -->
+ <!-- no translation found for bluetooth_a2dp_codec_summaries:4 (508106435710925399) -->
+ <!-- no translation found for bluetooth_a2dp_codec_sample_rate_titles:0 (7102940318360468759) -->
+ <!-- no translation found for bluetooth_a2dp_codec_sample_rate_titles:1 (8895532488906185219) -->
+ <!-- no translation found for bluetooth_a2dp_codec_sample_rate_titles:2 (2909915718994807056) -->
+ <!-- no translation found for bluetooth_a2dp_codec_sample_rate_titles:3 (3347287377354164611) -->
+ <!-- no translation found for bluetooth_a2dp_codec_sample_rate_titles:4 (1234212100239985373) -->
+ <!-- no translation found for bluetooth_a2dp_codec_sample_rate_summaries:0 (7224433008148687313) -->
+ <!-- no translation found for bluetooth_a2dp_codec_sample_rate_summaries:1 (4482862757811638365) -->
+ <!-- no translation found for bluetooth_a2dp_codec_sample_rate_summaries:2 (354495328188724404) -->
+ <!-- no translation found for bluetooth_a2dp_codec_sample_rate_summaries:3 (7329816882213695083) -->
+ <!-- no translation found for bluetooth_a2dp_codec_sample_rate_summaries:4 (6967397666254430476) -->
+ <!-- no translation found for bluetooth_a2dp_codec_bits_per_sample_titles:0 (6694044160540313386) -->
+ <!-- no translation found for bluetooth_a2dp_codec_bits_per_sample_titles:1 (5618929009984956469) -->
+ <!-- no translation found for bluetooth_a2dp_codec_bits_per_sample_titles:2 (3412640499234627248) -->
+ <!-- no translation found for bluetooth_a2dp_codec_bits_per_sample_titles:3 (121583001492929387) -->
+ <!-- no translation found for bluetooth_a2dp_codec_bits_per_sample_summaries:0 (5091076677792306320) -->
+ <!-- no translation found for bluetooth_a2dp_codec_bits_per_sample_summaries:1 (4726688794884191540) -->
+ <!-- no translation found for bluetooth_a2dp_codec_bits_per_sample_summaries:2 (305344756485516870) -->
+ <!-- no translation found for bluetooth_a2dp_codec_bits_per_sample_summaries:3 (244568657919675099) -->
+ <!-- no translation found for bluetooth_a2dp_codec_channel_mode_titles:0 (13423709606339855) -->
+ <!-- no translation found for bluetooth_a2dp_codec_channel_mode_titles:1 (4106832974775067314) -->
+ <!-- no translation found for bluetooth_a2dp_codec_channel_mode_titles:2 (5571632958424639155) -->
+ <!-- no translation found for bluetooth_a2dp_codec_channel_mode_summaries:0 (8128478683963250130) -->
+ <!-- no translation found for bluetooth_a2dp_codec_channel_mode_summaries:1 (8900559293912978337) -->
+ <!-- no translation found for bluetooth_a2dp_codec_channel_mode_summaries:2 (8883739882299884241) -->
+ <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_titles:0 (2944889121850394020) -->
+ <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_titles:1 (138837449700903545) -->
+ <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_titles:2 (4777177307869441982) -->
+ <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_summaries:0 (172302906231378902) -->
+ <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_summaries:1 (9091111147684472529) -->
+ <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_summaries:2 (3367904477834831032) -->
<string-array name="select_logd_size_titles">
<item msgid="8665206199209698501">"Desactivado"</item>
<item msgid="1593289376502312923">"64 K"</item>
diff --git a/packages/SettingsLib/res/values-gl-rES/strings.xml b/packages/SettingsLib/res/values-gl-rES/strings.xml
index 1110fe2..bdc0a4d 100644
--- a/packages/SettingsLib/res/values-gl-rES/strings.xml
+++ b/packages/SettingsLib/res/values-gl-rES/strings.xml
@@ -170,6 +170,26 @@
<string name="wifi_allow_scan_with_traffic" msgid="3601853081178265786">"Permitir sempre buscas de itinerancia da wifi"</string>
<string name="mobile_data_always_on" msgid="7745605759775320362">"Datos móbiles sempre activados"</string>
<string name="bluetooth_disable_absolute_volume" msgid="2660673801947898809">"Desactivar volume absoluto"</string>
+ <!-- no translation found for bluetooth_select_a2dp_codec_type (90597356942154882) -->
+ <skip />
+ <!-- no translation found for bluetooth_select_a2dp_codec_type_dialog_title (6470824182074383881) -->
+ <skip />
+ <!-- no translation found for bluetooth_select_a2dp_codec_sample_rate (4788245703824623062) -->
+ <skip />
+ <!-- no translation found for bluetooth_select_a2dp_codec_sample_rate_dialog_title (4263851572248033749) -->
+ <skip />
+ <!-- no translation found for bluetooth_select_a2dp_codec_bits_per_sample (2099645202720164141) -->
+ <skip />
+ <!-- no translation found for bluetooth_select_a2dp_codec_bits_per_sample_dialog_title (2096170505745650345) -->
+ <skip />
+ <!-- no translation found for bluetooth_select_a2dp_codec_channel_mode (884855779449390540) -->
+ <skip />
+ <!-- no translation found for bluetooth_select_a2dp_codec_channel_mode_dialog_title (4073812880900816325) -->
+ <skip />
+ <!-- no translation found for bluetooth_select_a2dp_codec_ldac_playback_quality (4846872213548295632) -->
+ <skip />
+ <!-- no translation found for bluetooth_select_a2dp_codec_ldac_playback_quality_dialog_title (3940973633342423717) -->
+ <skip />
<string name="wifi_display_certification_summary" msgid="1155182309166746973">"Mostra opcións para o certificado de visualización sen fíos"</string>
<string name="wifi_verbose_logging_summary" msgid="6615071616111731958">"Aumentar o nivel de rexistro da wifi, mostrar por SSID RSSI no selector de wifi"</string>
<string name="wifi_aggressive_handover_summary" msgid="6328455667642570371">"Cando está activada esta función, a wifi será máis agresiva ao entregar a conexión de datos ao móbil, cando o sinal wifi é feble"</string>
diff --git a/packages/SettingsLib/res/values-gu-rIN/arrays.xml b/packages/SettingsLib/res/values-gu-rIN/arrays.xml
index e097159..45c4726 100644
--- a/packages/SettingsLib/res/values-gu-rIN/arrays.xml
+++ b/packages/SettingsLib/res/values-gu-rIN/arrays.xml
@@ -58,6 +58,46 @@
<item msgid="3878793616631049349">"ફક્ત DRM સામગ્રી માટે HDCP તપાસનો ઉપયોગ કરો"</item>
<item msgid="45075631231212732">"હંમેશા HDCP તપાસનો ઉપયોગ કરો"</item>
</string-array>
+ <!-- no translation found for bluetooth_a2dp_codec_titles:0 (1852387125374225729) -->
+ <!-- no translation found for bluetooth_a2dp_codec_titles:1 (7539690996561263909) -->
+ <!-- no translation found for bluetooth_a2dp_codec_titles:2 (4260844283202960798) -->
+ <!-- no translation found for bluetooth_a2dp_codec_titles:3 (7279983368484312990) -->
+ <!-- no translation found for bluetooth_a2dp_codec_titles:4 (2301339338870319651) -->
+ <!-- no translation found for bluetooth_a2dp_codec_summaries:0 (9072025520360316957) -->
+ <!-- no translation found for bluetooth_a2dp_codec_summaries:1 (6898329690939802290) -->
+ <!-- no translation found for bluetooth_a2dp_codec_summaries:2 (1190434429082395888) -->
+ <!-- no translation found for bluetooth_a2dp_codec_summaries:3 (649699003004233053) -->
+ <!-- no translation found for bluetooth_a2dp_codec_summaries:4 (508106435710925399) -->
+ <!-- no translation found for bluetooth_a2dp_codec_sample_rate_titles:0 (7102940318360468759) -->
+ <!-- no translation found for bluetooth_a2dp_codec_sample_rate_titles:1 (8895532488906185219) -->
+ <!-- no translation found for bluetooth_a2dp_codec_sample_rate_titles:2 (2909915718994807056) -->
+ <!-- no translation found for bluetooth_a2dp_codec_sample_rate_titles:3 (3347287377354164611) -->
+ <!-- no translation found for bluetooth_a2dp_codec_sample_rate_titles:4 (1234212100239985373) -->
+ <!-- no translation found for bluetooth_a2dp_codec_sample_rate_summaries:0 (7224433008148687313) -->
+ <!-- no translation found for bluetooth_a2dp_codec_sample_rate_summaries:1 (4482862757811638365) -->
+ <!-- no translation found for bluetooth_a2dp_codec_sample_rate_summaries:2 (354495328188724404) -->
+ <!-- no translation found for bluetooth_a2dp_codec_sample_rate_summaries:3 (7329816882213695083) -->
+ <!-- no translation found for bluetooth_a2dp_codec_sample_rate_summaries:4 (6967397666254430476) -->
+ <!-- no translation found for bluetooth_a2dp_codec_bits_per_sample_titles:0 (6694044160540313386) -->
+ <!-- no translation found for bluetooth_a2dp_codec_bits_per_sample_titles:1 (5618929009984956469) -->
+ <!-- no translation found for bluetooth_a2dp_codec_bits_per_sample_titles:2 (3412640499234627248) -->
+ <!-- no translation found for bluetooth_a2dp_codec_bits_per_sample_titles:3 (121583001492929387) -->
+ <!-- no translation found for bluetooth_a2dp_codec_bits_per_sample_summaries:0 (5091076677792306320) -->
+ <!-- no translation found for bluetooth_a2dp_codec_bits_per_sample_summaries:1 (4726688794884191540) -->
+ <!-- no translation found for bluetooth_a2dp_codec_bits_per_sample_summaries:2 (305344756485516870) -->
+ <!-- no translation found for bluetooth_a2dp_codec_bits_per_sample_summaries:3 (244568657919675099) -->
+ <!-- no translation found for bluetooth_a2dp_codec_channel_mode_titles:0 (13423709606339855) -->
+ <!-- no translation found for bluetooth_a2dp_codec_channel_mode_titles:1 (4106832974775067314) -->
+ <!-- no translation found for bluetooth_a2dp_codec_channel_mode_titles:2 (5571632958424639155) -->
+ <!-- no translation found for bluetooth_a2dp_codec_channel_mode_summaries:0 (8128478683963250130) -->
+ <!-- no translation found for bluetooth_a2dp_codec_channel_mode_summaries:1 (8900559293912978337) -->
+ <!-- no translation found for bluetooth_a2dp_codec_channel_mode_summaries:2 (8883739882299884241) -->
+ <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_titles:0 (2944889121850394020) -->
+ <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_titles:1 (138837449700903545) -->
+ <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_titles:2 (4777177307869441982) -->
+ <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_summaries:0 (172302906231378902) -->
+ <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_summaries:1 (9091111147684472529) -->
+ <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_summaries:2 (3367904477834831032) -->
<string-array name="select_logd_size_titles">
<item msgid="8665206199209698501">"બંધ"</item>
<item msgid="1593289376502312923">"64K"</item>
diff --git a/packages/SettingsLib/res/values-gu-rIN/strings.xml b/packages/SettingsLib/res/values-gu-rIN/strings.xml
index a732ea1..f55fd28 100644
--- a/packages/SettingsLib/res/values-gu-rIN/strings.xml
+++ b/packages/SettingsLib/res/values-gu-rIN/strings.xml
@@ -170,6 +170,26 @@
<string name="wifi_allow_scan_with_traffic" msgid="3601853081178265786">"હંમેશા Wi‑Fi રોમ સ્કૅન્સને મંજૂરી આપો"</string>
<string name="mobile_data_always_on" msgid="7745605759775320362">"સેલ્યુલર ડેટા હંમેશા સક્રિય"</string>
<string name="bluetooth_disable_absolute_volume" msgid="2660673801947898809">"ચોક્કસ વૉલ્યૂમને અક્ષમ કરો"</string>
+ <!-- no translation found for bluetooth_select_a2dp_codec_type (90597356942154882) -->
+ <skip />
+ <!-- no translation found for bluetooth_select_a2dp_codec_type_dialog_title (6470824182074383881) -->
+ <skip />
+ <!-- no translation found for bluetooth_select_a2dp_codec_sample_rate (4788245703824623062) -->
+ <skip />
+ <!-- no translation found for bluetooth_select_a2dp_codec_sample_rate_dialog_title (4263851572248033749) -->
+ <skip />
+ <!-- no translation found for bluetooth_select_a2dp_codec_bits_per_sample (2099645202720164141) -->
+ <skip />
+ <!-- no translation found for bluetooth_select_a2dp_codec_bits_per_sample_dialog_title (2096170505745650345) -->
+ <skip />
+ <!-- no translation found for bluetooth_select_a2dp_codec_channel_mode (884855779449390540) -->
+ <skip />
+ <!-- no translation found for bluetooth_select_a2dp_codec_channel_mode_dialog_title (4073812880900816325) -->
+ <skip />
+ <!-- no translation found for bluetooth_select_a2dp_codec_ldac_playback_quality (4846872213548295632) -->
+ <skip />
+ <!-- no translation found for bluetooth_select_a2dp_codec_ldac_playback_quality_dialog_title (3940973633342423717) -->
+ <skip />
<string name="wifi_display_certification_summary" msgid="1155182309166746973">"વાયરલેસ ડિસ્પ્લે પ્રમાણપત્ર માટેના વિકલ્પો બતાવો"</string>
<string name="wifi_verbose_logging_summary" msgid="6615071616111731958">"Wi‑Fi લોગિંગ સ્તર વધારો, Wi‑Fi પીકરમાં SSID RSSI દીઠ બતાવો"</string>
<string name="wifi_aggressive_handover_summary" msgid="6328455667642570371">"જ્યારે સક્ષમ હોય, ત્યારે Wi‑Fi સિગ્નલ ઓછા હોવા પર, સેલ્યુલર પર ડેટા કનેક્શન મોકલવામાં વધુ આક્રમક હશે"</string>
diff --git a/packages/SettingsLib/res/values-hi/arrays.xml b/packages/SettingsLib/res/values-hi/arrays.xml
index 9b03f5f..6e9a088 100644
--- a/packages/SettingsLib/res/values-hi/arrays.xml
+++ b/packages/SettingsLib/res/values-hi/arrays.xml
@@ -58,6 +58,46 @@
<item msgid="3878793616631049349">"HDCP जांच का उपयोग केवल DRM सामग्री के लिए करें"</item>
<item msgid="45075631231212732">"हमेशा HDCP जांच का उपयोग करें"</item>
</string-array>
+ <!-- no translation found for bluetooth_a2dp_codec_titles:0 (1852387125374225729) -->
+ <!-- no translation found for bluetooth_a2dp_codec_titles:1 (7539690996561263909) -->
+ <!-- no translation found for bluetooth_a2dp_codec_titles:2 (4260844283202960798) -->
+ <!-- no translation found for bluetooth_a2dp_codec_titles:3 (7279983368484312990) -->
+ <!-- no translation found for bluetooth_a2dp_codec_titles:4 (2301339338870319651) -->
+ <!-- no translation found for bluetooth_a2dp_codec_summaries:0 (9072025520360316957) -->
+ <!-- no translation found for bluetooth_a2dp_codec_summaries:1 (6898329690939802290) -->
+ <!-- no translation found for bluetooth_a2dp_codec_summaries:2 (1190434429082395888) -->
+ <!-- no translation found for bluetooth_a2dp_codec_summaries:3 (649699003004233053) -->
+ <!-- no translation found for bluetooth_a2dp_codec_summaries:4 (508106435710925399) -->
+ <!-- no translation found for bluetooth_a2dp_codec_sample_rate_titles:0 (7102940318360468759) -->
+ <!-- no translation found for bluetooth_a2dp_codec_sample_rate_titles:1 (8895532488906185219) -->
+ <!-- no translation found for bluetooth_a2dp_codec_sample_rate_titles:2 (2909915718994807056) -->
+ <!-- no translation found for bluetooth_a2dp_codec_sample_rate_titles:3 (3347287377354164611) -->
+ <!-- no translation found for bluetooth_a2dp_codec_sample_rate_titles:4 (1234212100239985373) -->
+ <!-- no translation found for bluetooth_a2dp_codec_sample_rate_summaries:0 (7224433008148687313) -->
+ <!-- no translation found for bluetooth_a2dp_codec_sample_rate_summaries:1 (4482862757811638365) -->
+ <!-- no translation found for bluetooth_a2dp_codec_sample_rate_summaries:2 (354495328188724404) -->
+ <!-- no translation found for bluetooth_a2dp_codec_sample_rate_summaries:3 (7329816882213695083) -->
+ <!-- no translation found for bluetooth_a2dp_codec_sample_rate_summaries:4 (6967397666254430476) -->
+ <!-- no translation found for bluetooth_a2dp_codec_bits_per_sample_titles:0 (6694044160540313386) -->
+ <!-- no translation found for bluetooth_a2dp_codec_bits_per_sample_titles:1 (5618929009984956469) -->
+ <!-- no translation found for bluetooth_a2dp_codec_bits_per_sample_titles:2 (3412640499234627248) -->
+ <!-- no translation found for bluetooth_a2dp_codec_bits_per_sample_titles:3 (121583001492929387) -->
+ <!-- no translation found for bluetooth_a2dp_codec_bits_per_sample_summaries:0 (5091076677792306320) -->
+ <!-- no translation found for bluetooth_a2dp_codec_bits_per_sample_summaries:1 (4726688794884191540) -->
+ <!-- no translation found for bluetooth_a2dp_codec_bits_per_sample_summaries:2 (305344756485516870) -->
+ <!-- no translation found for bluetooth_a2dp_codec_bits_per_sample_summaries:3 (244568657919675099) -->
+ <!-- no translation found for bluetooth_a2dp_codec_channel_mode_titles:0 (13423709606339855) -->
+ <!-- no translation found for bluetooth_a2dp_codec_channel_mode_titles:1 (4106832974775067314) -->
+ <!-- no translation found for bluetooth_a2dp_codec_channel_mode_titles:2 (5571632958424639155) -->
+ <!-- no translation found for bluetooth_a2dp_codec_channel_mode_summaries:0 (8128478683963250130) -->
+ <!-- no translation found for bluetooth_a2dp_codec_channel_mode_summaries:1 (8900559293912978337) -->
+ <!-- no translation found for bluetooth_a2dp_codec_channel_mode_summaries:2 (8883739882299884241) -->
+ <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_titles:0 (2944889121850394020) -->
+ <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_titles:1 (138837449700903545) -->
+ <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_titles:2 (4777177307869441982) -->
+ <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_summaries:0 (172302906231378902) -->
+ <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_summaries:1 (9091111147684472529) -->
+ <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_summaries:2 (3367904477834831032) -->
<string-array name="select_logd_size_titles">
<item msgid="8665206199209698501">"बंद"</item>
<item msgid="1593289376502312923">"64K"</item>
diff --git a/packages/SettingsLib/res/values-hi/strings.xml b/packages/SettingsLib/res/values-hi/strings.xml
index eefdff1..2600479 100644
--- a/packages/SettingsLib/res/values-hi/strings.xml
+++ b/packages/SettingsLib/res/values-hi/strings.xml
@@ -79,7 +79,7 @@
<string name="bluetooth_pairing_device_down_error_message" msgid="7870998403045801381">"<xliff:g id="DEVICE_NAME">%1$s</xliff:g> से संचार नहीं कर सकता."</string>
<string name="bluetooth_pairing_rejected_error_message" msgid="1648157108520832454">"<xliff:g id="DEVICE_NAME">%1$s</xliff:g> द्वारा युग्मन अस्वीकृत किया गया."</string>
<string name="accessibility_wifi_off" msgid="1166761729660614716">"वाई-फ़ाई बंद है."</string>
- <string name="accessibility_no_wifi" msgid="8834610636137374508">"वाई-फ़ाई डिस्कनेक्ट है."</string>
+ <string name="accessibility_no_wifi" msgid="8834610636137374508">"वाई-फ़ाई डिसकनेक्ट है."</string>
<string name="accessibility_wifi_one_bar" msgid="4869376278894301820">"वाई-फ़ाई का एक बार है."</string>
<string name="accessibility_wifi_two_bars" msgid="3569851234710034416">"वाई-फ़ाई की दो पट्टी मिल रही हैं."</string>
<string name="accessibility_wifi_three_bars" msgid="8134185644861380311">"वाई-फ़ाई की एक पट्टी मिल रही है."</string>
@@ -170,6 +170,26 @@
<string name="wifi_allow_scan_with_traffic" msgid="3601853081178265786">"हमेशा वाई-फ़ाई रोम स्कैन करने दें"</string>
<string name="mobile_data_always_on" msgid="7745605759775320362">"सेल्युलर डेटा हमेशा सक्रिय"</string>
<string name="bluetooth_disable_absolute_volume" msgid="2660673801947898809">"पूर्ण वॉल्यूम अक्षम करें"</string>
+ <!-- no translation found for bluetooth_select_a2dp_codec_type (90597356942154882) -->
+ <skip />
+ <!-- no translation found for bluetooth_select_a2dp_codec_type_dialog_title (6470824182074383881) -->
+ <skip />
+ <!-- no translation found for bluetooth_select_a2dp_codec_sample_rate (4788245703824623062) -->
+ <skip />
+ <!-- no translation found for bluetooth_select_a2dp_codec_sample_rate_dialog_title (4263851572248033749) -->
+ <skip />
+ <!-- no translation found for bluetooth_select_a2dp_codec_bits_per_sample (2099645202720164141) -->
+ <skip />
+ <!-- no translation found for bluetooth_select_a2dp_codec_bits_per_sample_dialog_title (2096170505745650345) -->
+ <skip />
+ <!-- no translation found for bluetooth_select_a2dp_codec_channel_mode (884855779449390540) -->
+ <skip />
+ <!-- no translation found for bluetooth_select_a2dp_codec_channel_mode_dialog_title (4073812880900816325) -->
+ <skip />
+ <!-- no translation found for bluetooth_select_a2dp_codec_ldac_playback_quality (4846872213548295632) -->
+ <skip />
+ <!-- no translation found for bluetooth_select_a2dp_codec_ldac_playback_quality_dialog_title (3940973633342423717) -->
+ <skip />
<string name="wifi_display_certification_summary" msgid="1155182309166746973">"वायरलेस दिखाई देने के लिए प्रमाणन विकल्प दिखाएं"</string>
<string name="wifi_verbose_logging_summary" msgid="6615071616111731958">"वाई-फ़ाई प्रवेश स्तर बढ़ाएं, वाई-फ़ाई पिकर में प्रति SSID RSSI दिखाएं"</string>
<string name="wifi_aggressive_handover_summary" msgid="6328455667642570371">"इसके सक्षम होने पर, जब वाई-फ़ाई संकेत कमज़ोर हों तो वाई-फ़ाई, डेटा कनेक्शन को सेल्यूलर पर अधिक बलपूर्वक भेजेगा"</string>
diff --git a/packages/SettingsLib/res/values-hr/arrays.xml b/packages/SettingsLib/res/values-hr/arrays.xml
index 42d6bd5..0b96cc6 100644
--- a/packages/SettingsLib/res/values-hr/arrays.xml
+++ b/packages/SettingsLib/res/values-hr/arrays.xml
@@ -58,6 +58,46 @@
<item msgid="3878793616631049349">"Upotrebljavaj HDCP provjeru samo za DRM sadržaj"</item>
<item msgid="45075631231212732">"Uvijek upotrebljavaj HDCP provjeru"</item>
</string-array>
+ <!-- no translation found for bluetooth_a2dp_codec_titles:0 (1852387125374225729) -->
+ <!-- no translation found for bluetooth_a2dp_codec_titles:1 (7539690996561263909) -->
+ <!-- no translation found for bluetooth_a2dp_codec_titles:2 (4260844283202960798) -->
+ <!-- no translation found for bluetooth_a2dp_codec_titles:3 (7279983368484312990) -->
+ <!-- no translation found for bluetooth_a2dp_codec_titles:4 (2301339338870319651) -->
+ <!-- no translation found for bluetooth_a2dp_codec_summaries:0 (9072025520360316957) -->
+ <!-- no translation found for bluetooth_a2dp_codec_summaries:1 (6898329690939802290) -->
+ <!-- no translation found for bluetooth_a2dp_codec_summaries:2 (1190434429082395888) -->
+ <!-- no translation found for bluetooth_a2dp_codec_summaries:3 (649699003004233053) -->
+ <!-- no translation found for bluetooth_a2dp_codec_summaries:4 (508106435710925399) -->
+ <!-- no translation found for bluetooth_a2dp_codec_sample_rate_titles:0 (7102940318360468759) -->
+ <!-- no translation found for bluetooth_a2dp_codec_sample_rate_titles:1 (8895532488906185219) -->
+ <!-- no translation found for bluetooth_a2dp_codec_sample_rate_titles:2 (2909915718994807056) -->
+ <!-- no translation found for bluetooth_a2dp_codec_sample_rate_titles:3 (3347287377354164611) -->
+ <!-- no translation found for bluetooth_a2dp_codec_sample_rate_titles:4 (1234212100239985373) -->
+ <!-- no translation found for bluetooth_a2dp_codec_sample_rate_summaries:0 (7224433008148687313) -->
+ <!-- no translation found for bluetooth_a2dp_codec_sample_rate_summaries:1 (4482862757811638365) -->
+ <!-- no translation found for bluetooth_a2dp_codec_sample_rate_summaries:2 (354495328188724404) -->
+ <!-- no translation found for bluetooth_a2dp_codec_sample_rate_summaries:3 (7329816882213695083) -->
+ <!-- no translation found for bluetooth_a2dp_codec_sample_rate_summaries:4 (6967397666254430476) -->
+ <!-- no translation found for bluetooth_a2dp_codec_bits_per_sample_titles:0 (6694044160540313386) -->
+ <!-- no translation found for bluetooth_a2dp_codec_bits_per_sample_titles:1 (5618929009984956469) -->
+ <!-- no translation found for bluetooth_a2dp_codec_bits_per_sample_titles:2 (3412640499234627248) -->
+ <!-- no translation found for bluetooth_a2dp_codec_bits_per_sample_titles:3 (121583001492929387) -->
+ <!-- no translation found for bluetooth_a2dp_codec_bits_per_sample_summaries:0 (5091076677792306320) -->
+ <!-- no translation found for bluetooth_a2dp_codec_bits_per_sample_summaries:1 (4726688794884191540) -->
+ <!-- no translation found for bluetooth_a2dp_codec_bits_per_sample_summaries:2 (305344756485516870) -->
+ <!-- no translation found for bluetooth_a2dp_codec_bits_per_sample_summaries:3 (244568657919675099) -->
+ <!-- no translation found for bluetooth_a2dp_codec_channel_mode_titles:0 (13423709606339855) -->
+ <!-- no translation found for bluetooth_a2dp_codec_channel_mode_titles:1 (4106832974775067314) -->
+ <!-- no translation found for bluetooth_a2dp_codec_channel_mode_titles:2 (5571632958424639155) -->
+ <!-- no translation found for bluetooth_a2dp_codec_channel_mode_summaries:0 (8128478683963250130) -->
+ <!-- no translation found for bluetooth_a2dp_codec_channel_mode_summaries:1 (8900559293912978337) -->
+ <!-- no translation found for bluetooth_a2dp_codec_channel_mode_summaries:2 (8883739882299884241) -->
+ <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_titles:0 (2944889121850394020) -->
+ <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_titles:1 (138837449700903545) -->
+ <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_titles:2 (4777177307869441982) -->
+ <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_summaries:0 (172302906231378902) -->
+ <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_summaries:1 (9091111147684472529) -->
+ <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_summaries:2 (3367904477834831032) -->
<string-array name="select_logd_size_titles">
<item msgid="8665206199209698501">"Isključeno"</item>
<item msgid="1593289376502312923">"64 KB"</item>
diff --git a/packages/SettingsLib/res/values-hr/strings.xml b/packages/SettingsLib/res/values-hr/strings.xml
index 9b38b61..a4c965d 100644
--- a/packages/SettingsLib/res/values-hr/strings.xml
+++ b/packages/SettingsLib/res/values-hr/strings.xml
@@ -170,6 +170,26 @@
<string name="wifi_allow_scan_with_traffic" msgid="3601853081178265786">"Uvijek dopusti slobodno traženje Wi-Fi mreže"</string>
<string name="mobile_data_always_on" msgid="7745605759775320362">"Mobilni podaci uvijek aktivni"</string>
<string name="bluetooth_disable_absolute_volume" msgid="2660673801947898809">"Onemogući apsolutnu glasnoću"</string>
+ <!-- no translation found for bluetooth_select_a2dp_codec_type (90597356942154882) -->
+ <skip />
+ <!-- no translation found for bluetooth_select_a2dp_codec_type_dialog_title (6470824182074383881) -->
+ <skip />
+ <!-- no translation found for bluetooth_select_a2dp_codec_sample_rate (4788245703824623062) -->
+ <skip />
+ <!-- no translation found for bluetooth_select_a2dp_codec_sample_rate_dialog_title (4263851572248033749) -->
+ <skip />
+ <!-- no translation found for bluetooth_select_a2dp_codec_bits_per_sample (2099645202720164141) -->
+ <skip />
+ <!-- no translation found for bluetooth_select_a2dp_codec_bits_per_sample_dialog_title (2096170505745650345) -->
+ <skip />
+ <!-- no translation found for bluetooth_select_a2dp_codec_channel_mode (884855779449390540) -->
+ <skip />
+ <!-- no translation found for bluetooth_select_a2dp_codec_channel_mode_dialog_title (4073812880900816325) -->
+ <skip />
+ <!-- no translation found for bluetooth_select_a2dp_codec_ldac_playback_quality (4846872213548295632) -->
+ <skip />
+ <!-- no translation found for bluetooth_select_a2dp_codec_ldac_playback_quality_dialog_title (3940973633342423717) -->
+ <skip />
<string name="wifi_display_certification_summary" msgid="1155182309166746973">"Prikaži opcije za certifikaciju bežičnog prikaza"</string>
<string name="wifi_verbose_logging_summary" msgid="6615071616111731958">"Povećana razina prijave na Wi‑Fi, prikaz po SSID RSSI-ju u Biraču Wi‑Fi-ja"</string>
<string name="wifi_aggressive_handover_summary" msgid="6328455667642570371">"Ako je omogućeno, Wi-Fi će aktivno prebacivati podatkovnu vezu mobilnoj mreži kada je Wi-Fi signal slab."</string>
diff --git a/packages/SettingsLib/res/values-hu/arrays.xml b/packages/SettingsLib/res/values-hu/arrays.xml
index a5a8a9b..9ef6995 100644
--- a/packages/SettingsLib/res/values-hu/arrays.xml
+++ b/packages/SettingsLib/res/values-hu/arrays.xml
@@ -58,6 +58,46 @@
<item msgid="3878793616631049349">"Csak DRM-tartalomhoz használjon HDCP ellenőrzést"</item>
<item msgid="45075631231212732">"Mindig használjon HDCP ellenőrzést"</item>
</string-array>
+ <!-- no translation found for bluetooth_a2dp_codec_titles:0 (1852387125374225729) -->
+ <!-- no translation found for bluetooth_a2dp_codec_titles:1 (7539690996561263909) -->
+ <!-- no translation found for bluetooth_a2dp_codec_titles:2 (4260844283202960798) -->
+ <!-- no translation found for bluetooth_a2dp_codec_titles:3 (7279983368484312990) -->
+ <!-- no translation found for bluetooth_a2dp_codec_titles:4 (2301339338870319651) -->
+ <!-- no translation found for bluetooth_a2dp_codec_summaries:0 (9072025520360316957) -->
+ <!-- no translation found for bluetooth_a2dp_codec_summaries:1 (6898329690939802290) -->
+ <!-- no translation found for bluetooth_a2dp_codec_summaries:2 (1190434429082395888) -->
+ <!-- no translation found for bluetooth_a2dp_codec_summaries:3 (649699003004233053) -->
+ <!-- no translation found for bluetooth_a2dp_codec_summaries:4 (508106435710925399) -->
+ <!-- no translation found for bluetooth_a2dp_codec_sample_rate_titles:0 (7102940318360468759) -->
+ <!-- no translation found for bluetooth_a2dp_codec_sample_rate_titles:1 (8895532488906185219) -->
+ <!-- no translation found for bluetooth_a2dp_codec_sample_rate_titles:2 (2909915718994807056) -->
+ <!-- no translation found for bluetooth_a2dp_codec_sample_rate_titles:3 (3347287377354164611) -->
+ <!-- no translation found for bluetooth_a2dp_codec_sample_rate_titles:4 (1234212100239985373) -->
+ <!-- no translation found for bluetooth_a2dp_codec_sample_rate_summaries:0 (7224433008148687313) -->
+ <!-- no translation found for bluetooth_a2dp_codec_sample_rate_summaries:1 (4482862757811638365) -->
+ <!-- no translation found for bluetooth_a2dp_codec_sample_rate_summaries:2 (354495328188724404) -->
+ <!-- no translation found for bluetooth_a2dp_codec_sample_rate_summaries:3 (7329816882213695083) -->
+ <!-- no translation found for bluetooth_a2dp_codec_sample_rate_summaries:4 (6967397666254430476) -->
+ <!-- no translation found for bluetooth_a2dp_codec_bits_per_sample_titles:0 (6694044160540313386) -->
+ <!-- no translation found for bluetooth_a2dp_codec_bits_per_sample_titles:1 (5618929009984956469) -->
+ <!-- no translation found for bluetooth_a2dp_codec_bits_per_sample_titles:2 (3412640499234627248) -->
+ <!-- no translation found for bluetooth_a2dp_codec_bits_per_sample_titles:3 (121583001492929387) -->
+ <!-- no translation found for bluetooth_a2dp_codec_bits_per_sample_summaries:0 (5091076677792306320) -->
+ <!-- no translation found for bluetooth_a2dp_codec_bits_per_sample_summaries:1 (4726688794884191540) -->
+ <!-- no translation found for bluetooth_a2dp_codec_bits_per_sample_summaries:2 (305344756485516870) -->
+ <!-- no translation found for bluetooth_a2dp_codec_bits_per_sample_summaries:3 (244568657919675099) -->
+ <!-- no translation found for bluetooth_a2dp_codec_channel_mode_titles:0 (13423709606339855) -->
+ <!-- no translation found for bluetooth_a2dp_codec_channel_mode_titles:1 (4106832974775067314) -->
+ <!-- no translation found for bluetooth_a2dp_codec_channel_mode_titles:2 (5571632958424639155) -->
+ <!-- no translation found for bluetooth_a2dp_codec_channel_mode_summaries:0 (8128478683963250130) -->
+ <!-- no translation found for bluetooth_a2dp_codec_channel_mode_summaries:1 (8900559293912978337) -->
+ <!-- no translation found for bluetooth_a2dp_codec_channel_mode_summaries:2 (8883739882299884241) -->
+ <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_titles:0 (2944889121850394020) -->
+ <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_titles:1 (138837449700903545) -->
+ <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_titles:2 (4777177307869441982) -->
+ <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_summaries:0 (172302906231378902) -->
+ <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_summaries:1 (9091111147684472529) -->
+ <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_summaries:2 (3367904477834831032) -->
<string-array name="select_logd_size_titles">
<item msgid="8665206199209698501">"Ki"</item>
<item msgid="1593289376502312923">"64 KB"</item>
diff --git a/packages/SettingsLib/res/values-hu/strings.xml b/packages/SettingsLib/res/values-hu/strings.xml
index a373545..323a14c 100644
--- a/packages/SettingsLib/res/values-hu/strings.xml
+++ b/packages/SettingsLib/res/values-hu/strings.xml
@@ -170,6 +170,26 @@
<string name="wifi_allow_scan_with_traffic" msgid="3601853081178265786">"Wi‑Fi-roaming ellenőrzésének engedélyezése mindig"</string>
<string name="mobile_data_always_on" msgid="7745605759775320362">"A mobilhálózati adatforgalom mindig aktív"</string>
<string name="bluetooth_disable_absolute_volume" msgid="2660673801947898809">"Abszolút hangerő funkció letiltása"</string>
+ <!-- no translation found for bluetooth_select_a2dp_codec_type (90597356942154882) -->
+ <skip />
+ <!-- no translation found for bluetooth_select_a2dp_codec_type_dialog_title (6470824182074383881) -->
+ <skip />
+ <!-- no translation found for bluetooth_select_a2dp_codec_sample_rate (4788245703824623062) -->
+ <skip />
+ <!-- no translation found for bluetooth_select_a2dp_codec_sample_rate_dialog_title (4263851572248033749) -->
+ <skip />
+ <!-- no translation found for bluetooth_select_a2dp_codec_bits_per_sample (2099645202720164141) -->
+ <skip />
+ <!-- no translation found for bluetooth_select_a2dp_codec_bits_per_sample_dialog_title (2096170505745650345) -->
+ <skip />
+ <!-- no translation found for bluetooth_select_a2dp_codec_channel_mode (884855779449390540) -->
+ <skip />
+ <!-- no translation found for bluetooth_select_a2dp_codec_channel_mode_dialog_title (4073812880900816325) -->
+ <skip />
+ <!-- no translation found for bluetooth_select_a2dp_codec_ldac_playback_quality (4846872213548295632) -->
+ <skip />
+ <!-- no translation found for bluetooth_select_a2dp_codec_ldac_playback_quality_dialog_title (3940973633342423717) -->
+ <skip />
<string name="wifi_display_certification_summary" msgid="1155182309166746973">"Vezeték nélküli kijelző tanúsítványával kapcsolatos lehetőségek megjelenítése"</string>
<string name="wifi_verbose_logging_summary" msgid="6615071616111731958">"Wi‑Fi-naplózási szint növelése, RSSI/SSID megjelenítése a Wi‑Fi-választóban"</string>
<string name="wifi_aggressive_handover_summary" msgid="6328455667642570371">"Ha engedélyezi, a Wi-Fi agresszívebben fogja átadni az adatkapcsolatot a mobilhálózatnak gyenge Wi-Fi-jel esetén"</string>
diff --git a/packages/SettingsLib/res/values-hy-rAM/arrays.xml b/packages/SettingsLib/res/values-hy-rAM/arrays.xml
index 1241bee..f696e91 100644
--- a/packages/SettingsLib/res/values-hy-rAM/arrays.xml
+++ b/packages/SettingsLib/res/values-hy-rAM/arrays.xml
@@ -58,6 +58,46 @@
<item msgid="3878793616631049349">"Օգտագործել HDCP-ը` միայն DRM-ի բովանդակությունը ստուգելու համար"</item>
<item msgid="45075631231212732">"Միշտ օգտագործել HDCP ստուգումը"</item>
</string-array>
+ <!-- no translation found for bluetooth_a2dp_codec_titles:0 (1852387125374225729) -->
+ <!-- no translation found for bluetooth_a2dp_codec_titles:1 (7539690996561263909) -->
+ <!-- no translation found for bluetooth_a2dp_codec_titles:2 (4260844283202960798) -->
+ <!-- no translation found for bluetooth_a2dp_codec_titles:3 (7279983368484312990) -->
+ <!-- no translation found for bluetooth_a2dp_codec_titles:4 (2301339338870319651) -->
+ <!-- no translation found for bluetooth_a2dp_codec_summaries:0 (9072025520360316957) -->
+ <!-- no translation found for bluetooth_a2dp_codec_summaries:1 (6898329690939802290) -->
+ <!-- no translation found for bluetooth_a2dp_codec_summaries:2 (1190434429082395888) -->
+ <!-- no translation found for bluetooth_a2dp_codec_summaries:3 (649699003004233053) -->
+ <!-- no translation found for bluetooth_a2dp_codec_summaries:4 (508106435710925399) -->
+ <!-- no translation found for bluetooth_a2dp_codec_sample_rate_titles:0 (7102940318360468759) -->
+ <!-- no translation found for bluetooth_a2dp_codec_sample_rate_titles:1 (8895532488906185219) -->
+ <!-- no translation found for bluetooth_a2dp_codec_sample_rate_titles:2 (2909915718994807056) -->
+ <!-- no translation found for bluetooth_a2dp_codec_sample_rate_titles:3 (3347287377354164611) -->
+ <!-- no translation found for bluetooth_a2dp_codec_sample_rate_titles:4 (1234212100239985373) -->
+ <!-- no translation found for bluetooth_a2dp_codec_sample_rate_summaries:0 (7224433008148687313) -->
+ <!-- no translation found for bluetooth_a2dp_codec_sample_rate_summaries:1 (4482862757811638365) -->
+ <!-- no translation found for bluetooth_a2dp_codec_sample_rate_summaries:2 (354495328188724404) -->
+ <!-- no translation found for bluetooth_a2dp_codec_sample_rate_summaries:3 (7329816882213695083) -->
+ <!-- no translation found for bluetooth_a2dp_codec_sample_rate_summaries:4 (6967397666254430476) -->
+ <!-- no translation found for bluetooth_a2dp_codec_bits_per_sample_titles:0 (6694044160540313386) -->
+ <!-- no translation found for bluetooth_a2dp_codec_bits_per_sample_titles:1 (5618929009984956469) -->
+ <!-- no translation found for bluetooth_a2dp_codec_bits_per_sample_titles:2 (3412640499234627248) -->
+ <!-- no translation found for bluetooth_a2dp_codec_bits_per_sample_titles:3 (121583001492929387) -->
+ <!-- no translation found for bluetooth_a2dp_codec_bits_per_sample_summaries:0 (5091076677792306320) -->
+ <!-- no translation found for bluetooth_a2dp_codec_bits_per_sample_summaries:1 (4726688794884191540) -->
+ <!-- no translation found for bluetooth_a2dp_codec_bits_per_sample_summaries:2 (305344756485516870) -->
+ <!-- no translation found for bluetooth_a2dp_codec_bits_per_sample_summaries:3 (244568657919675099) -->
+ <!-- no translation found for bluetooth_a2dp_codec_channel_mode_titles:0 (13423709606339855) -->
+ <!-- no translation found for bluetooth_a2dp_codec_channel_mode_titles:1 (4106832974775067314) -->
+ <!-- no translation found for bluetooth_a2dp_codec_channel_mode_titles:2 (5571632958424639155) -->
+ <!-- no translation found for bluetooth_a2dp_codec_channel_mode_summaries:0 (8128478683963250130) -->
+ <!-- no translation found for bluetooth_a2dp_codec_channel_mode_summaries:1 (8900559293912978337) -->
+ <!-- no translation found for bluetooth_a2dp_codec_channel_mode_summaries:2 (8883739882299884241) -->
+ <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_titles:0 (2944889121850394020) -->
+ <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_titles:1 (138837449700903545) -->
+ <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_titles:2 (4777177307869441982) -->
+ <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_summaries:0 (172302906231378902) -->
+ <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_summaries:1 (9091111147684472529) -->
+ <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_summaries:2 (3367904477834831032) -->
<string-array name="select_logd_size_titles">
<item msgid="8665206199209698501">"Անջատված է"</item>
<item msgid="1593289376502312923">"64ԿԲ"</item>
diff --git a/packages/SettingsLib/res/values-hy-rAM/strings.xml b/packages/SettingsLib/res/values-hy-rAM/strings.xml
index 817bb60..f7b5965 100644
--- a/packages/SettingsLib/res/values-hy-rAM/strings.xml
+++ b/packages/SettingsLib/res/values-hy-rAM/strings.xml
@@ -170,7 +170,27 @@
<string name="wifi_allow_scan_with_traffic" msgid="3601853081178265786">"Միշտ թույլատրել Wi‑Fi ռոումինգի որոնումը"</string>
<string name="mobile_data_always_on" msgid="7745605759775320362">"Բջջային տվյալները՝ միշտ ակտիվացրած"</string>
<string name="bluetooth_disable_absolute_volume" msgid="2660673801947898809">"Անջատել ձայնի բացարձակ ուժգնությունը"</string>
- <string name="wifi_display_certification_summary" msgid="1155182309166746973">"Ցույց տալ անլար էկրանի վկայագրման ընտրանքները"</string>
+ <!-- no translation found for bluetooth_select_a2dp_codec_type (90597356942154882) -->
+ <skip />
+ <!-- no translation found for bluetooth_select_a2dp_codec_type_dialog_title (6470824182074383881) -->
+ <skip />
+ <!-- no translation found for bluetooth_select_a2dp_codec_sample_rate (4788245703824623062) -->
+ <skip />
+ <!-- no translation found for bluetooth_select_a2dp_codec_sample_rate_dialog_title (4263851572248033749) -->
+ <skip />
+ <!-- no translation found for bluetooth_select_a2dp_codec_bits_per_sample (2099645202720164141) -->
+ <skip />
+ <!-- no translation found for bluetooth_select_a2dp_codec_bits_per_sample_dialog_title (2096170505745650345) -->
+ <skip />
+ <!-- no translation found for bluetooth_select_a2dp_codec_channel_mode (884855779449390540) -->
+ <skip />
+ <!-- no translation found for bluetooth_select_a2dp_codec_channel_mode_dialog_title (4073812880900816325) -->
+ <skip />
+ <!-- no translation found for bluetooth_select_a2dp_codec_ldac_playback_quality (4846872213548295632) -->
+ <skip />
+ <!-- no translation found for bluetooth_select_a2dp_codec_ldac_playback_quality_dialog_title (3940973633342423717) -->
+ <skip />
+ <string name="wifi_display_certification_summary" msgid="1155182309166746973">"Ցույց տալ անլար էկրանի հավաստագրման ընտրանքները"</string>
<string name="wifi_verbose_logging_summary" msgid="6615071616111731958">"Բարձրացնել մակարդակը, Wi‑Fi ընտրիչում ամեն մի SSID-ի համար ցույց տալ RSSI"</string>
<string name="wifi_aggressive_handover_summary" msgid="6328455667642570371">"Եթե այս գործառույթը միացված է, Wi‑Fi-ի թույլ ազդանշանի դեպքում Wi‑Fi ինտերնետից անցումը բջջային ինտերնետին ավելի կտրուկ կլինի"</string>
<string name="wifi_allow_scan_with_traffic_summary" msgid="2575101424972686310">"Թույլատրել/արգելել Wi‑Fi ռոումինգի որոնումը՝ կախված միջերեսում տվյալների երթևեկի ծավալից"</string>
diff --git a/packages/SettingsLib/res/values-in/arrays.xml b/packages/SettingsLib/res/values-in/arrays.xml
index 63bd8f3..dc6f7b80 100644
--- a/packages/SettingsLib/res/values-in/arrays.xml
+++ b/packages/SettingsLib/res/values-in/arrays.xml
@@ -58,6 +58,46 @@
<item msgid="3878793616631049349">"Gunakan pemeriksaan HDCP untuk konten DRM saja"</item>
<item msgid="45075631231212732">"Selalu gunakan pemeriksaan HDCP"</item>
</string-array>
+ <!-- no translation found for bluetooth_a2dp_codec_titles:0 (1852387125374225729) -->
+ <!-- no translation found for bluetooth_a2dp_codec_titles:1 (7539690996561263909) -->
+ <!-- no translation found for bluetooth_a2dp_codec_titles:2 (4260844283202960798) -->
+ <!-- no translation found for bluetooth_a2dp_codec_titles:3 (7279983368484312990) -->
+ <!-- no translation found for bluetooth_a2dp_codec_titles:4 (2301339338870319651) -->
+ <!-- no translation found for bluetooth_a2dp_codec_summaries:0 (9072025520360316957) -->
+ <!-- no translation found for bluetooth_a2dp_codec_summaries:1 (6898329690939802290) -->
+ <!-- no translation found for bluetooth_a2dp_codec_summaries:2 (1190434429082395888) -->
+ <!-- no translation found for bluetooth_a2dp_codec_summaries:3 (649699003004233053) -->
+ <!-- no translation found for bluetooth_a2dp_codec_summaries:4 (508106435710925399) -->
+ <!-- no translation found for bluetooth_a2dp_codec_sample_rate_titles:0 (7102940318360468759) -->
+ <!-- no translation found for bluetooth_a2dp_codec_sample_rate_titles:1 (8895532488906185219) -->
+ <!-- no translation found for bluetooth_a2dp_codec_sample_rate_titles:2 (2909915718994807056) -->
+ <!-- no translation found for bluetooth_a2dp_codec_sample_rate_titles:3 (3347287377354164611) -->
+ <!-- no translation found for bluetooth_a2dp_codec_sample_rate_titles:4 (1234212100239985373) -->
+ <!-- no translation found for bluetooth_a2dp_codec_sample_rate_summaries:0 (7224433008148687313) -->
+ <!-- no translation found for bluetooth_a2dp_codec_sample_rate_summaries:1 (4482862757811638365) -->
+ <!-- no translation found for bluetooth_a2dp_codec_sample_rate_summaries:2 (354495328188724404) -->
+ <!-- no translation found for bluetooth_a2dp_codec_sample_rate_summaries:3 (7329816882213695083) -->
+ <!-- no translation found for bluetooth_a2dp_codec_sample_rate_summaries:4 (6967397666254430476) -->
+ <!-- no translation found for bluetooth_a2dp_codec_bits_per_sample_titles:0 (6694044160540313386) -->
+ <!-- no translation found for bluetooth_a2dp_codec_bits_per_sample_titles:1 (5618929009984956469) -->
+ <!-- no translation found for bluetooth_a2dp_codec_bits_per_sample_titles:2 (3412640499234627248) -->
+ <!-- no translation found for bluetooth_a2dp_codec_bits_per_sample_titles:3 (121583001492929387) -->
+ <!-- no translation found for bluetooth_a2dp_codec_bits_per_sample_summaries:0 (5091076677792306320) -->
+ <!-- no translation found for bluetooth_a2dp_codec_bits_per_sample_summaries:1 (4726688794884191540) -->
+ <!-- no translation found for bluetooth_a2dp_codec_bits_per_sample_summaries:2 (305344756485516870) -->
+ <!-- no translation found for bluetooth_a2dp_codec_bits_per_sample_summaries:3 (244568657919675099) -->
+ <!-- no translation found for bluetooth_a2dp_codec_channel_mode_titles:0 (13423709606339855) -->
+ <!-- no translation found for bluetooth_a2dp_codec_channel_mode_titles:1 (4106832974775067314) -->
+ <!-- no translation found for bluetooth_a2dp_codec_channel_mode_titles:2 (5571632958424639155) -->
+ <!-- no translation found for bluetooth_a2dp_codec_channel_mode_summaries:0 (8128478683963250130) -->
+ <!-- no translation found for bluetooth_a2dp_codec_channel_mode_summaries:1 (8900559293912978337) -->
+ <!-- no translation found for bluetooth_a2dp_codec_channel_mode_summaries:2 (8883739882299884241) -->
+ <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_titles:0 (2944889121850394020) -->
+ <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_titles:1 (138837449700903545) -->
+ <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_titles:2 (4777177307869441982) -->
+ <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_summaries:0 (172302906231378902) -->
+ <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_summaries:1 (9091111147684472529) -->
+ <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_summaries:2 (3367904477834831032) -->
<string-array name="select_logd_size_titles">
<item msgid="8665206199209698501">"Nonaktif"</item>
<item msgid="1593289376502312923">"64 K"</item>
diff --git a/packages/SettingsLib/res/values-in/strings.xml b/packages/SettingsLib/res/values-in/strings.xml
index 9559887..82052194 100644
--- a/packages/SettingsLib/res/values-in/strings.xml
+++ b/packages/SettingsLib/res/values-in/strings.xml
@@ -170,6 +170,26 @@
<string name="wifi_allow_scan_with_traffic" msgid="3601853081178265786">"Selalu izinkan Pemindaian Roaming Wi-Fi"</string>
<string name="mobile_data_always_on" msgid="7745605759775320362">"Data seluler selalu aktif"</string>
<string name="bluetooth_disable_absolute_volume" msgid="2660673801947898809">"Nonaktifkan volume absolut"</string>
+ <!-- no translation found for bluetooth_select_a2dp_codec_type (90597356942154882) -->
+ <skip />
+ <!-- no translation found for bluetooth_select_a2dp_codec_type_dialog_title (6470824182074383881) -->
+ <skip />
+ <!-- no translation found for bluetooth_select_a2dp_codec_sample_rate (4788245703824623062) -->
+ <skip />
+ <!-- no translation found for bluetooth_select_a2dp_codec_sample_rate_dialog_title (4263851572248033749) -->
+ <skip />
+ <!-- no translation found for bluetooth_select_a2dp_codec_bits_per_sample (2099645202720164141) -->
+ <skip />
+ <!-- no translation found for bluetooth_select_a2dp_codec_bits_per_sample_dialog_title (2096170505745650345) -->
+ <skip />
+ <!-- no translation found for bluetooth_select_a2dp_codec_channel_mode (884855779449390540) -->
+ <skip />
+ <!-- no translation found for bluetooth_select_a2dp_codec_channel_mode_dialog_title (4073812880900816325) -->
+ <skip />
+ <!-- no translation found for bluetooth_select_a2dp_codec_ldac_playback_quality (4846872213548295632) -->
+ <skip />
+ <!-- no translation found for bluetooth_select_a2dp_codec_ldac_playback_quality_dialog_title (3940973633342423717) -->
+ <skip />
<string name="wifi_display_certification_summary" msgid="1155182309166746973">"Tampilkan opsi untuk sertifikasi layar nirkabel"</string>
<string name="wifi_verbose_logging_summary" msgid="6615071616111731958">"Tingkatkan level pencatatan log Wi-Fi, tampilkan per SSID RSSI di Pemilih Wi‑Fi"</string>
<string name="wifi_aggressive_handover_summary" msgid="6328455667642570371">"Jika diaktifkan, Wi-Fi akan menjadi lebih agresif dalam mengalihkan sambungan data ke Seluler saat sinyal Wi-Fi lemah"</string>
diff --git a/packages/SettingsLib/res/values-is-rIS/arrays.xml b/packages/SettingsLib/res/values-is-rIS/arrays.xml
index 6c0a3cd..091c4ed 100644
--- a/packages/SettingsLib/res/values-is-rIS/arrays.xml
+++ b/packages/SettingsLib/res/values-is-rIS/arrays.xml
@@ -58,6 +58,46 @@
<item msgid="3878793616631049349">"Nota HDCP-athugun aðeins fyrir höfundarréttarvarið efni"</item>
<item msgid="45075631231212732">"Nota alltaf HDCP-eftirlit"</item>
</string-array>
+ <!-- no translation found for bluetooth_a2dp_codec_titles:0 (1852387125374225729) -->
+ <!-- no translation found for bluetooth_a2dp_codec_titles:1 (7539690996561263909) -->
+ <!-- no translation found for bluetooth_a2dp_codec_titles:2 (4260844283202960798) -->
+ <!-- no translation found for bluetooth_a2dp_codec_titles:3 (7279983368484312990) -->
+ <!-- no translation found for bluetooth_a2dp_codec_titles:4 (2301339338870319651) -->
+ <!-- no translation found for bluetooth_a2dp_codec_summaries:0 (9072025520360316957) -->
+ <!-- no translation found for bluetooth_a2dp_codec_summaries:1 (6898329690939802290) -->
+ <!-- no translation found for bluetooth_a2dp_codec_summaries:2 (1190434429082395888) -->
+ <!-- no translation found for bluetooth_a2dp_codec_summaries:3 (649699003004233053) -->
+ <!-- no translation found for bluetooth_a2dp_codec_summaries:4 (508106435710925399) -->
+ <!-- no translation found for bluetooth_a2dp_codec_sample_rate_titles:0 (7102940318360468759) -->
+ <!-- no translation found for bluetooth_a2dp_codec_sample_rate_titles:1 (8895532488906185219) -->
+ <!-- no translation found for bluetooth_a2dp_codec_sample_rate_titles:2 (2909915718994807056) -->
+ <!-- no translation found for bluetooth_a2dp_codec_sample_rate_titles:3 (3347287377354164611) -->
+ <!-- no translation found for bluetooth_a2dp_codec_sample_rate_titles:4 (1234212100239985373) -->
+ <!-- no translation found for bluetooth_a2dp_codec_sample_rate_summaries:0 (7224433008148687313) -->
+ <!-- no translation found for bluetooth_a2dp_codec_sample_rate_summaries:1 (4482862757811638365) -->
+ <!-- no translation found for bluetooth_a2dp_codec_sample_rate_summaries:2 (354495328188724404) -->
+ <!-- no translation found for bluetooth_a2dp_codec_sample_rate_summaries:3 (7329816882213695083) -->
+ <!-- no translation found for bluetooth_a2dp_codec_sample_rate_summaries:4 (6967397666254430476) -->
+ <!-- no translation found for bluetooth_a2dp_codec_bits_per_sample_titles:0 (6694044160540313386) -->
+ <!-- no translation found for bluetooth_a2dp_codec_bits_per_sample_titles:1 (5618929009984956469) -->
+ <!-- no translation found for bluetooth_a2dp_codec_bits_per_sample_titles:2 (3412640499234627248) -->
+ <!-- no translation found for bluetooth_a2dp_codec_bits_per_sample_titles:3 (121583001492929387) -->
+ <!-- no translation found for bluetooth_a2dp_codec_bits_per_sample_summaries:0 (5091076677792306320) -->
+ <!-- no translation found for bluetooth_a2dp_codec_bits_per_sample_summaries:1 (4726688794884191540) -->
+ <!-- no translation found for bluetooth_a2dp_codec_bits_per_sample_summaries:2 (305344756485516870) -->
+ <!-- no translation found for bluetooth_a2dp_codec_bits_per_sample_summaries:3 (244568657919675099) -->
+ <!-- no translation found for bluetooth_a2dp_codec_channel_mode_titles:0 (13423709606339855) -->
+ <!-- no translation found for bluetooth_a2dp_codec_channel_mode_titles:1 (4106832974775067314) -->
+ <!-- no translation found for bluetooth_a2dp_codec_channel_mode_titles:2 (5571632958424639155) -->
+ <!-- no translation found for bluetooth_a2dp_codec_channel_mode_summaries:0 (8128478683963250130) -->
+ <!-- no translation found for bluetooth_a2dp_codec_channel_mode_summaries:1 (8900559293912978337) -->
+ <!-- no translation found for bluetooth_a2dp_codec_channel_mode_summaries:2 (8883739882299884241) -->
+ <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_titles:0 (2944889121850394020) -->
+ <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_titles:1 (138837449700903545) -->
+ <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_titles:2 (4777177307869441982) -->
+ <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_summaries:0 (172302906231378902) -->
+ <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_summaries:1 (9091111147684472529) -->
+ <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_summaries:2 (3367904477834831032) -->
<string-array name="select_logd_size_titles">
<item msgid="8665206199209698501">"Slökkt"</item>
<item msgid="1593289376502312923">"64 k"</item>
diff --git a/packages/SettingsLib/res/values-is-rIS/strings.xml b/packages/SettingsLib/res/values-is-rIS/strings.xml
index 8be8444..2f0d3a9 100644
--- a/packages/SettingsLib/res/values-is-rIS/strings.xml
+++ b/packages/SettingsLib/res/values-is-rIS/strings.xml
@@ -170,6 +170,26 @@
<string name="wifi_allow_scan_with_traffic" msgid="3601853081178265786">"Leyfa alltaf reikileit með Wi-Fi"</string>
<string name="mobile_data_always_on" msgid="7745605759775320362">"Alltaf kveikt á farsímagögnum"</string>
<string name="bluetooth_disable_absolute_volume" msgid="2660673801947898809">"Slökkva á samstillingu hljóðstyrks"</string>
+ <!-- no translation found for bluetooth_select_a2dp_codec_type (90597356942154882) -->
+ <skip />
+ <!-- no translation found for bluetooth_select_a2dp_codec_type_dialog_title (6470824182074383881) -->
+ <skip />
+ <!-- no translation found for bluetooth_select_a2dp_codec_sample_rate (4788245703824623062) -->
+ <skip />
+ <!-- no translation found for bluetooth_select_a2dp_codec_sample_rate_dialog_title (4263851572248033749) -->
+ <skip />
+ <!-- no translation found for bluetooth_select_a2dp_codec_bits_per_sample (2099645202720164141) -->
+ <skip />
+ <!-- no translation found for bluetooth_select_a2dp_codec_bits_per_sample_dialog_title (2096170505745650345) -->
+ <skip />
+ <!-- no translation found for bluetooth_select_a2dp_codec_channel_mode (884855779449390540) -->
+ <skip />
+ <!-- no translation found for bluetooth_select_a2dp_codec_channel_mode_dialog_title (4073812880900816325) -->
+ <skip />
+ <!-- no translation found for bluetooth_select_a2dp_codec_ldac_playback_quality (4846872213548295632) -->
+ <skip />
+ <!-- no translation found for bluetooth_select_a2dp_codec_ldac_playback_quality_dialog_title (3940973633342423717) -->
+ <skip />
<string name="wifi_display_certification_summary" msgid="1155182309166746973">"Sýna valkosti fyrir vottun þráðlausra skjáa"</string>
<string name="wifi_verbose_logging_summary" msgid="6615071616111731958">"Auka skráningarstig Wi-Fi, sýna RSSI fyrir hvert SSID í Wi-Fi vali"</string>
<string name="wifi_aggressive_handover_summary" msgid="6328455667642570371">"Þegar þetta er virkt mun Wi-Fi ganga harðar fram í að færa gagnatenginguna yfir til símkerfisins þegar Wi-Fi merkið er lélegt"</string>
diff --git a/packages/SettingsLib/res/values-it/arrays.xml b/packages/SettingsLib/res/values-it/arrays.xml
index 518afed..5aaf989 100644
--- a/packages/SettingsLib/res/values-it/arrays.xml
+++ b/packages/SettingsLib/res/values-it/arrays.xml
@@ -58,6 +58,46 @@
<item msgid="3878793616631049349">"Usa la verifica HDCP solo per contenuti DRM"</item>
<item msgid="45075631231212732">"Usa sempre la verifica HDCP"</item>
</string-array>
+ <!-- no translation found for bluetooth_a2dp_codec_titles:0 (1852387125374225729) -->
+ <!-- no translation found for bluetooth_a2dp_codec_titles:1 (7539690996561263909) -->
+ <!-- no translation found for bluetooth_a2dp_codec_titles:2 (4260844283202960798) -->
+ <!-- no translation found for bluetooth_a2dp_codec_titles:3 (7279983368484312990) -->
+ <!-- no translation found for bluetooth_a2dp_codec_titles:4 (2301339338870319651) -->
+ <!-- no translation found for bluetooth_a2dp_codec_summaries:0 (9072025520360316957) -->
+ <!-- no translation found for bluetooth_a2dp_codec_summaries:1 (6898329690939802290) -->
+ <!-- no translation found for bluetooth_a2dp_codec_summaries:2 (1190434429082395888) -->
+ <!-- no translation found for bluetooth_a2dp_codec_summaries:3 (649699003004233053) -->
+ <!-- no translation found for bluetooth_a2dp_codec_summaries:4 (508106435710925399) -->
+ <!-- no translation found for bluetooth_a2dp_codec_sample_rate_titles:0 (7102940318360468759) -->
+ <!-- no translation found for bluetooth_a2dp_codec_sample_rate_titles:1 (8895532488906185219) -->
+ <!-- no translation found for bluetooth_a2dp_codec_sample_rate_titles:2 (2909915718994807056) -->
+ <!-- no translation found for bluetooth_a2dp_codec_sample_rate_titles:3 (3347287377354164611) -->
+ <!-- no translation found for bluetooth_a2dp_codec_sample_rate_titles:4 (1234212100239985373) -->
+ <!-- no translation found for bluetooth_a2dp_codec_sample_rate_summaries:0 (7224433008148687313) -->
+ <!-- no translation found for bluetooth_a2dp_codec_sample_rate_summaries:1 (4482862757811638365) -->
+ <!-- no translation found for bluetooth_a2dp_codec_sample_rate_summaries:2 (354495328188724404) -->
+ <!-- no translation found for bluetooth_a2dp_codec_sample_rate_summaries:3 (7329816882213695083) -->
+ <!-- no translation found for bluetooth_a2dp_codec_sample_rate_summaries:4 (6967397666254430476) -->
+ <!-- no translation found for bluetooth_a2dp_codec_bits_per_sample_titles:0 (6694044160540313386) -->
+ <!-- no translation found for bluetooth_a2dp_codec_bits_per_sample_titles:1 (5618929009984956469) -->
+ <!-- no translation found for bluetooth_a2dp_codec_bits_per_sample_titles:2 (3412640499234627248) -->
+ <!-- no translation found for bluetooth_a2dp_codec_bits_per_sample_titles:3 (121583001492929387) -->
+ <!-- no translation found for bluetooth_a2dp_codec_bits_per_sample_summaries:0 (5091076677792306320) -->
+ <!-- no translation found for bluetooth_a2dp_codec_bits_per_sample_summaries:1 (4726688794884191540) -->
+ <!-- no translation found for bluetooth_a2dp_codec_bits_per_sample_summaries:2 (305344756485516870) -->
+ <!-- no translation found for bluetooth_a2dp_codec_bits_per_sample_summaries:3 (244568657919675099) -->
+ <!-- no translation found for bluetooth_a2dp_codec_channel_mode_titles:0 (13423709606339855) -->
+ <!-- no translation found for bluetooth_a2dp_codec_channel_mode_titles:1 (4106832974775067314) -->
+ <!-- no translation found for bluetooth_a2dp_codec_channel_mode_titles:2 (5571632958424639155) -->
+ <!-- no translation found for bluetooth_a2dp_codec_channel_mode_summaries:0 (8128478683963250130) -->
+ <!-- no translation found for bluetooth_a2dp_codec_channel_mode_summaries:1 (8900559293912978337) -->
+ <!-- no translation found for bluetooth_a2dp_codec_channel_mode_summaries:2 (8883739882299884241) -->
+ <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_titles:0 (2944889121850394020) -->
+ <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_titles:1 (138837449700903545) -->
+ <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_titles:2 (4777177307869441982) -->
+ <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_summaries:0 (172302906231378902) -->
+ <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_summaries:1 (9091111147684472529) -->
+ <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_summaries:2 (3367904477834831032) -->
<string-array name="select_logd_size_titles">
<item msgid="8665206199209698501">"Off"</item>
<item msgid="1593289376502312923">"64 kB"</item>
diff --git a/packages/SettingsLib/res/values-it/strings.xml b/packages/SettingsLib/res/values-it/strings.xml
index 74ee5a1..b06eaf5 100644
--- a/packages/SettingsLib/res/values-it/strings.xml
+++ b/packages/SettingsLib/res/values-it/strings.xml
@@ -170,6 +170,26 @@
<string name="wifi_allow_scan_with_traffic" msgid="3601853081178265786">"Consenti sempre scansioni roaming Wi-Fi"</string>
<string name="mobile_data_always_on" msgid="7745605759775320362">"Dati cellulare sempre attivi"</string>
<string name="bluetooth_disable_absolute_volume" msgid="2660673801947898809">"Disattiva volume assoluto"</string>
+ <!-- no translation found for bluetooth_select_a2dp_codec_type (90597356942154882) -->
+ <skip />
+ <!-- no translation found for bluetooth_select_a2dp_codec_type_dialog_title (6470824182074383881) -->
+ <skip />
+ <!-- no translation found for bluetooth_select_a2dp_codec_sample_rate (4788245703824623062) -->
+ <skip />
+ <!-- no translation found for bluetooth_select_a2dp_codec_sample_rate_dialog_title (4263851572248033749) -->
+ <skip />
+ <!-- no translation found for bluetooth_select_a2dp_codec_bits_per_sample (2099645202720164141) -->
+ <skip />
+ <!-- no translation found for bluetooth_select_a2dp_codec_bits_per_sample_dialog_title (2096170505745650345) -->
+ <skip />
+ <!-- no translation found for bluetooth_select_a2dp_codec_channel_mode (884855779449390540) -->
+ <skip />
+ <!-- no translation found for bluetooth_select_a2dp_codec_channel_mode_dialog_title (4073812880900816325) -->
+ <skip />
+ <!-- no translation found for bluetooth_select_a2dp_codec_ldac_playback_quality (4846872213548295632) -->
+ <skip />
+ <!-- no translation found for bluetooth_select_a2dp_codec_ldac_playback_quality_dialog_title (3940973633342423717) -->
+ <skip />
<string name="wifi_display_certification_summary" msgid="1155182309166746973">"Mostra opzioni per la certificazione display wireless"</string>
<string name="wifi_verbose_logging_summary" msgid="6615071616111731958">"Aumenta il livello di registrazione Wi-Fi, mostrando il SSID RSSI nel selettore Wi-Fi"</string>
<string name="wifi_aggressive_handover_summary" msgid="6328455667642570371">"Quando questa impostazione è attivata, il Wi-Fi sarà più aggressivo nel passare la connessione dati al cellulare, quando il segnale Wi-Fi è basso"</string>
diff --git a/packages/SettingsLib/res/values-iw/arrays.xml b/packages/SettingsLib/res/values-iw/arrays.xml
index b3aee1d..8e25a87 100644
--- a/packages/SettingsLib/res/values-iw/arrays.xml
+++ b/packages/SettingsLib/res/values-iw/arrays.xml
@@ -58,6 +58,46 @@
<item msgid="3878793616631049349">"השתמש בבדיקת HDCP עבור תוכן DRM בלבד"</item>
<item msgid="45075631231212732">"תמיד השתמש בבדיקת HDCP"</item>
</string-array>
+ <!-- no translation found for bluetooth_a2dp_codec_titles:0 (1852387125374225729) -->
+ <!-- no translation found for bluetooth_a2dp_codec_titles:1 (7539690996561263909) -->
+ <!-- no translation found for bluetooth_a2dp_codec_titles:2 (4260844283202960798) -->
+ <!-- no translation found for bluetooth_a2dp_codec_titles:3 (7279983368484312990) -->
+ <!-- no translation found for bluetooth_a2dp_codec_titles:4 (2301339338870319651) -->
+ <!-- no translation found for bluetooth_a2dp_codec_summaries:0 (9072025520360316957) -->
+ <!-- no translation found for bluetooth_a2dp_codec_summaries:1 (6898329690939802290) -->
+ <!-- no translation found for bluetooth_a2dp_codec_summaries:2 (1190434429082395888) -->
+ <!-- no translation found for bluetooth_a2dp_codec_summaries:3 (649699003004233053) -->
+ <!-- no translation found for bluetooth_a2dp_codec_summaries:4 (508106435710925399) -->
+ <!-- no translation found for bluetooth_a2dp_codec_sample_rate_titles:0 (7102940318360468759) -->
+ <!-- no translation found for bluetooth_a2dp_codec_sample_rate_titles:1 (8895532488906185219) -->
+ <!-- no translation found for bluetooth_a2dp_codec_sample_rate_titles:2 (2909915718994807056) -->
+ <!-- no translation found for bluetooth_a2dp_codec_sample_rate_titles:3 (3347287377354164611) -->
+ <!-- no translation found for bluetooth_a2dp_codec_sample_rate_titles:4 (1234212100239985373) -->
+ <!-- no translation found for bluetooth_a2dp_codec_sample_rate_summaries:0 (7224433008148687313) -->
+ <!-- no translation found for bluetooth_a2dp_codec_sample_rate_summaries:1 (4482862757811638365) -->
+ <!-- no translation found for bluetooth_a2dp_codec_sample_rate_summaries:2 (354495328188724404) -->
+ <!-- no translation found for bluetooth_a2dp_codec_sample_rate_summaries:3 (7329816882213695083) -->
+ <!-- no translation found for bluetooth_a2dp_codec_sample_rate_summaries:4 (6967397666254430476) -->
+ <!-- no translation found for bluetooth_a2dp_codec_bits_per_sample_titles:0 (6694044160540313386) -->
+ <!-- no translation found for bluetooth_a2dp_codec_bits_per_sample_titles:1 (5618929009984956469) -->
+ <!-- no translation found for bluetooth_a2dp_codec_bits_per_sample_titles:2 (3412640499234627248) -->
+ <!-- no translation found for bluetooth_a2dp_codec_bits_per_sample_titles:3 (121583001492929387) -->
+ <!-- no translation found for bluetooth_a2dp_codec_bits_per_sample_summaries:0 (5091076677792306320) -->
+ <!-- no translation found for bluetooth_a2dp_codec_bits_per_sample_summaries:1 (4726688794884191540) -->
+ <!-- no translation found for bluetooth_a2dp_codec_bits_per_sample_summaries:2 (305344756485516870) -->
+ <!-- no translation found for bluetooth_a2dp_codec_bits_per_sample_summaries:3 (244568657919675099) -->
+ <!-- no translation found for bluetooth_a2dp_codec_channel_mode_titles:0 (13423709606339855) -->
+ <!-- no translation found for bluetooth_a2dp_codec_channel_mode_titles:1 (4106832974775067314) -->
+ <!-- no translation found for bluetooth_a2dp_codec_channel_mode_titles:2 (5571632958424639155) -->
+ <!-- no translation found for bluetooth_a2dp_codec_channel_mode_summaries:0 (8128478683963250130) -->
+ <!-- no translation found for bluetooth_a2dp_codec_channel_mode_summaries:1 (8900559293912978337) -->
+ <!-- no translation found for bluetooth_a2dp_codec_channel_mode_summaries:2 (8883739882299884241) -->
+ <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_titles:0 (2944889121850394020) -->
+ <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_titles:1 (138837449700903545) -->
+ <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_titles:2 (4777177307869441982) -->
+ <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_summaries:0 (172302906231378902) -->
+ <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_summaries:1 (9091111147684472529) -->
+ <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_summaries:2 (3367904477834831032) -->
<string-array name="select_logd_size_titles">
<item msgid="8665206199209698501">"כבוי"</item>
<item msgid="1593289376502312923">"64K"</item>
diff --git a/packages/SettingsLib/res/values-iw/strings.xml b/packages/SettingsLib/res/values-iw/strings.xml
index aa3dc13..a0c7f7c 100644
--- a/packages/SettingsLib/res/values-iw/strings.xml
+++ b/packages/SettingsLib/res/values-iw/strings.xml
@@ -170,6 +170,26 @@
<string name="wifi_allow_scan_with_traffic" msgid="3601853081178265786">"התר תמיד סריקות נדידה של Wi‑Fi"</string>
<string name="mobile_data_always_on" msgid="7745605759775320362">"נתונים סלולריים פעילים תמיד"</string>
<string name="bluetooth_disable_absolute_volume" msgid="2660673801947898809">"השבת עוצמת קול מוחלטת"</string>
+ <!-- no translation found for bluetooth_select_a2dp_codec_type (90597356942154882) -->
+ <skip />
+ <!-- no translation found for bluetooth_select_a2dp_codec_type_dialog_title (6470824182074383881) -->
+ <skip />
+ <!-- no translation found for bluetooth_select_a2dp_codec_sample_rate (4788245703824623062) -->
+ <skip />
+ <!-- no translation found for bluetooth_select_a2dp_codec_sample_rate_dialog_title (4263851572248033749) -->
+ <skip />
+ <!-- no translation found for bluetooth_select_a2dp_codec_bits_per_sample (2099645202720164141) -->
+ <skip />
+ <!-- no translation found for bluetooth_select_a2dp_codec_bits_per_sample_dialog_title (2096170505745650345) -->
+ <skip />
+ <!-- no translation found for bluetooth_select_a2dp_codec_channel_mode (884855779449390540) -->
+ <skip />
+ <!-- no translation found for bluetooth_select_a2dp_codec_channel_mode_dialog_title (4073812880900816325) -->
+ <skip />
+ <!-- no translation found for bluetooth_select_a2dp_codec_ldac_playback_quality (4846872213548295632) -->
+ <skip />
+ <!-- no translation found for bluetooth_select_a2dp_codec_ldac_playback_quality_dialog_title (3940973633342423717) -->
+ <skip />
<string name="wifi_display_certification_summary" msgid="1155182309166746973">"הצג אפשרויות עבור אישור של תצוגת WiFi"</string>
<string name="wifi_verbose_logging_summary" msgid="6615071616111731958">"העלה את רמת הרישום של Wi‑Fi ביומן, הצג לכל SSID RSSI ב-Wi‑Fi Picker"</string>
<string name="wifi_aggressive_handover_summary" msgid="6328455667642570371">"כשתכונה זו מופעלת, Wi-Fi יתנהג בצורה אגרסיבית יותר בעת העברת חיבור הנתונים לרשת הסלולרית כשאות ה-Wi-Fi חלש."</string>
diff --git a/packages/SettingsLib/res/values-ja/arrays.xml b/packages/SettingsLib/res/values-ja/arrays.xml
index 3d7d070..df23819 100644
--- a/packages/SettingsLib/res/values-ja/arrays.xml
+++ b/packages/SettingsLib/res/values-ja/arrays.xml
@@ -58,6 +58,46 @@
<item msgid="3878793616631049349">"DRMコンテンツにのみHDCPチェックを使用する"</item>
<item msgid="45075631231212732">"HDCPチェックを常に使用する"</item>
</string-array>
+ <!-- no translation found for bluetooth_a2dp_codec_titles:0 (1852387125374225729) -->
+ <!-- no translation found for bluetooth_a2dp_codec_titles:1 (7539690996561263909) -->
+ <!-- no translation found for bluetooth_a2dp_codec_titles:2 (4260844283202960798) -->
+ <!-- no translation found for bluetooth_a2dp_codec_titles:3 (7279983368484312990) -->
+ <!-- no translation found for bluetooth_a2dp_codec_titles:4 (2301339338870319651) -->
+ <!-- no translation found for bluetooth_a2dp_codec_summaries:0 (9072025520360316957) -->
+ <!-- no translation found for bluetooth_a2dp_codec_summaries:1 (6898329690939802290) -->
+ <!-- no translation found for bluetooth_a2dp_codec_summaries:2 (1190434429082395888) -->
+ <!-- no translation found for bluetooth_a2dp_codec_summaries:3 (649699003004233053) -->
+ <!-- no translation found for bluetooth_a2dp_codec_summaries:4 (508106435710925399) -->
+ <!-- no translation found for bluetooth_a2dp_codec_sample_rate_titles:0 (7102940318360468759) -->
+ <!-- no translation found for bluetooth_a2dp_codec_sample_rate_titles:1 (8895532488906185219) -->
+ <!-- no translation found for bluetooth_a2dp_codec_sample_rate_titles:2 (2909915718994807056) -->
+ <!-- no translation found for bluetooth_a2dp_codec_sample_rate_titles:3 (3347287377354164611) -->
+ <!-- no translation found for bluetooth_a2dp_codec_sample_rate_titles:4 (1234212100239985373) -->
+ <!-- no translation found for bluetooth_a2dp_codec_sample_rate_summaries:0 (7224433008148687313) -->
+ <!-- no translation found for bluetooth_a2dp_codec_sample_rate_summaries:1 (4482862757811638365) -->
+ <!-- no translation found for bluetooth_a2dp_codec_sample_rate_summaries:2 (354495328188724404) -->
+ <!-- no translation found for bluetooth_a2dp_codec_sample_rate_summaries:3 (7329816882213695083) -->
+ <!-- no translation found for bluetooth_a2dp_codec_sample_rate_summaries:4 (6967397666254430476) -->
+ <!-- no translation found for bluetooth_a2dp_codec_bits_per_sample_titles:0 (6694044160540313386) -->
+ <!-- no translation found for bluetooth_a2dp_codec_bits_per_sample_titles:1 (5618929009984956469) -->
+ <!-- no translation found for bluetooth_a2dp_codec_bits_per_sample_titles:2 (3412640499234627248) -->
+ <!-- no translation found for bluetooth_a2dp_codec_bits_per_sample_titles:3 (121583001492929387) -->
+ <!-- no translation found for bluetooth_a2dp_codec_bits_per_sample_summaries:0 (5091076677792306320) -->
+ <!-- no translation found for bluetooth_a2dp_codec_bits_per_sample_summaries:1 (4726688794884191540) -->
+ <!-- no translation found for bluetooth_a2dp_codec_bits_per_sample_summaries:2 (305344756485516870) -->
+ <!-- no translation found for bluetooth_a2dp_codec_bits_per_sample_summaries:3 (244568657919675099) -->
+ <!-- no translation found for bluetooth_a2dp_codec_channel_mode_titles:0 (13423709606339855) -->
+ <!-- no translation found for bluetooth_a2dp_codec_channel_mode_titles:1 (4106832974775067314) -->
+ <!-- no translation found for bluetooth_a2dp_codec_channel_mode_titles:2 (5571632958424639155) -->
+ <!-- no translation found for bluetooth_a2dp_codec_channel_mode_summaries:0 (8128478683963250130) -->
+ <!-- no translation found for bluetooth_a2dp_codec_channel_mode_summaries:1 (8900559293912978337) -->
+ <!-- no translation found for bluetooth_a2dp_codec_channel_mode_summaries:2 (8883739882299884241) -->
+ <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_titles:0 (2944889121850394020) -->
+ <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_titles:1 (138837449700903545) -->
+ <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_titles:2 (4777177307869441982) -->
+ <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_summaries:0 (172302906231378902) -->
+ <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_summaries:1 (9091111147684472529) -->
+ <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_summaries:2 (3367904477834831032) -->
<string-array name="select_logd_size_titles">
<item msgid="8665206199209698501">"OFF"</item>
<item msgid="1593289376502312923">"64 K"</item>
diff --git a/packages/SettingsLib/res/values-ja/strings.xml b/packages/SettingsLib/res/values-ja/strings.xml
index f760d934..1def9dc 100644
--- a/packages/SettingsLib/res/values-ja/strings.xml
+++ b/packages/SettingsLib/res/values-ja/strings.xml
@@ -170,6 +170,26 @@
<string name="wifi_allow_scan_with_traffic" msgid="3601853081178265786">"Wi‑Fiローミングスキャンを常に許可する"</string>
<string name="mobile_data_always_on" msgid="7745605759775320362">"モバイルデータを常にON"</string>
<string name="bluetooth_disable_absolute_volume" msgid="2660673801947898809">"絶対音量を無効にする"</string>
+ <!-- no translation found for bluetooth_select_a2dp_codec_type (90597356942154882) -->
+ <skip />
+ <!-- no translation found for bluetooth_select_a2dp_codec_type_dialog_title (6470824182074383881) -->
+ <skip />
+ <!-- no translation found for bluetooth_select_a2dp_codec_sample_rate (4788245703824623062) -->
+ <skip />
+ <!-- no translation found for bluetooth_select_a2dp_codec_sample_rate_dialog_title (4263851572248033749) -->
+ <skip />
+ <!-- no translation found for bluetooth_select_a2dp_codec_bits_per_sample (2099645202720164141) -->
+ <skip />
+ <!-- no translation found for bluetooth_select_a2dp_codec_bits_per_sample_dialog_title (2096170505745650345) -->
+ <skip />
+ <!-- no translation found for bluetooth_select_a2dp_codec_channel_mode (884855779449390540) -->
+ <skip />
+ <!-- no translation found for bluetooth_select_a2dp_codec_channel_mode_dialog_title (4073812880900816325) -->
+ <skip />
+ <!-- no translation found for bluetooth_select_a2dp_codec_ldac_playback_quality (4846872213548295632) -->
+ <skip />
+ <!-- no translation found for bluetooth_select_a2dp_codec_ldac_playback_quality_dialog_title (3940973633342423717) -->
+ <skip />
<string name="wifi_display_certification_summary" msgid="1155182309166746973">"ワイヤレスディスプレイ認証のオプションを表示"</string>
<string name="wifi_verbose_logging_summary" msgid="6615071616111731958">"Wi-Fiログレベルを上げて、Wi-Fi選択ツールでSSID RSSIごとに表示します"</string>
<string name="wifi_aggressive_handover_summary" msgid="6328455667642570371">"有効にすると、Wi-Fiの電波強度が弱い場合は強制的にモバイルデータ接続に切り替わるようになります"</string>
diff --git a/packages/SettingsLib/res/values-ka-rGE/arrays.xml b/packages/SettingsLib/res/values-ka-rGE/arrays.xml
index 804e129..df296ba 100644
--- a/packages/SettingsLib/res/values-ka-rGE/arrays.xml
+++ b/packages/SettingsLib/res/values-ka-rGE/arrays.xml
@@ -58,6 +58,46 @@
<item msgid="3878793616631049349">"HDCP შემოწმების გამოყენება მხოლოდ DRM კონტენტის შემთხვევაში"</item>
<item msgid="45075631231212732">"ყოველთვის გამოიყენე HDCP შემოწმება"</item>
</string-array>
+ <!-- no translation found for bluetooth_a2dp_codec_titles:0 (1852387125374225729) -->
+ <!-- no translation found for bluetooth_a2dp_codec_titles:1 (7539690996561263909) -->
+ <!-- no translation found for bluetooth_a2dp_codec_titles:2 (4260844283202960798) -->
+ <!-- no translation found for bluetooth_a2dp_codec_titles:3 (7279983368484312990) -->
+ <!-- no translation found for bluetooth_a2dp_codec_titles:4 (2301339338870319651) -->
+ <!-- no translation found for bluetooth_a2dp_codec_summaries:0 (9072025520360316957) -->
+ <!-- no translation found for bluetooth_a2dp_codec_summaries:1 (6898329690939802290) -->
+ <!-- no translation found for bluetooth_a2dp_codec_summaries:2 (1190434429082395888) -->
+ <!-- no translation found for bluetooth_a2dp_codec_summaries:3 (649699003004233053) -->
+ <!-- no translation found for bluetooth_a2dp_codec_summaries:4 (508106435710925399) -->
+ <!-- no translation found for bluetooth_a2dp_codec_sample_rate_titles:0 (7102940318360468759) -->
+ <!-- no translation found for bluetooth_a2dp_codec_sample_rate_titles:1 (8895532488906185219) -->
+ <!-- no translation found for bluetooth_a2dp_codec_sample_rate_titles:2 (2909915718994807056) -->
+ <!-- no translation found for bluetooth_a2dp_codec_sample_rate_titles:3 (3347287377354164611) -->
+ <!-- no translation found for bluetooth_a2dp_codec_sample_rate_titles:4 (1234212100239985373) -->
+ <!-- no translation found for bluetooth_a2dp_codec_sample_rate_summaries:0 (7224433008148687313) -->
+ <!-- no translation found for bluetooth_a2dp_codec_sample_rate_summaries:1 (4482862757811638365) -->
+ <!-- no translation found for bluetooth_a2dp_codec_sample_rate_summaries:2 (354495328188724404) -->
+ <!-- no translation found for bluetooth_a2dp_codec_sample_rate_summaries:3 (7329816882213695083) -->
+ <!-- no translation found for bluetooth_a2dp_codec_sample_rate_summaries:4 (6967397666254430476) -->
+ <!-- no translation found for bluetooth_a2dp_codec_bits_per_sample_titles:0 (6694044160540313386) -->
+ <!-- no translation found for bluetooth_a2dp_codec_bits_per_sample_titles:1 (5618929009984956469) -->
+ <!-- no translation found for bluetooth_a2dp_codec_bits_per_sample_titles:2 (3412640499234627248) -->
+ <!-- no translation found for bluetooth_a2dp_codec_bits_per_sample_titles:3 (121583001492929387) -->
+ <!-- no translation found for bluetooth_a2dp_codec_bits_per_sample_summaries:0 (5091076677792306320) -->
+ <!-- no translation found for bluetooth_a2dp_codec_bits_per_sample_summaries:1 (4726688794884191540) -->
+ <!-- no translation found for bluetooth_a2dp_codec_bits_per_sample_summaries:2 (305344756485516870) -->
+ <!-- no translation found for bluetooth_a2dp_codec_bits_per_sample_summaries:3 (244568657919675099) -->
+ <!-- no translation found for bluetooth_a2dp_codec_channel_mode_titles:0 (13423709606339855) -->
+ <!-- no translation found for bluetooth_a2dp_codec_channel_mode_titles:1 (4106832974775067314) -->
+ <!-- no translation found for bluetooth_a2dp_codec_channel_mode_titles:2 (5571632958424639155) -->
+ <!-- no translation found for bluetooth_a2dp_codec_channel_mode_summaries:0 (8128478683963250130) -->
+ <!-- no translation found for bluetooth_a2dp_codec_channel_mode_summaries:1 (8900559293912978337) -->
+ <!-- no translation found for bluetooth_a2dp_codec_channel_mode_summaries:2 (8883739882299884241) -->
+ <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_titles:0 (2944889121850394020) -->
+ <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_titles:1 (138837449700903545) -->
+ <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_titles:2 (4777177307869441982) -->
+ <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_summaries:0 (172302906231378902) -->
+ <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_summaries:1 (9091111147684472529) -->
+ <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_summaries:2 (3367904477834831032) -->
<string-array name="select_logd_size_titles">
<item msgid="8665206199209698501">"გამორთული"</item>
<item msgid="1593289376502312923">"64 კბაიტი"</item>
diff --git a/packages/SettingsLib/res/values-ka-rGE/strings.xml b/packages/SettingsLib/res/values-ka-rGE/strings.xml
index 8a3b81b..14447cd 100644
--- a/packages/SettingsLib/res/values-ka-rGE/strings.xml
+++ b/packages/SettingsLib/res/values-ka-rGE/strings.xml
@@ -170,6 +170,26 @@
<string name="wifi_allow_scan_with_traffic" msgid="3601853081178265786">"Wi‑Fi Roam სკანირების მუდამ დაშვება"</string>
<string name="mobile_data_always_on" msgid="7745605759775320362">"ფიჭური მონაცემები ყოველთვის აქტიურია"</string>
<string name="bluetooth_disable_absolute_volume" msgid="2660673801947898809">"ხმის აბსოლუტური სიძლიერის გათიშვა"</string>
+ <!-- no translation found for bluetooth_select_a2dp_codec_type (90597356942154882) -->
+ <skip />
+ <!-- no translation found for bluetooth_select_a2dp_codec_type_dialog_title (6470824182074383881) -->
+ <skip />
+ <!-- no translation found for bluetooth_select_a2dp_codec_sample_rate (4788245703824623062) -->
+ <skip />
+ <!-- no translation found for bluetooth_select_a2dp_codec_sample_rate_dialog_title (4263851572248033749) -->
+ <skip />
+ <!-- no translation found for bluetooth_select_a2dp_codec_bits_per_sample (2099645202720164141) -->
+ <skip />
+ <!-- no translation found for bluetooth_select_a2dp_codec_bits_per_sample_dialog_title (2096170505745650345) -->
+ <skip />
+ <!-- no translation found for bluetooth_select_a2dp_codec_channel_mode (884855779449390540) -->
+ <skip />
+ <!-- no translation found for bluetooth_select_a2dp_codec_channel_mode_dialog_title (4073812880900816325) -->
+ <skip />
+ <!-- no translation found for bluetooth_select_a2dp_codec_ldac_playback_quality (4846872213548295632) -->
+ <skip />
+ <!-- no translation found for bluetooth_select_a2dp_codec_ldac_playback_quality_dialog_title (3940973633342423717) -->
+ <skip />
<string name="wifi_display_certification_summary" msgid="1155182309166746973">"უსადენო ეკრანის სერტიფიცირების ვარიანტების ჩვენება"</string>
<string name="wifi_verbose_logging_summary" msgid="6615071616111731958">"Wi‑Fi-ს აღრიცხვის დონის გაზრდა, Wi‑Fi ამომრჩეველში ყოველ SSID RSSI-ზე ჩვენება"</string>
<string name="wifi_aggressive_handover_summary" msgid="6328455667642570371">"თუ ჩართულია, Wi‑Fi სიგნალის შესუსტების შემთხვევაში Wi-Fi უფრო აქტიურად შეეცდება გადაიყვანოს ინტერნეტ-კავშირი მობილურ ინტერნეტზე"</string>
diff --git a/packages/SettingsLib/res/values-kk-rKZ/arrays.xml b/packages/SettingsLib/res/values-kk-rKZ/arrays.xml
index 78e2f7653..b08a33a 100644
--- a/packages/SettingsLib/res/values-kk-rKZ/arrays.xml
+++ b/packages/SettingsLib/res/values-kk-rKZ/arrays.xml
@@ -58,6 +58,46 @@
<item msgid="3878793616631049349">"HDCP (кең жолақты сандық мазмұн қорғау) тексеруді DRM (авторлық құқықты техникалық қорғау) мазмұны үшін ғана қолданыңыз"</item>
<item msgid="45075631231212732">"Әрқашан HDCP (жоғары кең жолақты сандық мазмұн қорғаушы) тексерулерін қолданыңыз"</item>
</string-array>
+ <!-- no translation found for bluetooth_a2dp_codec_titles:0 (1852387125374225729) -->
+ <!-- no translation found for bluetooth_a2dp_codec_titles:1 (7539690996561263909) -->
+ <!-- no translation found for bluetooth_a2dp_codec_titles:2 (4260844283202960798) -->
+ <!-- no translation found for bluetooth_a2dp_codec_titles:3 (7279983368484312990) -->
+ <!-- no translation found for bluetooth_a2dp_codec_titles:4 (2301339338870319651) -->
+ <!-- no translation found for bluetooth_a2dp_codec_summaries:0 (9072025520360316957) -->
+ <!-- no translation found for bluetooth_a2dp_codec_summaries:1 (6898329690939802290) -->
+ <!-- no translation found for bluetooth_a2dp_codec_summaries:2 (1190434429082395888) -->
+ <!-- no translation found for bluetooth_a2dp_codec_summaries:3 (649699003004233053) -->
+ <!-- no translation found for bluetooth_a2dp_codec_summaries:4 (508106435710925399) -->
+ <!-- no translation found for bluetooth_a2dp_codec_sample_rate_titles:0 (7102940318360468759) -->
+ <!-- no translation found for bluetooth_a2dp_codec_sample_rate_titles:1 (8895532488906185219) -->
+ <!-- no translation found for bluetooth_a2dp_codec_sample_rate_titles:2 (2909915718994807056) -->
+ <!-- no translation found for bluetooth_a2dp_codec_sample_rate_titles:3 (3347287377354164611) -->
+ <!-- no translation found for bluetooth_a2dp_codec_sample_rate_titles:4 (1234212100239985373) -->
+ <!-- no translation found for bluetooth_a2dp_codec_sample_rate_summaries:0 (7224433008148687313) -->
+ <!-- no translation found for bluetooth_a2dp_codec_sample_rate_summaries:1 (4482862757811638365) -->
+ <!-- no translation found for bluetooth_a2dp_codec_sample_rate_summaries:2 (354495328188724404) -->
+ <!-- no translation found for bluetooth_a2dp_codec_sample_rate_summaries:3 (7329816882213695083) -->
+ <!-- no translation found for bluetooth_a2dp_codec_sample_rate_summaries:4 (6967397666254430476) -->
+ <!-- no translation found for bluetooth_a2dp_codec_bits_per_sample_titles:0 (6694044160540313386) -->
+ <!-- no translation found for bluetooth_a2dp_codec_bits_per_sample_titles:1 (5618929009984956469) -->
+ <!-- no translation found for bluetooth_a2dp_codec_bits_per_sample_titles:2 (3412640499234627248) -->
+ <!-- no translation found for bluetooth_a2dp_codec_bits_per_sample_titles:3 (121583001492929387) -->
+ <!-- no translation found for bluetooth_a2dp_codec_bits_per_sample_summaries:0 (5091076677792306320) -->
+ <!-- no translation found for bluetooth_a2dp_codec_bits_per_sample_summaries:1 (4726688794884191540) -->
+ <!-- no translation found for bluetooth_a2dp_codec_bits_per_sample_summaries:2 (305344756485516870) -->
+ <!-- no translation found for bluetooth_a2dp_codec_bits_per_sample_summaries:3 (244568657919675099) -->
+ <!-- no translation found for bluetooth_a2dp_codec_channel_mode_titles:0 (13423709606339855) -->
+ <!-- no translation found for bluetooth_a2dp_codec_channel_mode_titles:1 (4106832974775067314) -->
+ <!-- no translation found for bluetooth_a2dp_codec_channel_mode_titles:2 (5571632958424639155) -->
+ <!-- no translation found for bluetooth_a2dp_codec_channel_mode_summaries:0 (8128478683963250130) -->
+ <!-- no translation found for bluetooth_a2dp_codec_channel_mode_summaries:1 (8900559293912978337) -->
+ <!-- no translation found for bluetooth_a2dp_codec_channel_mode_summaries:2 (8883739882299884241) -->
+ <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_titles:0 (2944889121850394020) -->
+ <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_titles:1 (138837449700903545) -->
+ <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_titles:2 (4777177307869441982) -->
+ <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_summaries:0 (172302906231378902) -->
+ <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_summaries:1 (9091111147684472529) -->
+ <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_summaries:2 (3367904477834831032) -->
<string-array name="select_logd_size_titles">
<item msgid="8665206199209698501">"Өшірулі"</item>
<item msgid="1593289376502312923">"64 КБ"</item>
diff --git a/packages/SettingsLib/res/values-kk-rKZ/strings.xml b/packages/SettingsLib/res/values-kk-rKZ/strings.xml
index 920b810..b2ca989 100644
--- a/packages/SettingsLib/res/values-kk-rKZ/strings.xml
+++ b/packages/SettingsLib/res/values-kk-rKZ/strings.xml
@@ -170,6 +170,26 @@
<string name="wifi_allow_scan_with_traffic" msgid="3601853081178265786">"Wi‑Fi роумингін іздеулерге әрқашан рұқсат ету"</string>
<string name="mobile_data_always_on" msgid="7745605759775320362">"Ұялы деректер әрқашан белсенді"</string>
<string name="bluetooth_disable_absolute_volume" msgid="2660673801947898809">"Абсолютті дыбыс деңгейін өшіру"</string>
+ <!-- no translation found for bluetooth_select_a2dp_codec_type (90597356942154882) -->
+ <skip />
+ <!-- no translation found for bluetooth_select_a2dp_codec_type_dialog_title (6470824182074383881) -->
+ <skip />
+ <!-- no translation found for bluetooth_select_a2dp_codec_sample_rate (4788245703824623062) -->
+ <skip />
+ <!-- no translation found for bluetooth_select_a2dp_codec_sample_rate_dialog_title (4263851572248033749) -->
+ <skip />
+ <!-- no translation found for bluetooth_select_a2dp_codec_bits_per_sample (2099645202720164141) -->
+ <skip />
+ <!-- no translation found for bluetooth_select_a2dp_codec_bits_per_sample_dialog_title (2096170505745650345) -->
+ <skip />
+ <!-- no translation found for bluetooth_select_a2dp_codec_channel_mode (884855779449390540) -->
+ <skip />
+ <!-- no translation found for bluetooth_select_a2dp_codec_channel_mode_dialog_title (4073812880900816325) -->
+ <skip />
+ <!-- no translation found for bluetooth_select_a2dp_codec_ldac_playback_quality (4846872213548295632) -->
+ <skip />
+ <!-- no translation found for bluetooth_select_a2dp_codec_ldac_playback_quality_dialog_title (3940973633342423717) -->
+ <skip />
<string name="wifi_display_certification_summary" msgid="1155182309166746973">"Сымсыз дисплей растау опцияларын көрсету"</string>
<string name="wifi_verbose_logging_summary" msgid="6615071616111731958">"Wi‑Fi жур. тір. дең. арт., Wi‑Fi желісін таңдағышта әр SSID RSSI бойынша көрсету"</string>
<string name="wifi_aggressive_handover_summary" msgid="6328455667642570371">"Wi‑Fi сигналы әлсіз болғанда, деректер байланысы мәжбүрлі түрде ұялы желіге ауысады"</string>
diff --git a/packages/SettingsLib/res/values-km-rKH/arrays.xml b/packages/SettingsLib/res/values-km-rKH/arrays.xml
index 2879b09..0787bcd 100644
--- a/packages/SettingsLib/res/values-km-rKH/arrays.xml
+++ b/packages/SettingsLib/res/values-km-rKH/arrays.xml
@@ -58,6 +58,46 @@
<item msgid="3878793616631049349">"ប្រើការពិនិត្យ HDCP សម្រាប់តែមាតិកា DRM ប៉ុណ្ណោះ"</item>
<item msgid="45075631231212732">"ប្រើការពិនិត្យ HDCP ជានិច្ច"</item>
</string-array>
+ <!-- no translation found for bluetooth_a2dp_codec_titles:0 (1852387125374225729) -->
+ <!-- no translation found for bluetooth_a2dp_codec_titles:1 (7539690996561263909) -->
+ <!-- no translation found for bluetooth_a2dp_codec_titles:2 (4260844283202960798) -->
+ <!-- no translation found for bluetooth_a2dp_codec_titles:3 (7279983368484312990) -->
+ <!-- no translation found for bluetooth_a2dp_codec_titles:4 (2301339338870319651) -->
+ <!-- no translation found for bluetooth_a2dp_codec_summaries:0 (9072025520360316957) -->
+ <!-- no translation found for bluetooth_a2dp_codec_summaries:1 (6898329690939802290) -->
+ <!-- no translation found for bluetooth_a2dp_codec_summaries:2 (1190434429082395888) -->
+ <!-- no translation found for bluetooth_a2dp_codec_summaries:3 (649699003004233053) -->
+ <!-- no translation found for bluetooth_a2dp_codec_summaries:4 (508106435710925399) -->
+ <!-- no translation found for bluetooth_a2dp_codec_sample_rate_titles:0 (7102940318360468759) -->
+ <!-- no translation found for bluetooth_a2dp_codec_sample_rate_titles:1 (8895532488906185219) -->
+ <!-- no translation found for bluetooth_a2dp_codec_sample_rate_titles:2 (2909915718994807056) -->
+ <!-- no translation found for bluetooth_a2dp_codec_sample_rate_titles:3 (3347287377354164611) -->
+ <!-- no translation found for bluetooth_a2dp_codec_sample_rate_titles:4 (1234212100239985373) -->
+ <!-- no translation found for bluetooth_a2dp_codec_sample_rate_summaries:0 (7224433008148687313) -->
+ <!-- no translation found for bluetooth_a2dp_codec_sample_rate_summaries:1 (4482862757811638365) -->
+ <!-- no translation found for bluetooth_a2dp_codec_sample_rate_summaries:2 (354495328188724404) -->
+ <!-- no translation found for bluetooth_a2dp_codec_sample_rate_summaries:3 (7329816882213695083) -->
+ <!-- no translation found for bluetooth_a2dp_codec_sample_rate_summaries:4 (6967397666254430476) -->
+ <!-- no translation found for bluetooth_a2dp_codec_bits_per_sample_titles:0 (6694044160540313386) -->
+ <!-- no translation found for bluetooth_a2dp_codec_bits_per_sample_titles:1 (5618929009984956469) -->
+ <!-- no translation found for bluetooth_a2dp_codec_bits_per_sample_titles:2 (3412640499234627248) -->
+ <!-- no translation found for bluetooth_a2dp_codec_bits_per_sample_titles:3 (121583001492929387) -->
+ <!-- no translation found for bluetooth_a2dp_codec_bits_per_sample_summaries:0 (5091076677792306320) -->
+ <!-- no translation found for bluetooth_a2dp_codec_bits_per_sample_summaries:1 (4726688794884191540) -->
+ <!-- no translation found for bluetooth_a2dp_codec_bits_per_sample_summaries:2 (305344756485516870) -->
+ <!-- no translation found for bluetooth_a2dp_codec_bits_per_sample_summaries:3 (244568657919675099) -->
+ <!-- no translation found for bluetooth_a2dp_codec_channel_mode_titles:0 (13423709606339855) -->
+ <!-- no translation found for bluetooth_a2dp_codec_channel_mode_titles:1 (4106832974775067314) -->
+ <!-- no translation found for bluetooth_a2dp_codec_channel_mode_titles:2 (5571632958424639155) -->
+ <!-- no translation found for bluetooth_a2dp_codec_channel_mode_summaries:0 (8128478683963250130) -->
+ <!-- no translation found for bluetooth_a2dp_codec_channel_mode_summaries:1 (8900559293912978337) -->
+ <!-- no translation found for bluetooth_a2dp_codec_channel_mode_summaries:2 (8883739882299884241) -->
+ <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_titles:0 (2944889121850394020) -->
+ <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_titles:1 (138837449700903545) -->
+ <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_titles:2 (4777177307869441982) -->
+ <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_summaries:0 (172302906231378902) -->
+ <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_summaries:1 (9091111147684472529) -->
+ <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_summaries:2 (3367904477834831032) -->
<string-array name="select_logd_size_titles">
<item msgid="8665206199209698501">"បិទ"</item>
<item msgid="1593289376502312923">"64K"</item>
diff --git a/packages/SettingsLib/res/values-km-rKH/strings.xml b/packages/SettingsLib/res/values-km-rKH/strings.xml
index d162bd1..a64aeaa 100644
--- a/packages/SettingsLib/res/values-km-rKH/strings.xml
+++ b/packages/SettingsLib/res/values-km-rKH/strings.xml
@@ -170,6 +170,26 @@
<string name="wifi_allow_scan_with_traffic" msgid="3601853081178265786">"តែងតែអនុញ្ញាតការវិភាគរ៉ូមវ៉ាយហ្វាយ"</string>
<string name="mobile_data_always_on" msgid="7745605759775320362">"ទិន្នន័យចល័តសកម្មជានិច្ច"</string>
<string name="bluetooth_disable_absolute_volume" msgid="2660673801947898809">"បិទកម្រិតសំឡេងលឺខ្លាំង"</string>
+ <!-- no translation found for bluetooth_select_a2dp_codec_type (90597356942154882) -->
+ <skip />
+ <!-- no translation found for bluetooth_select_a2dp_codec_type_dialog_title (6470824182074383881) -->
+ <skip />
+ <!-- no translation found for bluetooth_select_a2dp_codec_sample_rate (4788245703824623062) -->
+ <skip />
+ <!-- no translation found for bluetooth_select_a2dp_codec_sample_rate_dialog_title (4263851572248033749) -->
+ <skip />
+ <!-- no translation found for bluetooth_select_a2dp_codec_bits_per_sample (2099645202720164141) -->
+ <skip />
+ <!-- no translation found for bluetooth_select_a2dp_codec_bits_per_sample_dialog_title (2096170505745650345) -->
+ <skip />
+ <!-- no translation found for bluetooth_select_a2dp_codec_channel_mode (884855779449390540) -->
+ <skip />
+ <!-- no translation found for bluetooth_select_a2dp_codec_channel_mode_dialog_title (4073812880900816325) -->
+ <skip />
+ <!-- no translation found for bluetooth_select_a2dp_codec_ldac_playback_quality (4846872213548295632) -->
+ <skip />
+ <!-- no translation found for bluetooth_select_a2dp_codec_ldac_playback_quality_dialog_title (3940973633342423717) -->
+ <skip />
<string name="wifi_display_certification_summary" msgid="1155182309166746973">"បង្ហាញជម្រើសសម្រាប់វិញ្ញាបនបត្របង្ហាញឥតខ្សែ"</string>
<string name="wifi_verbose_logging_summary" msgid="6615071616111731958">"បង្កើនកម្រិតកំណត់ហេតុវ៉ាយហ្វាយបង្ហាញក្នុង SSID RSSI ក្នុងកម្មវិធីជ្រើសវ៉ាយហ្វាយ"</string>
<string name="wifi_aggressive_handover_summary" msgid="6328455667642570371">"ពេលបានបើក វ៉ាយហ្វាយនឹងកាន់តែបង្ខំក្នុងការបញ្ជូនការភ្ជាប់ទិន្នន័យទៅបណ្ដាញចល័ត នៅពេលសញ្ញាវ៉ាយហ្វាយយឺត"</string>
diff --git a/packages/SettingsLib/res/values-kn-rIN/arrays.xml b/packages/SettingsLib/res/values-kn-rIN/arrays.xml
index d3e9f65..102faa5 100644
--- a/packages/SettingsLib/res/values-kn-rIN/arrays.xml
+++ b/packages/SettingsLib/res/values-kn-rIN/arrays.xml
@@ -51,13 +51,53 @@
<string-array name="hdcp_checking_titles">
<item msgid="441827799230089869">"ಎಂದಿಗೂ ಪರಿಶೀಲಿಸದಿರು"</item>
<item msgid="6042769699089883931">"DRM ವಿಷಯಗಳಿಗಾಗಿ ಮಾತ್ರ ಪರಿಶೀಲಿಸಿ"</item>
- <item msgid="9174900380056846820">"ಯಾವಾಗಲೂ ಪರಿಶೀಲಿಸು"</item>
+ <item msgid="9174900380056846820">"ಯಾವಾಗಲೂ ಪರಿಶೀಲಿಸಿ"</item>
</string-array>
<string-array name="hdcp_checking_summaries">
<item msgid="505558545611516707">"HDCP ಪರಿಶೀಲನೆಯನ್ನು ಎಂದಿಗೂ ಬಳಸದಿರು"</item>
<item msgid="3878793616631049349">"DRM ವಿಷಯಗಳಿಗೆ ಮಾತ್ರ HDCP ಪರೀಕ್ಷಿಸುವಿಕೆಯನ್ನು ಬಳಸು"</item>
<item msgid="45075631231212732">"HDCP ಪರಿಶೀಲನೆಯನ್ನು ಯಾವಾಗಲೂ ಬಳಸು"</item>
</string-array>
+ <!-- no translation found for bluetooth_a2dp_codec_titles:0 (1852387125374225729) -->
+ <!-- no translation found for bluetooth_a2dp_codec_titles:1 (7539690996561263909) -->
+ <!-- no translation found for bluetooth_a2dp_codec_titles:2 (4260844283202960798) -->
+ <!-- no translation found for bluetooth_a2dp_codec_titles:3 (7279983368484312990) -->
+ <!-- no translation found for bluetooth_a2dp_codec_titles:4 (2301339338870319651) -->
+ <!-- no translation found for bluetooth_a2dp_codec_summaries:0 (9072025520360316957) -->
+ <!-- no translation found for bluetooth_a2dp_codec_summaries:1 (6898329690939802290) -->
+ <!-- no translation found for bluetooth_a2dp_codec_summaries:2 (1190434429082395888) -->
+ <!-- no translation found for bluetooth_a2dp_codec_summaries:3 (649699003004233053) -->
+ <!-- no translation found for bluetooth_a2dp_codec_summaries:4 (508106435710925399) -->
+ <!-- no translation found for bluetooth_a2dp_codec_sample_rate_titles:0 (7102940318360468759) -->
+ <!-- no translation found for bluetooth_a2dp_codec_sample_rate_titles:1 (8895532488906185219) -->
+ <!-- no translation found for bluetooth_a2dp_codec_sample_rate_titles:2 (2909915718994807056) -->
+ <!-- no translation found for bluetooth_a2dp_codec_sample_rate_titles:3 (3347287377354164611) -->
+ <!-- no translation found for bluetooth_a2dp_codec_sample_rate_titles:4 (1234212100239985373) -->
+ <!-- no translation found for bluetooth_a2dp_codec_sample_rate_summaries:0 (7224433008148687313) -->
+ <!-- no translation found for bluetooth_a2dp_codec_sample_rate_summaries:1 (4482862757811638365) -->
+ <!-- no translation found for bluetooth_a2dp_codec_sample_rate_summaries:2 (354495328188724404) -->
+ <!-- no translation found for bluetooth_a2dp_codec_sample_rate_summaries:3 (7329816882213695083) -->
+ <!-- no translation found for bluetooth_a2dp_codec_sample_rate_summaries:4 (6967397666254430476) -->
+ <!-- no translation found for bluetooth_a2dp_codec_bits_per_sample_titles:0 (6694044160540313386) -->
+ <!-- no translation found for bluetooth_a2dp_codec_bits_per_sample_titles:1 (5618929009984956469) -->
+ <!-- no translation found for bluetooth_a2dp_codec_bits_per_sample_titles:2 (3412640499234627248) -->
+ <!-- no translation found for bluetooth_a2dp_codec_bits_per_sample_titles:3 (121583001492929387) -->
+ <!-- no translation found for bluetooth_a2dp_codec_bits_per_sample_summaries:0 (5091076677792306320) -->
+ <!-- no translation found for bluetooth_a2dp_codec_bits_per_sample_summaries:1 (4726688794884191540) -->
+ <!-- no translation found for bluetooth_a2dp_codec_bits_per_sample_summaries:2 (305344756485516870) -->
+ <!-- no translation found for bluetooth_a2dp_codec_bits_per_sample_summaries:3 (244568657919675099) -->
+ <!-- no translation found for bluetooth_a2dp_codec_channel_mode_titles:0 (13423709606339855) -->
+ <!-- no translation found for bluetooth_a2dp_codec_channel_mode_titles:1 (4106832974775067314) -->
+ <!-- no translation found for bluetooth_a2dp_codec_channel_mode_titles:2 (5571632958424639155) -->
+ <!-- no translation found for bluetooth_a2dp_codec_channel_mode_summaries:0 (8128478683963250130) -->
+ <!-- no translation found for bluetooth_a2dp_codec_channel_mode_summaries:1 (8900559293912978337) -->
+ <!-- no translation found for bluetooth_a2dp_codec_channel_mode_summaries:2 (8883739882299884241) -->
+ <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_titles:0 (2944889121850394020) -->
+ <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_titles:1 (138837449700903545) -->
+ <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_titles:2 (4777177307869441982) -->
+ <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_summaries:0 (172302906231378902) -->
+ <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_summaries:1 (9091111147684472529) -->
+ <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_summaries:2 (3367904477834831032) -->
<string-array name="select_logd_size_titles">
<item msgid="8665206199209698501">"ಆಫ್"</item>
<item msgid="1593289376502312923">"64K"</item>
diff --git a/packages/SettingsLib/res/values-kn-rIN/strings.xml b/packages/SettingsLib/res/values-kn-rIN/strings.xml
index ca0ba0a..bb6f098 100644
--- a/packages/SettingsLib/res/values-kn-rIN/strings.xml
+++ b/packages/SettingsLib/res/values-kn-rIN/strings.xml
@@ -170,6 +170,26 @@
<string name="wifi_allow_scan_with_traffic" msgid="3601853081178265786">"ವೈ-ಫೈ ರೋಮ್ ಸ್ಕ್ಯಾನ್ಗಳನ್ನು ಯಾವಾಗಲೂ ಅನುಮತಿಸಿ"</string>
<string name="mobile_data_always_on" msgid="7745605759775320362">"ಸೆಲ್ಯುಲರ್ ಡೇಟಾ ಯಾವಾಗಲೂ ಸಕ್ರಿಯ"</string>
<string name="bluetooth_disable_absolute_volume" msgid="2660673801947898809">"ಸಂಪೂರ್ಣ ವಾಲ್ಯೂಮ್ ನಿಷ್ಕ್ರಿಯಗೊಳಿಸಿ"</string>
+ <!-- no translation found for bluetooth_select_a2dp_codec_type (90597356942154882) -->
+ <skip />
+ <!-- no translation found for bluetooth_select_a2dp_codec_type_dialog_title (6470824182074383881) -->
+ <skip />
+ <!-- no translation found for bluetooth_select_a2dp_codec_sample_rate (4788245703824623062) -->
+ <skip />
+ <!-- no translation found for bluetooth_select_a2dp_codec_sample_rate_dialog_title (4263851572248033749) -->
+ <skip />
+ <!-- no translation found for bluetooth_select_a2dp_codec_bits_per_sample (2099645202720164141) -->
+ <skip />
+ <!-- no translation found for bluetooth_select_a2dp_codec_bits_per_sample_dialog_title (2096170505745650345) -->
+ <skip />
+ <!-- no translation found for bluetooth_select_a2dp_codec_channel_mode (884855779449390540) -->
+ <skip />
+ <!-- no translation found for bluetooth_select_a2dp_codec_channel_mode_dialog_title (4073812880900816325) -->
+ <skip />
+ <!-- no translation found for bluetooth_select_a2dp_codec_ldac_playback_quality (4846872213548295632) -->
+ <skip />
+ <!-- no translation found for bluetooth_select_a2dp_codec_ldac_playback_quality_dialog_title (3940973633342423717) -->
+ <skip />
<string name="wifi_display_certification_summary" msgid="1155182309166746973">"ವೈರ್ಲೆಸ್ ಪ್ರದರ್ಶನ ಪ್ರಮಾಣೀಕರಣಕ್ಕಾಗಿ ಆಯ್ಕೆಗಳನ್ನು ತೋರಿಸು"</string>
<string name="wifi_verbose_logging_summary" msgid="6615071616111731958">"Wi‑Fi ಲಾಗಿಂಗ್ ಮಟ್ಟನ್ನು ಹೆಚ್ಚಿಸಿ, Wi‑Fi ಆಯ್ಕೆಯಲ್ಲಿ ಪ್ರತಿಯೊಂದು SSID RSSI ತೋರಿಸಿ"</string>
<string name="wifi_aggressive_handover_summary" msgid="6328455667642570371">"ಸಕ್ರಿಯಗೊಂಡರೆ, Wi‑Fi ಸಿಗ್ನಲ್ ದುರ್ಬಲವಾಗಿದ್ದರೂ ಕೂಡ, ಸೆಲ್ಯುಲರ್ಗೆ ಡೇಟಾ ಸಂಪರ್ಕವನ್ನು ಹಸ್ತಾಂತರಿಸುವಲ್ಲಿ Wi‑Fi ಹೆಚ್ಚು ಆಕ್ರಮಣಕಾರಿಯಾಗಿರುತ್ತದೆ"</string>
diff --git a/packages/SettingsLib/res/values-ko/arrays.xml b/packages/SettingsLib/res/values-ko/arrays.xml
index 9cf5fd4..941b049 100644
--- a/packages/SettingsLib/res/values-ko/arrays.xml
+++ b/packages/SettingsLib/res/values-ko/arrays.xml
@@ -58,6 +58,46 @@
<item msgid="3878793616631049349">"DRM 콘텐츠에 대해서만 HDCP 확인 사용"</item>
<item msgid="45075631231212732">"항상 HDCP 확인 사용"</item>
</string-array>
+ <!-- no translation found for bluetooth_a2dp_codec_titles:0 (1852387125374225729) -->
+ <!-- no translation found for bluetooth_a2dp_codec_titles:1 (7539690996561263909) -->
+ <!-- no translation found for bluetooth_a2dp_codec_titles:2 (4260844283202960798) -->
+ <!-- no translation found for bluetooth_a2dp_codec_titles:3 (7279983368484312990) -->
+ <!-- no translation found for bluetooth_a2dp_codec_titles:4 (2301339338870319651) -->
+ <!-- no translation found for bluetooth_a2dp_codec_summaries:0 (9072025520360316957) -->
+ <!-- no translation found for bluetooth_a2dp_codec_summaries:1 (6898329690939802290) -->
+ <!-- no translation found for bluetooth_a2dp_codec_summaries:2 (1190434429082395888) -->
+ <!-- no translation found for bluetooth_a2dp_codec_summaries:3 (649699003004233053) -->
+ <!-- no translation found for bluetooth_a2dp_codec_summaries:4 (508106435710925399) -->
+ <!-- no translation found for bluetooth_a2dp_codec_sample_rate_titles:0 (7102940318360468759) -->
+ <!-- no translation found for bluetooth_a2dp_codec_sample_rate_titles:1 (8895532488906185219) -->
+ <!-- no translation found for bluetooth_a2dp_codec_sample_rate_titles:2 (2909915718994807056) -->
+ <!-- no translation found for bluetooth_a2dp_codec_sample_rate_titles:3 (3347287377354164611) -->
+ <!-- no translation found for bluetooth_a2dp_codec_sample_rate_titles:4 (1234212100239985373) -->
+ <!-- no translation found for bluetooth_a2dp_codec_sample_rate_summaries:0 (7224433008148687313) -->
+ <!-- no translation found for bluetooth_a2dp_codec_sample_rate_summaries:1 (4482862757811638365) -->
+ <!-- no translation found for bluetooth_a2dp_codec_sample_rate_summaries:2 (354495328188724404) -->
+ <!-- no translation found for bluetooth_a2dp_codec_sample_rate_summaries:3 (7329816882213695083) -->
+ <!-- no translation found for bluetooth_a2dp_codec_sample_rate_summaries:4 (6967397666254430476) -->
+ <!-- no translation found for bluetooth_a2dp_codec_bits_per_sample_titles:0 (6694044160540313386) -->
+ <!-- no translation found for bluetooth_a2dp_codec_bits_per_sample_titles:1 (5618929009984956469) -->
+ <!-- no translation found for bluetooth_a2dp_codec_bits_per_sample_titles:2 (3412640499234627248) -->
+ <!-- no translation found for bluetooth_a2dp_codec_bits_per_sample_titles:3 (121583001492929387) -->
+ <!-- no translation found for bluetooth_a2dp_codec_bits_per_sample_summaries:0 (5091076677792306320) -->
+ <!-- no translation found for bluetooth_a2dp_codec_bits_per_sample_summaries:1 (4726688794884191540) -->
+ <!-- no translation found for bluetooth_a2dp_codec_bits_per_sample_summaries:2 (305344756485516870) -->
+ <!-- no translation found for bluetooth_a2dp_codec_bits_per_sample_summaries:3 (244568657919675099) -->
+ <!-- no translation found for bluetooth_a2dp_codec_channel_mode_titles:0 (13423709606339855) -->
+ <!-- no translation found for bluetooth_a2dp_codec_channel_mode_titles:1 (4106832974775067314) -->
+ <!-- no translation found for bluetooth_a2dp_codec_channel_mode_titles:2 (5571632958424639155) -->
+ <!-- no translation found for bluetooth_a2dp_codec_channel_mode_summaries:0 (8128478683963250130) -->
+ <!-- no translation found for bluetooth_a2dp_codec_channel_mode_summaries:1 (8900559293912978337) -->
+ <!-- no translation found for bluetooth_a2dp_codec_channel_mode_summaries:2 (8883739882299884241) -->
+ <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_titles:0 (2944889121850394020) -->
+ <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_titles:1 (138837449700903545) -->
+ <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_titles:2 (4777177307869441982) -->
+ <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_summaries:0 (172302906231378902) -->
+ <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_summaries:1 (9091111147684472529) -->
+ <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_summaries:2 (3367904477834831032) -->
<string-array name="select_logd_size_titles">
<item msgid="8665206199209698501">"사용 안함"</item>
<item msgid="1593289376502312923">"64K"</item>
diff --git a/packages/SettingsLib/res/values-ko/strings.xml b/packages/SettingsLib/res/values-ko/strings.xml
index 2732853..ee97fe1 100644
--- a/packages/SettingsLib/res/values-ko/strings.xml
+++ b/packages/SettingsLib/res/values-ko/strings.xml
@@ -170,6 +170,26 @@
<string name="wifi_allow_scan_with_traffic" msgid="3601853081178265786">"Wi‑Fi 로밍 스캔 항상 허용"</string>
<string name="mobile_data_always_on" msgid="7745605759775320362">"모바일 데이터 항상 활성화"</string>
<string name="bluetooth_disable_absolute_volume" msgid="2660673801947898809">"절대 볼륨 사용 안함"</string>
+ <!-- no translation found for bluetooth_select_a2dp_codec_type (90597356942154882) -->
+ <skip />
+ <!-- no translation found for bluetooth_select_a2dp_codec_type_dialog_title (6470824182074383881) -->
+ <skip />
+ <!-- no translation found for bluetooth_select_a2dp_codec_sample_rate (4788245703824623062) -->
+ <skip />
+ <!-- no translation found for bluetooth_select_a2dp_codec_sample_rate_dialog_title (4263851572248033749) -->
+ <skip />
+ <!-- no translation found for bluetooth_select_a2dp_codec_bits_per_sample (2099645202720164141) -->
+ <skip />
+ <!-- no translation found for bluetooth_select_a2dp_codec_bits_per_sample_dialog_title (2096170505745650345) -->
+ <skip />
+ <!-- no translation found for bluetooth_select_a2dp_codec_channel_mode (884855779449390540) -->
+ <skip />
+ <!-- no translation found for bluetooth_select_a2dp_codec_channel_mode_dialog_title (4073812880900816325) -->
+ <skip />
+ <!-- no translation found for bluetooth_select_a2dp_codec_ldac_playback_quality (4846872213548295632) -->
+ <skip />
+ <!-- no translation found for bluetooth_select_a2dp_codec_ldac_playback_quality_dialog_title (3940973633342423717) -->
+ <skip />
<string name="wifi_display_certification_summary" msgid="1155182309166746973">"무선 디스플레이 인증서 옵션 표시"</string>
<string name="wifi_verbose_logging_summary" msgid="6615071616111731958">"Wi‑Fi 로깅 수준을 높이고, Wi‑Fi 선택도구에서 SSID RSSI당 값을 표시합니다."</string>
<string name="wifi_aggressive_handover_summary" msgid="6328455667642570371">"사용 설정하면 Wi-Fi 신호가 약할 때 데이터 연결을 Wi-Fi에서 데이터 네트워크로 더욱 적극적으로 핸드오버합니다."</string>
diff --git a/packages/SettingsLib/res/values-ky-rKG/arrays.xml b/packages/SettingsLib/res/values-ky-rKG/arrays.xml
index 1aadb9b..b84a284 100644
--- a/packages/SettingsLib/res/values-ky-rKG/arrays.xml
+++ b/packages/SettingsLib/res/values-ky-rKG/arrays.xml
@@ -58,6 +58,46 @@
<item msgid="3878793616631049349">"HDCP текшерүү DRM мазмунуна гана колдонулсун"</item>
<item msgid="45075631231212732">"Ар дайым HDCP текшерүү колдонулсун"</item>
</string-array>
+ <!-- no translation found for bluetooth_a2dp_codec_titles:0 (1852387125374225729) -->
+ <!-- no translation found for bluetooth_a2dp_codec_titles:1 (7539690996561263909) -->
+ <!-- no translation found for bluetooth_a2dp_codec_titles:2 (4260844283202960798) -->
+ <!-- no translation found for bluetooth_a2dp_codec_titles:3 (7279983368484312990) -->
+ <!-- no translation found for bluetooth_a2dp_codec_titles:4 (2301339338870319651) -->
+ <!-- no translation found for bluetooth_a2dp_codec_summaries:0 (9072025520360316957) -->
+ <!-- no translation found for bluetooth_a2dp_codec_summaries:1 (6898329690939802290) -->
+ <!-- no translation found for bluetooth_a2dp_codec_summaries:2 (1190434429082395888) -->
+ <!-- no translation found for bluetooth_a2dp_codec_summaries:3 (649699003004233053) -->
+ <!-- no translation found for bluetooth_a2dp_codec_summaries:4 (508106435710925399) -->
+ <!-- no translation found for bluetooth_a2dp_codec_sample_rate_titles:0 (7102940318360468759) -->
+ <!-- no translation found for bluetooth_a2dp_codec_sample_rate_titles:1 (8895532488906185219) -->
+ <!-- no translation found for bluetooth_a2dp_codec_sample_rate_titles:2 (2909915718994807056) -->
+ <!-- no translation found for bluetooth_a2dp_codec_sample_rate_titles:3 (3347287377354164611) -->
+ <!-- no translation found for bluetooth_a2dp_codec_sample_rate_titles:4 (1234212100239985373) -->
+ <!-- no translation found for bluetooth_a2dp_codec_sample_rate_summaries:0 (7224433008148687313) -->
+ <!-- no translation found for bluetooth_a2dp_codec_sample_rate_summaries:1 (4482862757811638365) -->
+ <!-- no translation found for bluetooth_a2dp_codec_sample_rate_summaries:2 (354495328188724404) -->
+ <!-- no translation found for bluetooth_a2dp_codec_sample_rate_summaries:3 (7329816882213695083) -->
+ <!-- no translation found for bluetooth_a2dp_codec_sample_rate_summaries:4 (6967397666254430476) -->
+ <!-- no translation found for bluetooth_a2dp_codec_bits_per_sample_titles:0 (6694044160540313386) -->
+ <!-- no translation found for bluetooth_a2dp_codec_bits_per_sample_titles:1 (5618929009984956469) -->
+ <!-- no translation found for bluetooth_a2dp_codec_bits_per_sample_titles:2 (3412640499234627248) -->
+ <!-- no translation found for bluetooth_a2dp_codec_bits_per_sample_titles:3 (121583001492929387) -->
+ <!-- no translation found for bluetooth_a2dp_codec_bits_per_sample_summaries:0 (5091076677792306320) -->
+ <!-- no translation found for bluetooth_a2dp_codec_bits_per_sample_summaries:1 (4726688794884191540) -->
+ <!-- no translation found for bluetooth_a2dp_codec_bits_per_sample_summaries:2 (305344756485516870) -->
+ <!-- no translation found for bluetooth_a2dp_codec_bits_per_sample_summaries:3 (244568657919675099) -->
+ <!-- no translation found for bluetooth_a2dp_codec_channel_mode_titles:0 (13423709606339855) -->
+ <!-- no translation found for bluetooth_a2dp_codec_channel_mode_titles:1 (4106832974775067314) -->
+ <!-- no translation found for bluetooth_a2dp_codec_channel_mode_titles:2 (5571632958424639155) -->
+ <!-- no translation found for bluetooth_a2dp_codec_channel_mode_summaries:0 (8128478683963250130) -->
+ <!-- no translation found for bluetooth_a2dp_codec_channel_mode_summaries:1 (8900559293912978337) -->
+ <!-- no translation found for bluetooth_a2dp_codec_channel_mode_summaries:2 (8883739882299884241) -->
+ <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_titles:0 (2944889121850394020) -->
+ <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_titles:1 (138837449700903545) -->
+ <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_titles:2 (4777177307869441982) -->
+ <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_summaries:0 (172302906231378902) -->
+ <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_summaries:1 (9091111147684472529) -->
+ <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_summaries:2 (3367904477834831032) -->
<string-array name="select_logd_size_titles">
<item msgid="8665206199209698501">"Өчүк"</item>
<item msgid="1593289376502312923">"64K"</item>
diff --git a/packages/SettingsLib/res/values-ky-rKG/strings.xml b/packages/SettingsLib/res/values-ky-rKG/strings.xml
index 3783cce..6cac03f7 100644
--- a/packages/SettingsLib/res/values-ky-rKG/strings.xml
+++ b/packages/SettingsLib/res/values-ky-rKG/strings.xml
@@ -170,6 +170,26 @@
<string name="wifi_allow_scan_with_traffic" msgid="3601853081178265786">"Wi-Fi Роуминг Скандоо мүмкүнчүлүгүнө ар дайым уруксат берилсин"</string>
<string name="mobile_data_always_on" msgid="7745605759775320362">"Уюлдук дайындар ар дайым активдүү"</string>
<string name="bluetooth_disable_absolute_volume" msgid="2660673801947898809">"Үндүн абсолюттук деңгээли өчүрүлсүн"</string>
+ <!-- no translation found for bluetooth_select_a2dp_codec_type (90597356942154882) -->
+ <skip />
+ <!-- no translation found for bluetooth_select_a2dp_codec_type_dialog_title (6470824182074383881) -->
+ <skip />
+ <!-- no translation found for bluetooth_select_a2dp_codec_sample_rate (4788245703824623062) -->
+ <skip />
+ <!-- no translation found for bluetooth_select_a2dp_codec_sample_rate_dialog_title (4263851572248033749) -->
+ <skip />
+ <!-- no translation found for bluetooth_select_a2dp_codec_bits_per_sample (2099645202720164141) -->
+ <skip />
+ <!-- no translation found for bluetooth_select_a2dp_codec_bits_per_sample_dialog_title (2096170505745650345) -->
+ <skip />
+ <!-- no translation found for bluetooth_select_a2dp_codec_channel_mode (884855779449390540) -->
+ <skip />
+ <!-- no translation found for bluetooth_select_a2dp_codec_channel_mode_dialog_title (4073812880900816325) -->
+ <skip />
+ <!-- no translation found for bluetooth_select_a2dp_codec_ldac_playback_quality (4846872213548295632) -->
+ <skip />
+ <!-- no translation found for bluetooth_select_a2dp_codec_ldac_playback_quality_dialog_title (3940973633342423717) -->
+ <skip />
<string name="wifi_display_certification_summary" msgid="1155182309166746973">"Зымсыз дисплейди сертификатто мүмкүнчүлүктөрүн көргөзүү"</string>
<string name="wifi_verbose_logging_summary" msgid="6615071616111731958">"Wi-Fi Кармагычта Wi‑Fi протокол деңгээлин жогорулатуу жана ар бир SSID RSSI үчүн көрсөтүү."</string>
<string name="wifi_aggressive_handover_summary" msgid="6328455667642570371">"Иштетилгенде, Wi-Fi байланышы үзүл-кесил болуп жатканда, Wi-Fi дайындарды уюктук операторго өжөрлүк менен өткөрөт."</string>
diff --git a/packages/SettingsLib/res/values-lo-rLA/arrays.xml b/packages/SettingsLib/res/values-lo-rLA/arrays.xml
index a003655..f59377d 100644
--- a/packages/SettingsLib/res/values-lo-rLA/arrays.xml
+++ b/packages/SettingsLib/res/values-lo-rLA/arrays.xml
@@ -58,6 +58,46 @@
<item msgid="3878793616631049349">"ໃຊ້ການກວດສອບ HDCP ສຳລັບເນື້ອຫາ DRM ເທົ່ານັ້ນ"</item>
<item msgid="45075631231212732">"ໃຊ້ການກວດສອບ HDCP ສະເໝີ"</item>
</string-array>
+ <!-- no translation found for bluetooth_a2dp_codec_titles:0 (1852387125374225729) -->
+ <!-- no translation found for bluetooth_a2dp_codec_titles:1 (7539690996561263909) -->
+ <!-- no translation found for bluetooth_a2dp_codec_titles:2 (4260844283202960798) -->
+ <!-- no translation found for bluetooth_a2dp_codec_titles:3 (7279983368484312990) -->
+ <!-- no translation found for bluetooth_a2dp_codec_titles:4 (2301339338870319651) -->
+ <!-- no translation found for bluetooth_a2dp_codec_summaries:0 (9072025520360316957) -->
+ <!-- no translation found for bluetooth_a2dp_codec_summaries:1 (6898329690939802290) -->
+ <!-- no translation found for bluetooth_a2dp_codec_summaries:2 (1190434429082395888) -->
+ <!-- no translation found for bluetooth_a2dp_codec_summaries:3 (649699003004233053) -->
+ <!-- no translation found for bluetooth_a2dp_codec_summaries:4 (508106435710925399) -->
+ <!-- no translation found for bluetooth_a2dp_codec_sample_rate_titles:0 (7102940318360468759) -->
+ <!-- no translation found for bluetooth_a2dp_codec_sample_rate_titles:1 (8895532488906185219) -->
+ <!-- no translation found for bluetooth_a2dp_codec_sample_rate_titles:2 (2909915718994807056) -->
+ <!-- no translation found for bluetooth_a2dp_codec_sample_rate_titles:3 (3347287377354164611) -->
+ <!-- no translation found for bluetooth_a2dp_codec_sample_rate_titles:4 (1234212100239985373) -->
+ <!-- no translation found for bluetooth_a2dp_codec_sample_rate_summaries:0 (7224433008148687313) -->
+ <!-- no translation found for bluetooth_a2dp_codec_sample_rate_summaries:1 (4482862757811638365) -->
+ <!-- no translation found for bluetooth_a2dp_codec_sample_rate_summaries:2 (354495328188724404) -->
+ <!-- no translation found for bluetooth_a2dp_codec_sample_rate_summaries:3 (7329816882213695083) -->
+ <!-- no translation found for bluetooth_a2dp_codec_sample_rate_summaries:4 (6967397666254430476) -->
+ <!-- no translation found for bluetooth_a2dp_codec_bits_per_sample_titles:0 (6694044160540313386) -->
+ <!-- no translation found for bluetooth_a2dp_codec_bits_per_sample_titles:1 (5618929009984956469) -->
+ <!-- no translation found for bluetooth_a2dp_codec_bits_per_sample_titles:2 (3412640499234627248) -->
+ <!-- no translation found for bluetooth_a2dp_codec_bits_per_sample_titles:3 (121583001492929387) -->
+ <!-- no translation found for bluetooth_a2dp_codec_bits_per_sample_summaries:0 (5091076677792306320) -->
+ <!-- no translation found for bluetooth_a2dp_codec_bits_per_sample_summaries:1 (4726688794884191540) -->
+ <!-- no translation found for bluetooth_a2dp_codec_bits_per_sample_summaries:2 (305344756485516870) -->
+ <!-- no translation found for bluetooth_a2dp_codec_bits_per_sample_summaries:3 (244568657919675099) -->
+ <!-- no translation found for bluetooth_a2dp_codec_channel_mode_titles:0 (13423709606339855) -->
+ <!-- no translation found for bluetooth_a2dp_codec_channel_mode_titles:1 (4106832974775067314) -->
+ <!-- no translation found for bluetooth_a2dp_codec_channel_mode_titles:2 (5571632958424639155) -->
+ <!-- no translation found for bluetooth_a2dp_codec_channel_mode_summaries:0 (8128478683963250130) -->
+ <!-- no translation found for bluetooth_a2dp_codec_channel_mode_summaries:1 (8900559293912978337) -->
+ <!-- no translation found for bluetooth_a2dp_codec_channel_mode_summaries:2 (8883739882299884241) -->
+ <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_titles:0 (2944889121850394020) -->
+ <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_titles:1 (138837449700903545) -->
+ <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_titles:2 (4777177307869441982) -->
+ <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_summaries:0 (172302906231378902) -->
+ <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_summaries:1 (9091111147684472529) -->
+ <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_summaries:2 (3367904477834831032) -->
<string-array name="select_logd_size_titles">
<item msgid="8665206199209698501">"ປິດ"</item>
<item msgid="1593289376502312923">"64K"</item>
diff --git a/packages/SettingsLib/res/values-lo-rLA/strings.xml b/packages/SettingsLib/res/values-lo-rLA/strings.xml
index 7b16fd9..dfa6a61 100644
--- a/packages/SettingsLib/res/values-lo-rLA/strings.xml
+++ b/packages/SettingsLib/res/values-lo-rLA/strings.xml
@@ -170,6 +170,26 @@
<string name="wifi_allow_scan_with_traffic" msgid="3601853081178265786">"ອະນຸຍາດການສະແກນການໂຣມ Wi‑Fi ສະເໝີ"</string>
<string name="mobile_data_always_on" msgid="7745605759775320362">"ຂໍ້ມູນມືຖືເປີດຢູ່ສະເໝີ"</string>
<string name="bluetooth_disable_absolute_volume" msgid="2660673801947898809">"ປິດໃຊ້ລະດັບສຽງສົມບູນ"</string>
+ <!-- no translation found for bluetooth_select_a2dp_codec_type (90597356942154882) -->
+ <skip />
+ <!-- no translation found for bluetooth_select_a2dp_codec_type_dialog_title (6470824182074383881) -->
+ <skip />
+ <!-- no translation found for bluetooth_select_a2dp_codec_sample_rate (4788245703824623062) -->
+ <skip />
+ <!-- no translation found for bluetooth_select_a2dp_codec_sample_rate_dialog_title (4263851572248033749) -->
+ <skip />
+ <!-- no translation found for bluetooth_select_a2dp_codec_bits_per_sample (2099645202720164141) -->
+ <skip />
+ <!-- no translation found for bluetooth_select_a2dp_codec_bits_per_sample_dialog_title (2096170505745650345) -->
+ <skip />
+ <!-- no translation found for bluetooth_select_a2dp_codec_channel_mode (884855779449390540) -->
+ <skip />
+ <!-- no translation found for bluetooth_select_a2dp_codec_channel_mode_dialog_title (4073812880900816325) -->
+ <skip />
+ <!-- no translation found for bluetooth_select_a2dp_codec_ldac_playback_quality (4846872213548295632) -->
+ <skip />
+ <!-- no translation found for bluetooth_select_a2dp_codec_ldac_playback_quality_dialog_title (3940973633342423717) -->
+ <skip />
<string name="wifi_display_certification_summary" msgid="1155182309166746973">"ສະແດງໂຕເລືອກສຳລັບການສະແດງການຮັບຮອງລະບົບໄຮ້ສາຍ"</string>
<string name="wifi_verbose_logging_summary" msgid="6615071616111731958">"ເພີ່ມລະດັບການເກັບປະຫວັດ Wi‑Fi, ສະແດງຕໍ່ SSID RSSI ໃນ Wi‑Fi Picker"</string>
<string name="wifi_aggressive_handover_summary" msgid="6328455667642570371">"ເມື່ອເປີດນຳໃຊ້ແລ້ວ, ເຄືອຂ່າຍ Wi-Fi ຈະຖືກປ່ຽນໄປໃຊ້ເຄືອຂ່າຍໂທລະສັບແທນຫາກສັນຍານ Wi-Fi ອ່ອນ"</string>
diff --git a/packages/SettingsLib/res/values-lt/arrays.xml b/packages/SettingsLib/res/values-lt/arrays.xml
index 472365d..532e2f9 100644
--- a/packages/SettingsLib/res/values-lt/arrays.xml
+++ b/packages/SettingsLib/res/values-lt/arrays.xml
@@ -58,6 +58,46 @@
<item msgid="3878793616631049349">"Taikyti HDCP tikrinimą tik DRM turiniui"</item>
<item msgid="45075631231212732">"Visada naudoti HDCP tikrinimą"</item>
</string-array>
+ <!-- no translation found for bluetooth_a2dp_codec_titles:0 (1852387125374225729) -->
+ <!-- no translation found for bluetooth_a2dp_codec_titles:1 (7539690996561263909) -->
+ <!-- no translation found for bluetooth_a2dp_codec_titles:2 (4260844283202960798) -->
+ <!-- no translation found for bluetooth_a2dp_codec_titles:3 (7279983368484312990) -->
+ <!-- no translation found for bluetooth_a2dp_codec_titles:4 (2301339338870319651) -->
+ <!-- no translation found for bluetooth_a2dp_codec_summaries:0 (9072025520360316957) -->
+ <!-- no translation found for bluetooth_a2dp_codec_summaries:1 (6898329690939802290) -->
+ <!-- no translation found for bluetooth_a2dp_codec_summaries:2 (1190434429082395888) -->
+ <!-- no translation found for bluetooth_a2dp_codec_summaries:3 (649699003004233053) -->
+ <!-- no translation found for bluetooth_a2dp_codec_summaries:4 (508106435710925399) -->
+ <!-- no translation found for bluetooth_a2dp_codec_sample_rate_titles:0 (7102940318360468759) -->
+ <!-- no translation found for bluetooth_a2dp_codec_sample_rate_titles:1 (8895532488906185219) -->
+ <!-- no translation found for bluetooth_a2dp_codec_sample_rate_titles:2 (2909915718994807056) -->
+ <!-- no translation found for bluetooth_a2dp_codec_sample_rate_titles:3 (3347287377354164611) -->
+ <!-- no translation found for bluetooth_a2dp_codec_sample_rate_titles:4 (1234212100239985373) -->
+ <!-- no translation found for bluetooth_a2dp_codec_sample_rate_summaries:0 (7224433008148687313) -->
+ <!-- no translation found for bluetooth_a2dp_codec_sample_rate_summaries:1 (4482862757811638365) -->
+ <!-- no translation found for bluetooth_a2dp_codec_sample_rate_summaries:2 (354495328188724404) -->
+ <!-- no translation found for bluetooth_a2dp_codec_sample_rate_summaries:3 (7329816882213695083) -->
+ <!-- no translation found for bluetooth_a2dp_codec_sample_rate_summaries:4 (6967397666254430476) -->
+ <!-- no translation found for bluetooth_a2dp_codec_bits_per_sample_titles:0 (6694044160540313386) -->
+ <!-- no translation found for bluetooth_a2dp_codec_bits_per_sample_titles:1 (5618929009984956469) -->
+ <!-- no translation found for bluetooth_a2dp_codec_bits_per_sample_titles:2 (3412640499234627248) -->
+ <!-- no translation found for bluetooth_a2dp_codec_bits_per_sample_titles:3 (121583001492929387) -->
+ <!-- no translation found for bluetooth_a2dp_codec_bits_per_sample_summaries:0 (5091076677792306320) -->
+ <!-- no translation found for bluetooth_a2dp_codec_bits_per_sample_summaries:1 (4726688794884191540) -->
+ <!-- no translation found for bluetooth_a2dp_codec_bits_per_sample_summaries:2 (305344756485516870) -->
+ <!-- no translation found for bluetooth_a2dp_codec_bits_per_sample_summaries:3 (244568657919675099) -->
+ <!-- no translation found for bluetooth_a2dp_codec_channel_mode_titles:0 (13423709606339855) -->
+ <!-- no translation found for bluetooth_a2dp_codec_channel_mode_titles:1 (4106832974775067314) -->
+ <!-- no translation found for bluetooth_a2dp_codec_channel_mode_titles:2 (5571632958424639155) -->
+ <!-- no translation found for bluetooth_a2dp_codec_channel_mode_summaries:0 (8128478683963250130) -->
+ <!-- no translation found for bluetooth_a2dp_codec_channel_mode_summaries:1 (8900559293912978337) -->
+ <!-- no translation found for bluetooth_a2dp_codec_channel_mode_summaries:2 (8883739882299884241) -->
+ <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_titles:0 (2944889121850394020) -->
+ <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_titles:1 (138837449700903545) -->
+ <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_titles:2 (4777177307869441982) -->
+ <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_summaries:0 (172302906231378902) -->
+ <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_summaries:1 (9091111147684472529) -->
+ <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_summaries:2 (3367904477834831032) -->
<string-array name="select_logd_size_titles">
<item msgid="8665206199209698501">"Išjungta"</item>
<item msgid="1593289376502312923">"64 KB"</item>
diff --git a/packages/SettingsLib/res/values-lt/strings.xml b/packages/SettingsLib/res/values-lt/strings.xml
index 85e044f..1b57628 100644
--- a/packages/SettingsLib/res/values-lt/strings.xml
+++ b/packages/SettingsLib/res/values-lt/strings.xml
@@ -170,6 +170,26 @@
<string name="wifi_allow_scan_with_traffic" msgid="3601853081178265786">"Visada leisti „Wi-Fi“ tarptiklinio ryšio nuskaitymą"</string>
<string name="mobile_data_always_on" msgid="7745605759775320362">"Korinio ryšio duomenys visada aktyvūs"</string>
<string name="bluetooth_disable_absolute_volume" msgid="2660673801947898809">"Išjungti didžiausią garsą"</string>
+ <!-- no translation found for bluetooth_select_a2dp_codec_type (90597356942154882) -->
+ <skip />
+ <!-- no translation found for bluetooth_select_a2dp_codec_type_dialog_title (6470824182074383881) -->
+ <skip />
+ <!-- no translation found for bluetooth_select_a2dp_codec_sample_rate (4788245703824623062) -->
+ <skip />
+ <!-- no translation found for bluetooth_select_a2dp_codec_sample_rate_dialog_title (4263851572248033749) -->
+ <skip />
+ <!-- no translation found for bluetooth_select_a2dp_codec_bits_per_sample (2099645202720164141) -->
+ <skip />
+ <!-- no translation found for bluetooth_select_a2dp_codec_bits_per_sample_dialog_title (2096170505745650345) -->
+ <skip />
+ <!-- no translation found for bluetooth_select_a2dp_codec_channel_mode (884855779449390540) -->
+ <skip />
+ <!-- no translation found for bluetooth_select_a2dp_codec_channel_mode_dialog_title (4073812880900816325) -->
+ <skip />
+ <!-- no translation found for bluetooth_select_a2dp_codec_ldac_playback_quality (4846872213548295632) -->
+ <skip />
+ <!-- no translation found for bluetooth_select_a2dp_codec_ldac_playback_quality_dialog_title (3940973633342423717) -->
+ <skip />
<string name="wifi_display_certification_summary" msgid="1155182309166746973">"Rodyti belaidžio rodymo sertifikavimo parinktis"</string>
<string name="wifi_verbose_logging_summary" msgid="6615071616111731958">"Padidinti „Wi‑Fi“ įrašymo į žurnalą lygį, rodyti SSID RSSI „Wi-Fi“ rinkiklyje"</string>
<string name="wifi_aggressive_handover_summary" msgid="6328455667642570371">"Jei įgalinta ši parinktis, „Wi‑Fi“ agresyviau perduos duomenų ryšį į mobiliojo ryšio tinklą, kai „Wi‑Fi“ signalas bus silpnas"</string>
diff --git a/packages/SettingsLib/res/values-lv/arrays.xml b/packages/SettingsLib/res/values-lv/arrays.xml
index 7edb745..7bed3fe 100644
--- a/packages/SettingsLib/res/values-lv/arrays.xml
+++ b/packages/SettingsLib/res/values-lv/arrays.xml
@@ -58,6 +58,46 @@
<item msgid="3878793616631049349">"Izmantot HDCP pārbaudi tikai DRM saturam"</item>
<item msgid="45075631231212732">"Vienmēr izmantot HDCP pārbaudi"</item>
</string-array>
+ <!-- no translation found for bluetooth_a2dp_codec_titles:0 (1852387125374225729) -->
+ <!-- no translation found for bluetooth_a2dp_codec_titles:1 (7539690996561263909) -->
+ <!-- no translation found for bluetooth_a2dp_codec_titles:2 (4260844283202960798) -->
+ <!-- no translation found for bluetooth_a2dp_codec_titles:3 (7279983368484312990) -->
+ <!-- no translation found for bluetooth_a2dp_codec_titles:4 (2301339338870319651) -->
+ <!-- no translation found for bluetooth_a2dp_codec_summaries:0 (9072025520360316957) -->
+ <!-- no translation found for bluetooth_a2dp_codec_summaries:1 (6898329690939802290) -->
+ <!-- no translation found for bluetooth_a2dp_codec_summaries:2 (1190434429082395888) -->
+ <!-- no translation found for bluetooth_a2dp_codec_summaries:3 (649699003004233053) -->
+ <!-- no translation found for bluetooth_a2dp_codec_summaries:4 (508106435710925399) -->
+ <!-- no translation found for bluetooth_a2dp_codec_sample_rate_titles:0 (7102940318360468759) -->
+ <!-- no translation found for bluetooth_a2dp_codec_sample_rate_titles:1 (8895532488906185219) -->
+ <!-- no translation found for bluetooth_a2dp_codec_sample_rate_titles:2 (2909915718994807056) -->
+ <!-- no translation found for bluetooth_a2dp_codec_sample_rate_titles:3 (3347287377354164611) -->
+ <!-- no translation found for bluetooth_a2dp_codec_sample_rate_titles:4 (1234212100239985373) -->
+ <!-- no translation found for bluetooth_a2dp_codec_sample_rate_summaries:0 (7224433008148687313) -->
+ <!-- no translation found for bluetooth_a2dp_codec_sample_rate_summaries:1 (4482862757811638365) -->
+ <!-- no translation found for bluetooth_a2dp_codec_sample_rate_summaries:2 (354495328188724404) -->
+ <!-- no translation found for bluetooth_a2dp_codec_sample_rate_summaries:3 (7329816882213695083) -->
+ <!-- no translation found for bluetooth_a2dp_codec_sample_rate_summaries:4 (6967397666254430476) -->
+ <!-- no translation found for bluetooth_a2dp_codec_bits_per_sample_titles:0 (6694044160540313386) -->
+ <!-- no translation found for bluetooth_a2dp_codec_bits_per_sample_titles:1 (5618929009984956469) -->
+ <!-- no translation found for bluetooth_a2dp_codec_bits_per_sample_titles:2 (3412640499234627248) -->
+ <!-- no translation found for bluetooth_a2dp_codec_bits_per_sample_titles:3 (121583001492929387) -->
+ <!-- no translation found for bluetooth_a2dp_codec_bits_per_sample_summaries:0 (5091076677792306320) -->
+ <!-- no translation found for bluetooth_a2dp_codec_bits_per_sample_summaries:1 (4726688794884191540) -->
+ <!-- no translation found for bluetooth_a2dp_codec_bits_per_sample_summaries:2 (305344756485516870) -->
+ <!-- no translation found for bluetooth_a2dp_codec_bits_per_sample_summaries:3 (244568657919675099) -->
+ <!-- no translation found for bluetooth_a2dp_codec_channel_mode_titles:0 (13423709606339855) -->
+ <!-- no translation found for bluetooth_a2dp_codec_channel_mode_titles:1 (4106832974775067314) -->
+ <!-- no translation found for bluetooth_a2dp_codec_channel_mode_titles:2 (5571632958424639155) -->
+ <!-- no translation found for bluetooth_a2dp_codec_channel_mode_summaries:0 (8128478683963250130) -->
+ <!-- no translation found for bluetooth_a2dp_codec_channel_mode_summaries:1 (8900559293912978337) -->
+ <!-- no translation found for bluetooth_a2dp_codec_channel_mode_summaries:2 (8883739882299884241) -->
+ <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_titles:0 (2944889121850394020) -->
+ <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_titles:1 (138837449700903545) -->
+ <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_titles:2 (4777177307869441982) -->
+ <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_summaries:0 (172302906231378902) -->
+ <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_summaries:1 (9091111147684472529) -->
+ <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_summaries:2 (3367904477834831032) -->
<string-array name="select_logd_size_titles">
<item msgid="8665206199209698501">"Izslēgts"</item>
<item msgid="1593289376502312923">"64 KB"</item>
diff --git a/packages/SettingsLib/res/values-lv/strings.xml b/packages/SettingsLib/res/values-lv/strings.xml
index 36378f2..9ff8870 100644
--- a/packages/SettingsLib/res/values-lv/strings.xml
+++ b/packages/SettingsLib/res/values-lv/strings.xml
@@ -170,6 +170,26 @@
<string name="wifi_allow_scan_with_traffic" msgid="3601853081178265786">"Vienmēr atļaut Wi‑Fi meklēšanu"</string>
<string name="mobile_data_always_on" msgid="7745605759775320362">"Vienmēr aktīvs mobilo datu savienojums"</string>
<string name="bluetooth_disable_absolute_volume" msgid="2660673801947898809">"Atspējot absolūto skaļumu"</string>
+ <!-- no translation found for bluetooth_select_a2dp_codec_type (90597356942154882) -->
+ <skip />
+ <!-- no translation found for bluetooth_select_a2dp_codec_type_dialog_title (6470824182074383881) -->
+ <skip />
+ <!-- no translation found for bluetooth_select_a2dp_codec_sample_rate (4788245703824623062) -->
+ <skip />
+ <!-- no translation found for bluetooth_select_a2dp_codec_sample_rate_dialog_title (4263851572248033749) -->
+ <skip />
+ <!-- no translation found for bluetooth_select_a2dp_codec_bits_per_sample (2099645202720164141) -->
+ <skip />
+ <!-- no translation found for bluetooth_select_a2dp_codec_bits_per_sample_dialog_title (2096170505745650345) -->
+ <skip />
+ <!-- no translation found for bluetooth_select_a2dp_codec_channel_mode (884855779449390540) -->
+ <skip />
+ <!-- no translation found for bluetooth_select_a2dp_codec_channel_mode_dialog_title (4073812880900816325) -->
+ <skip />
+ <!-- no translation found for bluetooth_select_a2dp_codec_ldac_playback_quality (4846872213548295632) -->
+ <skip />
+ <!-- no translation found for bluetooth_select_a2dp_codec_ldac_playback_quality_dialog_title (3940973633342423717) -->
+ <skip />
<string name="wifi_display_certification_summary" msgid="1155182309166746973">"Rādīt bezvadu attēlošanas sertifikācijas iespējas"</string>
<string name="wifi_verbose_logging_summary" msgid="6615071616111731958">"Palieliniet Wi‑Fi reģistrēšanas līmeni; rādīt katram SSID RSSI Wi‑Fi atlasītājā."</string>
<string name="wifi_aggressive_handover_summary" msgid="6328455667642570371">"Ja opcija ir iespējota un Wi‑Fi signāls ir vājš, datu savienojuma pāreja no Wi-Fi uz mobilo tīklu tiks veikta agresīvāk."</string>
diff --git a/packages/SettingsLib/res/values-mk-rMK/arrays.xml b/packages/SettingsLib/res/values-mk-rMK/arrays.xml
index 48d4dca..f26f9d8 100644
--- a/packages/SettingsLib/res/values-mk-rMK/arrays.xml
+++ b/packages/SettingsLib/res/values-mk-rMK/arrays.xml
@@ -58,6 +58,46 @@
<item msgid="3878793616631049349">"Користи ХДЦП проверка само за ДРМ содржина"</item>
<item msgid="45075631231212732">"Секогаш користи ХДЦП проверка"</item>
</string-array>
+ <!-- no translation found for bluetooth_a2dp_codec_titles:0 (1852387125374225729) -->
+ <!-- no translation found for bluetooth_a2dp_codec_titles:1 (7539690996561263909) -->
+ <!-- no translation found for bluetooth_a2dp_codec_titles:2 (4260844283202960798) -->
+ <!-- no translation found for bluetooth_a2dp_codec_titles:3 (7279983368484312990) -->
+ <!-- no translation found for bluetooth_a2dp_codec_titles:4 (2301339338870319651) -->
+ <!-- no translation found for bluetooth_a2dp_codec_summaries:0 (9072025520360316957) -->
+ <!-- no translation found for bluetooth_a2dp_codec_summaries:1 (6898329690939802290) -->
+ <!-- no translation found for bluetooth_a2dp_codec_summaries:2 (1190434429082395888) -->
+ <!-- no translation found for bluetooth_a2dp_codec_summaries:3 (649699003004233053) -->
+ <!-- no translation found for bluetooth_a2dp_codec_summaries:4 (508106435710925399) -->
+ <!-- no translation found for bluetooth_a2dp_codec_sample_rate_titles:0 (7102940318360468759) -->
+ <!-- no translation found for bluetooth_a2dp_codec_sample_rate_titles:1 (8895532488906185219) -->
+ <!-- no translation found for bluetooth_a2dp_codec_sample_rate_titles:2 (2909915718994807056) -->
+ <!-- no translation found for bluetooth_a2dp_codec_sample_rate_titles:3 (3347287377354164611) -->
+ <!-- no translation found for bluetooth_a2dp_codec_sample_rate_titles:4 (1234212100239985373) -->
+ <!-- no translation found for bluetooth_a2dp_codec_sample_rate_summaries:0 (7224433008148687313) -->
+ <!-- no translation found for bluetooth_a2dp_codec_sample_rate_summaries:1 (4482862757811638365) -->
+ <!-- no translation found for bluetooth_a2dp_codec_sample_rate_summaries:2 (354495328188724404) -->
+ <!-- no translation found for bluetooth_a2dp_codec_sample_rate_summaries:3 (7329816882213695083) -->
+ <!-- no translation found for bluetooth_a2dp_codec_sample_rate_summaries:4 (6967397666254430476) -->
+ <!-- no translation found for bluetooth_a2dp_codec_bits_per_sample_titles:0 (6694044160540313386) -->
+ <!-- no translation found for bluetooth_a2dp_codec_bits_per_sample_titles:1 (5618929009984956469) -->
+ <!-- no translation found for bluetooth_a2dp_codec_bits_per_sample_titles:2 (3412640499234627248) -->
+ <!-- no translation found for bluetooth_a2dp_codec_bits_per_sample_titles:3 (121583001492929387) -->
+ <!-- no translation found for bluetooth_a2dp_codec_bits_per_sample_summaries:0 (5091076677792306320) -->
+ <!-- no translation found for bluetooth_a2dp_codec_bits_per_sample_summaries:1 (4726688794884191540) -->
+ <!-- no translation found for bluetooth_a2dp_codec_bits_per_sample_summaries:2 (305344756485516870) -->
+ <!-- no translation found for bluetooth_a2dp_codec_bits_per_sample_summaries:3 (244568657919675099) -->
+ <!-- no translation found for bluetooth_a2dp_codec_channel_mode_titles:0 (13423709606339855) -->
+ <!-- no translation found for bluetooth_a2dp_codec_channel_mode_titles:1 (4106832974775067314) -->
+ <!-- no translation found for bluetooth_a2dp_codec_channel_mode_titles:2 (5571632958424639155) -->
+ <!-- no translation found for bluetooth_a2dp_codec_channel_mode_summaries:0 (8128478683963250130) -->
+ <!-- no translation found for bluetooth_a2dp_codec_channel_mode_summaries:1 (8900559293912978337) -->
+ <!-- no translation found for bluetooth_a2dp_codec_channel_mode_summaries:2 (8883739882299884241) -->
+ <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_titles:0 (2944889121850394020) -->
+ <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_titles:1 (138837449700903545) -->
+ <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_titles:2 (4777177307869441982) -->
+ <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_summaries:0 (172302906231378902) -->
+ <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_summaries:1 (9091111147684472529) -->
+ <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_summaries:2 (3367904477834831032) -->
<string-array name="select_logd_size_titles">
<item msgid="8665206199209698501">"Исклучено"</item>
<item msgid="1593289376502312923">"64.000"</item>
diff --git a/packages/SettingsLib/res/values-mk-rMK/strings.xml b/packages/SettingsLib/res/values-mk-rMK/strings.xml
index ebe8d00..7422828 100644
--- a/packages/SettingsLib/res/values-mk-rMK/strings.xml
+++ b/packages/SettingsLib/res/values-mk-rMK/strings.xml
@@ -170,6 +170,26 @@
<string name="wifi_allow_scan_with_traffic" msgid="3601853081178265786">"Секогаш дозволувај Wi‑Fi скенирање во роаминг"</string>
<string name="mobile_data_always_on" msgid="7745605759775320362">"Мобилниот интернет е секогаш активен"</string>
<string name="bluetooth_disable_absolute_volume" msgid="2660673801947898809">"Оневозможете апсолутна јачина на звук"</string>
+ <!-- no translation found for bluetooth_select_a2dp_codec_type (90597356942154882) -->
+ <skip />
+ <!-- no translation found for bluetooth_select_a2dp_codec_type_dialog_title (6470824182074383881) -->
+ <skip />
+ <!-- no translation found for bluetooth_select_a2dp_codec_sample_rate (4788245703824623062) -->
+ <skip />
+ <!-- no translation found for bluetooth_select_a2dp_codec_sample_rate_dialog_title (4263851572248033749) -->
+ <skip />
+ <!-- no translation found for bluetooth_select_a2dp_codec_bits_per_sample (2099645202720164141) -->
+ <skip />
+ <!-- no translation found for bluetooth_select_a2dp_codec_bits_per_sample_dialog_title (2096170505745650345) -->
+ <skip />
+ <!-- no translation found for bluetooth_select_a2dp_codec_channel_mode (884855779449390540) -->
+ <skip />
+ <!-- no translation found for bluetooth_select_a2dp_codec_channel_mode_dialog_title (4073812880900816325) -->
+ <skip />
+ <!-- no translation found for bluetooth_select_a2dp_codec_ldac_playback_quality (4846872213548295632) -->
+ <skip />
+ <!-- no translation found for bluetooth_select_a2dp_codec_ldac_playback_quality_dialog_title (3940973633342423717) -->
+ <skip />
<string name="wifi_display_certification_summary" msgid="1155182309166746973">"Покажи ги опциите за безжичен приказ на сертификат"</string>
<string name="wifi_verbose_logging_summary" msgid="6615071616111731958">"Зголеми Wi‑Fi ниво на пријавување, прикажи по SSID RSSI во Wi‑Fi бирач"</string>
<string name="wifi_aggressive_handover_summary" msgid="6328455667642570371">"Кога е вклучено, Wi-Fi ќе биде поагресивно при предавање на поврзувањето со податоци на мобилната мрежа при слаб сигнал на Wi-Fi."</string>
diff --git a/packages/SettingsLib/res/values-ml-rIN/arrays.xml b/packages/SettingsLib/res/values-ml-rIN/arrays.xml
index f8cc582..b3891cc 100644
--- a/packages/SettingsLib/res/values-ml-rIN/arrays.xml
+++ b/packages/SettingsLib/res/values-ml-rIN/arrays.xml
@@ -58,6 +58,46 @@
<item msgid="3878793616631049349">"DRM ഉള്ളടക്കത്തിനുമാത്രമായി HDCP പരിശോധന ഉപയോഗിക്കുക"</item>
<item msgid="45075631231212732">"എല്ലായ്പ്പോഴും HDCP പരിശോധന ഉപയോഗിക്കുക"</item>
</string-array>
+ <!-- no translation found for bluetooth_a2dp_codec_titles:0 (1852387125374225729) -->
+ <!-- no translation found for bluetooth_a2dp_codec_titles:1 (7539690996561263909) -->
+ <!-- no translation found for bluetooth_a2dp_codec_titles:2 (4260844283202960798) -->
+ <!-- no translation found for bluetooth_a2dp_codec_titles:3 (7279983368484312990) -->
+ <!-- no translation found for bluetooth_a2dp_codec_titles:4 (2301339338870319651) -->
+ <!-- no translation found for bluetooth_a2dp_codec_summaries:0 (9072025520360316957) -->
+ <!-- no translation found for bluetooth_a2dp_codec_summaries:1 (6898329690939802290) -->
+ <!-- no translation found for bluetooth_a2dp_codec_summaries:2 (1190434429082395888) -->
+ <!-- no translation found for bluetooth_a2dp_codec_summaries:3 (649699003004233053) -->
+ <!-- no translation found for bluetooth_a2dp_codec_summaries:4 (508106435710925399) -->
+ <!-- no translation found for bluetooth_a2dp_codec_sample_rate_titles:0 (7102940318360468759) -->
+ <!-- no translation found for bluetooth_a2dp_codec_sample_rate_titles:1 (8895532488906185219) -->
+ <!-- no translation found for bluetooth_a2dp_codec_sample_rate_titles:2 (2909915718994807056) -->
+ <!-- no translation found for bluetooth_a2dp_codec_sample_rate_titles:3 (3347287377354164611) -->
+ <!-- no translation found for bluetooth_a2dp_codec_sample_rate_titles:4 (1234212100239985373) -->
+ <!-- no translation found for bluetooth_a2dp_codec_sample_rate_summaries:0 (7224433008148687313) -->
+ <!-- no translation found for bluetooth_a2dp_codec_sample_rate_summaries:1 (4482862757811638365) -->
+ <!-- no translation found for bluetooth_a2dp_codec_sample_rate_summaries:2 (354495328188724404) -->
+ <!-- no translation found for bluetooth_a2dp_codec_sample_rate_summaries:3 (7329816882213695083) -->
+ <!-- no translation found for bluetooth_a2dp_codec_sample_rate_summaries:4 (6967397666254430476) -->
+ <!-- no translation found for bluetooth_a2dp_codec_bits_per_sample_titles:0 (6694044160540313386) -->
+ <!-- no translation found for bluetooth_a2dp_codec_bits_per_sample_titles:1 (5618929009984956469) -->
+ <!-- no translation found for bluetooth_a2dp_codec_bits_per_sample_titles:2 (3412640499234627248) -->
+ <!-- no translation found for bluetooth_a2dp_codec_bits_per_sample_titles:3 (121583001492929387) -->
+ <!-- no translation found for bluetooth_a2dp_codec_bits_per_sample_summaries:0 (5091076677792306320) -->
+ <!-- no translation found for bluetooth_a2dp_codec_bits_per_sample_summaries:1 (4726688794884191540) -->
+ <!-- no translation found for bluetooth_a2dp_codec_bits_per_sample_summaries:2 (305344756485516870) -->
+ <!-- no translation found for bluetooth_a2dp_codec_bits_per_sample_summaries:3 (244568657919675099) -->
+ <!-- no translation found for bluetooth_a2dp_codec_channel_mode_titles:0 (13423709606339855) -->
+ <!-- no translation found for bluetooth_a2dp_codec_channel_mode_titles:1 (4106832974775067314) -->
+ <!-- no translation found for bluetooth_a2dp_codec_channel_mode_titles:2 (5571632958424639155) -->
+ <!-- no translation found for bluetooth_a2dp_codec_channel_mode_summaries:0 (8128478683963250130) -->
+ <!-- no translation found for bluetooth_a2dp_codec_channel_mode_summaries:1 (8900559293912978337) -->
+ <!-- no translation found for bluetooth_a2dp_codec_channel_mode_summaries:2 (8883739882299884241) -->
+ <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_titles:0 (2944889121850394020) -->
+ <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_titles:1 (138837449700903545) -->
+ <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_titles:2 (4777177307869441982) -->
+ <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_summaries:0 (172302906231378902) -->
+ <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_summaries:1 (9091111147684472529) -->
+ <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_summaries:2 (3367904477834831032) -->
<string-array name="select_logd_size_titles">
<item msgid="8665206199209698501">"ഓഫ്"</item>
<item msgid="1593289376502312923">"64K"</item>
diff --git a/packages/SettingsLib/res/values-ml-rIN/strings.xml b/packages/SettingsLib/res/values-ml-rIN/strings.xml
index 09c07ea..5cf8330 100644
--- a/packages/SettingsLib/res/values-ml-rIN/strings.xml
+++ b/packages/SettingsLib/res/values-ml-rIN/strings.xml
@@ -170,6 +170,26 @@
<string name="wifi_allow_scan_with_traffic" msgid="3601853081178265786">"എപ്പോഴും വൈഫൈ റോം സ്കാൻ അനുവദിക്കൂ"</string>
<string name="mobile_data_always_on" msgid="7745605759775320362">"സെല്ലുലാർ ഡാറ്റ എല്ലായ്പ്പോഴും സജീവം"</string>
<string name="bluetooth_disable_absolute_volume" msgid="2660673801947898809">"അബ്സൊല്യൂട്ട് വോളിയം പ്രവർത്തനരഹിതമാക്കുക"</string>
+ <!-- no translation found for bluetooth_select_a2dp_codec_type (90597356942154882) -->
+ <skip />
+ <!-- no translation found for bluetooth_select_a2dp_codec_type_dialog_title (6470824182074383881) -->
+ <skip />
+ <!-- no translation found for bluetooth_select_a2dp_codec_sample_rate (4788245703824623062) -->
+ <skip />
+ <!-- no translation found for bluetooth_select_a2dp_codec_sample_rate_dialog_title (4263851572248033749) -->
+ <skip />
+ <!-- no translation found for bluetooth_select_a2dp_codec_bits_per_sample (2099645202720164141) -->
+ <skip />
+ <!-- no translation found for bluetooth_select_a2dp_codec_bits_per_sample_dialog_title (2096170505745650345) -->
+ <skip />
+ <!-- no translation found for bluetooth_select_a2dp_codec_channel_mode (884855779449390540) -->
+ <skip />
+ <!-- no translation found for bluetooth_select_a2dp_codec_channel_mode_dialog_title (4073812880900816325) -->
+ <skip />
+ <!-- no translation found for bluetooth_select_a2dp_codec_ldac_playback_quality (4846872213548295632) -->
+ <skip />
+ <!-- no translation found for bluetooth_select_a2dp_codec_ldac_playback_quality_dialog_title (3940973633342423717) -->
+ <skip />
<string name="wifi_display_certification_summary" msgid="1155182309166746973">"വയർലെസ് ഡിസ്പ്ലേ സർട്ടിഫിക്കേഷനായി ഓപ്ഷനുകൾ ദൃശ്യമാക്കുക"</string>
<string name="wifi_verbose_logging_summary" msgid="6615071616111731958">"വൈഫൈ പിക്കറിൽ ഓരോ SSID RSSI പ്രകാരം കാണിക്കാൻ വൈഫൈ ലോഗിംഗ് നില വർദ്ധിപ്പിക്കുക"</string>
<string name="wifi_aggressive_handover_summary" msgid="6328455667642570371">"പ്രവർത്തനക്ഷമമായിരിക്കുമ്പോൾ, വൈഫൈ സിഗ്നൽ കുറവായിരിക്കുന്ന സമയത്ത് സെല്ലുലാറിലേക്ക് ഡാറ്റ കണക്ഷൻ മുഖേന കൈമാറുന്നതിൽ വൈഫൈ കൂടുതൽ പ്രവർത്തനക്ഷമമാകും"</string>
diff --git a/packages/SettingsLib/res/values-mn-rMN/arrays.xml b/packages/SettingsLib/res/values-mn-rMN/arrays.xml
index 60fe502..224fa2c 100644
--- a/packages/SettingsLib/res/values-mn-rMN/arrays.xml
+++ b/packages/SettingsLib/res/values-mn-rMN/arrays.xml
@@ -58,6 +58,46 @@
<item msgid="3878793616631049349">"HDCP шалгахыг зөвхөн DRM контентэд ашиглах"</item>
<item msgid="45075631231212732">"Байнга HDCP шалгахыг ашиглах"</item>
</string-array>
+ <!-- no translation found for bluetooth_a2dp_codec_titles:0 (1852387125374225729) -->
+ <!-- no translation found for bluetooth_a2dp_codec_titles:1 (7539690996561263909) -->
+ <!-- no translation found for bluetooth_a2dp_codec_titles:2 (4260844283202960798) -->
+ <!-- no translation found for bluetooth_a2dp_codec_titles:3 (7279983368484312990) -->
+ <!-- no translation found for bluetooth_a2dp_codec_titles:4 (2301339338870319651) -->
+ <!-- no translation found for bluetooth_a2dp_codec_summaries:0 (9072025520360316957) -->
+ <!-- no translation found for bluetooth_a2dp_codec_summaries:1 (6898329690939802290) -->
+ <!-- no translation found for bluetooth_a2dp_codec_summaries:2 (1190434429082395888) -->
+ <!-- no translation found for bluetooth_a2dp_codec_summaries:3 (649699003004233053) -->
+ <!-- no translation found for bluetooth_a2dp_codec_summaries:4 (508106435710925399) -->
+ <!-- no translation found for bluetooth_a2dp_codec_sample_rate_titles:0 (7102940318360468759) -->
+ <!-- no translation found for bluetooth_a2dp_codec_sample_rate_titles:1 (8895532488906185219) -->
+ <!-- no translation found for bluetooth_a2dp_codec_sample_rate_titles:2 (2909915718994807056) -->
+ <!-- no translation found for bluetooth_a2dp_codec_sample_rate_titles:3 (3347287377354164611) -->
+ <!-- no translation found for bluetooth_a2dp_codec_sample_rate_titles:4 (1234212100239985373) -->
+ <!-- no translation found for bluetooth_a2dp_codec_sample_rate_summaries:0 (7224433008148687313) -->
+ <!-- no translation found for bluetooth_a2dp_codec_sample_rate_summaries:1 (4482862757811638365) -->
+ <!-- no translation found for bluetooth_a2dp_codec_sample_rate_summaries:2 (354495328188724404) -->
+ <!-- no translation found for bluetooth_a2dp_codec_sample_rate_summaries:3 (7329816882213695083) -->
+ <!-- no translation found for bluetooth_a2dp_codec_sample_rate_summaries:4 (6967397666254430476) -->
+ <!-- no translation found for bluetooth_a2dp_codec_bits_per_sample_titles:0 (6694044160540313386) -->
+ <!-- no translation found for bluetooth_a2dp_codec_bits_per_sample_titles:1 (5618929009984956469) -->
+ <!-- no translation found for bluetooth_a2dp_codec_bits_per_sample_titles:2 (3412640499234627248) -->
+ <!-- no translation found for bluetooth_a2dp_codec_bits_per_sample_titles:3 (121583001492929387) -->
+ <!-- no translation found for bluetooth_a2dp_codec_bits_per_sample_summaries:0 (5091076677792306320) -->
+ <!-- no translation found for bluetooth_a2dp_codec_bits_per_sample_summaries:1 (4726688794884191540) -->
+ <!-- no translation found for bluetooth_a2dp_codec_bits_per_sample_summaries:2 (305344756485516870) -->
+ <!-- no translation found for bluetooth_a2dp_codec_bits_per_sample_summaries:3 (244568657919675099) -->
+ <!-- no translation found for bluetooth_a2dp_codec_channel_mode_titles:0 (13423709606339855) -->
+ <!-- no translation found for bluetooth_a2dp_codec_channel_mode_titles:1 (4106832974775067314) -->
+ <!-- no translation found for bluetooth_a2dp_codec_channel_mode_titles:2 (5571632958424639155) -->
+ <!-- no translation found for bluetooth_a2dp_codec_channel_mode_summaries:0 (8128478683963250130) -->
+ <!-- no translation found for bluetooth_a2dp_codec_channel_mode_summaries:1 (8900559293912978337) -->
+ <!-- no translation found for bluetooth_a2dp_codec_channel_mode_summaries:2 (8883739882299884241) -->
+ <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_titles:0 (2944889121850394020) -->
+ <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_titles:1 (138837449700903545) -->
+ <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_titles:2 (4777177307869441982) -->
+ <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_summaries:0 (172302906231378902) -->
+ <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_summaries:1 (9091111147684472529) -->
+ <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_summaries:2 (3367904477834831032) -->
<string-array name="select_logd_size_titles">
<item msgid="8665206199209698501">"Идэвхгүй"</item>
<item msgid="1593289376502312923">"64000"</item>
diff --git a/packages/SettingsLib/res/values-mn-rMN/strings.xml b/packages/SettingsLib/res/values-mn-rMN/strings.xml
index 86a62a2..9ffbca6 100644
--- a/packages/SettingsLib/res/values-mn-rMN/strings.xml
+++ b/packages/SettingsLib/res/values-mn-rMN/strings.xml
@@ -170,6 +170,26 @@
<string name="wifi_allow_scan_with_traffic" msgid="3601853081178265786">"Wi‑Fi Роум сканыг байнга зөвшөөрөх"</string>
<string name="mobile_data_always_on" msgid="7745605759775320362">"Үүрэн холбооны датаг үргэлж идэвхтэй байлгана"</string>
<string name="bluetooth_disable_absolute_volume" msgid="2660673801947898809">"Үнэмлэхүй дууны түвшинг идэвхгүй болгох"</string>
+ <!-- no translation found for bluetooth_select_a2dp_codec_type (90597356942154882) -->
+ <skip />
+ <!-- no translation found for bluetooth_select_a2dp_codec_type_dialog_title (6470824182074383881) -->
+ <skip />
+ <!-- no translation found for bluetooth_select_a2dp_codec_sample_rate (4788245703824623062) -->
+ <skip />
+ <!-- no translation found for bluetooth_select_a2dp_codec_sample_rate_dialog_title (4263851572248033749) -->
+ <skip />
+ <!-- no translation found for bluetooth_select_a2dp_codec_bits_per_sample (2099645202720164141) -->
+ <skip />
+ <!-- no translation found for bluetooth_select_a2dp_codec_bits_per_sample_dialog_title (2096170505745650345) -->
+ <skip />
+ <!-- no translation found for bluetooth_select_a2dp_codec_channel_mode (884855779449390540) -->
+ <skip />
+ <!-- no translation found for bluetooth_select_a2dp_codec_channel_mode_dialog_title (4073812880900816325) -->
+ <skip />
+ <!-- no translation found for bluetooth_select_a2dp_codec_ldac_playback_quality (4846872213548295632) -->
+ <skip />
+ <!-- no translation found for bluetooth_select_a2dp_codec_ldac_playback_quality_dialog_title (3940973633342423717) -->
+ <skip />
<string name="wifi_display_certification_summary" msgid="1155182309166746973">"Утасгүй дэлгэцийн сертификатын сонголтыг харуулах"</string>
<string name="wifi_verbose_logging_summary" msgid="6615071616111731958">"Wi‑Fi лог-н түвшинг нэмэгдүүлэх, Wi‑Fi Сонгогч дээрх SSID-д ногдох RSSI-г харуулах"</string>
<string name="wifi_aggressive_handover_summary" msgid="6328455667642570371">"Идэвхжүүлсэн үед Wi‑Fi дохио сул бол дата холболтыг Үүрэн рүү шилжүүлэхдээ илүү идэвхтэй байх болно"</string>
diff --git a/packages/SettingsLib/res/values-mr-rIN/arrays.xml b/packages/SettingsLib/res/values-mr-rIN/arrays.xml
index f950ba1..0fe9200 100644
--- a/packages/SettingsLib/res/values-mr-rIN/arrays.xml
+++ b/packages/SettingsLib/res/values-mr-rIN/arrays.xml
@@ -58,6 +58,46 @@
<item msgid="3878793616631049349">"केवळ DRM सामग्रीसाठी HDCP तपासणी वापरा"</item>
<item msgid="45075631231212732">"नेहमी HDCP तपासणी वापरा"</item>
</string-array>
+ <!-- no translation found for bluetooth_a2dp_codec_titles:0 (1852387125374225729) -->
+ <!-- no translation found for bluetooth_a2dp_codec_titles:1 (7539690996561263909) -->
+ <!-- no translation found for bluetooth_a2dp_codec_titles:2 (4260844283202960798) -->
+ <!-- no translation found for bluetooth_a2dp_codec_titles:3 (7279983368484312990) -->
+ <!-- no translation found for bluetooth_a2dp_codec_titles:4 (2301339338870319651) -->
+ <!-- no translation found for bluetooth_a2dp_codec_summaries:0 (9072025520360316957) -->
+ <!-- no translation found for bluetooth_a2dp_codec_summaries:1 (6898329690939802290) -->
+ <!-- no translation found for bluetooth_a2dp_codec_summaries:2 (1190434429082395888) -->
+ <!-- no translation found for bluetooth_a2dp_codec_summaries:3 (649699003004233053) -->
+ <!-- no translation found for bluetooth_a2dp_codec_summaries:4 (508106435710925399) -->
+ <!-- no translation found for bluetooth_a2dp_codec_sample_rate_titles:0 (7102940318360468759) -->
+ <!-- no translation found for bluetooth_a2dp_codec_sample_rate_titles:1 (8895532488906185219) -->
+ <!-- no translation found for bluetooth_a2dp_codec_sample_rate_titles:2 (2909915718994807056) -->
+ <!-- no translation found for bluetooth_a2dp_codec_sample_rate_titles:3 (3347287377354164611) -->
+ <!-- no translation found for bluetooth_a2dp_codec_sample_rate_titles:4 (1234212100239985373) -->
+ <!-- no translation found for bluetooth_a2dp_codec_sample_rate_summaries:0 (7224433008148687313) -->
+ <!-- no translation found for bluetooth_a2dp_codec_sample_rate_summaries:1 (4482862757811638365) -->
+ <!-- no translation found for bluetooth_a2dp_codec_sample_rate_summaries:2 (354495328188724404) -->
+ <!-- no translation found for bluetooth_a2dp_codec_sample_rate_summaries:3 (7329816882213695083) -->
+ <!-- no translation found for bluetooth_a2dp_codec_sample_rate_summaries:4 (6967397666254430476) -->
+ <!-- no translation found for bluetooth_a2dp_codec_bits_per_sample_titles:0 (6694044160540313386) -->
+ <!-- no translation found for bluetooth_a2dp_codec_bits_per_sample_titles:1 (5618929009984956469) -->
+ <!-- no translation found for bluetooth_a2dp_codec_bits_per_sample_titles:2 (3412640499234627248) -->
+ <!-- no translation found for bluetooth_a2dp_codec_bits_per_sample_titles:3 (121583001492929387) -->
+ <!-- no translation found for bluetooth_a2dp_codec_bits_per_sample_summaries:0 (5091076677792306320) -->
+ <!-- no translation found for bluetooth_a2dp_codec_bits_per_sample_summaries:1 (4726688794884191540) -->
+ <!-- no translation found for bluetooth_a2dp_codec_bits_per_sample_summaries:2 (305344756485516870) -->
+ <!-- no translation found for bluetooth_a2dp_codec_bits_per_sample_summaries:3 (244568657919675099) -->
+ <!-- no translation found for bluetooth_a2dp_codec_channel_mode_titles:0 (13423709606339855) -->
+ <!-- no translation found for bluetooth_a2dp_codec_channel_mode_titles:1 (4106832974775067314) -->
+ <!-- no translation found for bluetooth_a2dp_codec_channel_mode_titles:2 (5571632958424639155) -->
+ <!-- no translation found for bluetooth_a2dp_codec_channel_mode_summaries:0 (8128478683963250130) -->
+ <!-- no translation found for bluetooth_a2dp_codec_channel_mode_summaries:1 (8900559293912978337) -->
+ <!-- no translation found for bluetooth_a2dp_codec_channel_mode_summaries:2 (8883739882299884241) -->
+ <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_titles:0 (2944889121850394020) -->
+ <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_titles:1 (138837449700903545) -->
+ <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_titles:2 (4777177307869441982) -->
+ <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_summaries:0 (172302906231378902) -->
+ <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_summaries:1 (9091111147684472529) -->
+ <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_summaries:2 (3367904477834831032) -->
<string-array name="select_logd_size_titles">
<item msgid="8665206199209698501">"बंद"</item>
<item msgid="1593289376502312923">"64K"</item>
diff --git a/packages/SettingsLib/res/values-mr-rIN/strings.xml b/packages/SettingsLib/res/values-mr-rIN/strings.xml
index be1fbc6..0680c7c 100644
--- a/packages/SettingsLib/res/values-mr-rIN/strings.xml
+++ b/packages/SettingsLib/res/values-mr-rIN/strings.xml
@@ -170,6 +170,26 @@
<string name="wifi_allow_scan_with_traffic" msgid="3601853081178265786">"वाय-फाय रोम स्कॅनला नेहमी अनुमती द्या"</string>
<string name="mobile_data_always_on" msgid="7745605759775320362">"सेल्युलर डेटा नेहमी सक्रिय"</string>
<string name="bluetooth_disable_absolute_volume" msgid="2660673801947898809">"संपूर्ण आवाज अक्षम करा"</string>
+ <!-- no translation found for bluetooth_select_a2dp_codec_type (90597356942154882) -->
+ <skip />
+ <!-- no translation found for bluetooth_select_a2dp_codec_type_dialog_title (6470824182074383881) -->
+ <skip />
+ <!-- no translation found for bluetooth_select_a2dp_codec_sample_rate (4788245703824623062) -->
+ <skip />
+ <!-- no translation found for bluetooth_select_a2dp_codec_sample_rate_dialog_title (4263851572248033749) -->
+ <skip />
+ <!-- no translation found for bluetooth_select_a2dp_codec_bits_per_sample (2099645202720164141) -->
+ <skip />
+ <!-- no translation found for bluetooth_select_a2dp_codec_bits_per_sample_dialog_title (2096170505745650345) -->
+ <skip />
+ <!-- no translation found for bluetooth_select_a2dp_codec_channel_mode (884855779449390540) -->
+ <skip />
+ <!-- no translation found for bluetooth_select_a2dp_codec_channel_mode_dialog_title (4073812880900816325) -->
+ <skip />
+ <!-- no translation found for bluetooth_select_a2dp_codec_ldac_playback_quality (4846872213548295632) -->
+ <skip />
+ <!-- no translation found for bluetooth_select_a2dp_codec_ldac_playback_quality_dialog_title (3940973633342423717) -->
+ <skip />
<string name="wifi_display_certification_summary" msgid="1155182309166746973">"वायरलेस प्रदर्शन प्रमाणिकरणासाठी पर्याय दर्शवा"</string>
<string name="wifi_verbose_logging_summary" msgid="6615071616111731958">"वाय-फाय लॉगिंग स्तर वाढवा, वाय-फाय निवडकामध्ये प्रति SSID RSSI दर्शवा"</string>
<string name="wifi_aggressive_handover_summary" msgid="6328455667642570371">"सक्षम केल्यास, वाय-फाय सिग्नल निम्न असताना, वाय-फाय डेटा कनेक्शन सेल्युलरवर बळपूर्वक स्विच करेल."</string>
diff --git a/packages/SettingsLib/res/values-ms-rMY/arrays.xml b/packages/SettingsLib/res/values-ms-rMY/arrays.xml
index 07f219c..31c8f48 100644
--- a/packages/SettingsLib/res/values-ms-rMY/arrays.xml
+++ b/packages/SettingsLib/res/values-ms-rMY/arrays.xml
@@ -58,6 +58,46 @@
<item msgid="3878793616631049349">"Gunakan penyemakan HDCP untuk kandungan DRM sahaja"</item>
<item msgid="45075631231212732">"Sentiasa gunakan penyemakan HDCP"</item>
</string-array>
+ <!-- no translation found for bluetooth_a2dp_codec_titles:0 (1852387125374225729) -->
+ <!-- no translation found for bluetooth_a2dp_codec_titles:1 (7539690996561263909) -->
+ <!-- no translation found for bluetooth_a2dp_codec_titles:2 (4260844283202960798) -->
+ <!-- no translation found for bluetooth_a2dp_codec_titles:3 (7279983368484312990) -->
+ <!-- no translation found for bluetooth_a2dp_codec_titles:4 (2301339338870319651) -->
+ <!-- no translation found for bluetooth_a2dp_codec_summaries:0 (9072025520360316957) -->
+ <!-- no translation found for bluetooth_a2dp_codec_summaries:1 (6898329690939802290) -->
+ <!-- no translation found for bluetooth_a2dp_codec_summaries:2 (1190434429082395888) -->
+ <!-- no translation found for bluetooth_a2dp_codec_summaries:3 (649699003004233053) -->
+ <!-- no translation found for bluetooth_a2dp_codec_summaries:4 (508106435710925399) -->
+ <!-- no translation found for bluetooth_a2dp_codec_sample_rate_titles:0 (7102940318360468759) -->
+ <!-- no translation found for bluetooth_a2dp_codec_sample_rate_titles:1 (8895532488906185219) -->
+ <!-- no translation found for bluetooth_a2dp_codec_sample_rate_titles:2 (2909915718994807056) -->
+ <!-- no translation found for bluetooth_a2dp_codec_sample_rate_titles:3 (3347287377354164611) -->
+ <!-- no translation found for bluetooth_a2dp_codec_sample_rate_titles:4 (1234212100239985373) -->
+ <!-- no translation found for bluetooth_a2dp_codec_sample_rate_summaries:0 (7224433008148687313) -->
+ <!-- no translation found for bluetooth_a2dp_codec_sample_rate_summaries:1 (4482862757811638365) -->
+ <!-- no translation found for bluetooth_a2dp_codec_sample_rate_summaries:2 (354495328188724404) -->
+ <!-- no translation found for bluetooth_a2dp_codec_sample_rate_summaries:3 (7329816882213695083) -->
+ <!-- no translation found for bluetooth_a2dp_codec_sample_rate_summaries:4 (6967397666254430476) -->
+ <!-- no translation found for bluetooth_a2dp_codec_bits_per_sample_titles:0 (6694044160540313386) -->
+ <!-- no translation found for bluetooth_a2dp_codec_bits_per_sample_titles:1 (5618929009984956469) -->
+ <!-- no translation found for bluetooth_a2dp_codec_bits_per_sample_titles:2 (3412640499234627248) -->
+ <!-- no translation found for bluetooth_a2dp_codec_bits_per_sample_titles:3 (121583001492929387) -->
+ <!-- no translation found for bluetooth_a2dp_codec_bits_per_sample_summaries:0 (5091076677792306320) -->
+ <!-- no translation found for bluetooth_a2dp_codec_bits_per_sample_summaries:1 (4726688794884191540) -->
+ <!-- no translation found for bluetooth_a2dp_codec_bits_per_sample_summaries:2 (305344756485516870) -->
+ <!-- no translation found for bluetooth_a2dp_codec_bits_per_sample_summaries:3 (244568657919675099) -->
+ <!-- no translation found for bluetooth_a2dp_codec_channel_mode_titles:0 (13423709606339855) -->
+ <!-- no translation found for bluetooth_a2dp_codec_channel_mode_titles:1 (4106832974775067314) -->
+ <!-- no translation found for bluetooth_a2dp_codec_channel_mode_titles:2 (5571632958424639155) -->
+ <!-- no translation found for bluetooth_a2dp_codec_channel_mode_summaries:0 (8128478683963250130) -->
+ <!-- no translation found for bluetooth_a2dp_codec_channel_mode_summaries:1 (8900559293912978337) -->
+ <!-- no translation found for bluetooth_a2dp_codec_channel_mode_summaries:2 (8883739882299884241) -->
+ <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_titles:0 (2944889121850394020) -->
+ <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_titles:1 (138837449700903545) -->
+ <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_titles:2 (4777177307869441982) -->
+ <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_summaries:0 (172302906231378902) -->
+ <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_summaries:1 (9091111147684472529) -->
+ <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_summaries:2 (3367904477834831032) -->
<string-array name="select_logd_size_titles">
<item msgid="8665206199209698501">"Mati"</item>
<item msgid="1593289376502312923">"64K"</item>
diff --git a/packages/SettingsLib/res/values-ms-rMY/strings.xml b/packages/SettingsLib/res/values-ms-rMY/strings.xml
index 8935581..bac1c54 100644
--- a/packages/SettingsLib/res/values-ms-rMY/strings.xml
+++ b/packages/SettingsLib/res/values-ms-rMY/strings.xml
@@ -170,6 +170,26 @@
<string name="wifi_allow_scan_with_traffic" msgid="3601853081178265786">"Sentiasa benarkan Imbasan Perayauan Wi-Fi"</string>
<string name="mobile_data_always_on" msgid="7745605759775320362">"Data selular sentiasa aktif"</string>
<string name="bluetooth_disable_absolute_volume" msgid="2660673801947898809">"Lumpuhkan kelantangan mutlak"</string>
+ <!-- no translation found for bluetooth_select_a2dp_codec_type (90597356942154882) -->
+ <skip />
+ <!-- no translation found for bluetooth_select_a2dp_codec_type_dialog_title (6470824182074383881) -->
+ <skip />
+ <!-- no translation found for bluetooth_select_a2dp_codec_sample_rate (4788245703824623062) -->
+ <skip />
+ <!-- no translation found for bluetooth_select_a2dp_codec_sample_rate_dialog_title (4263851572248033749) -->
+ <skip />
+ <!-- no translation found for bluetooth_select_a2dp_codec_bits_per_sample (2099645202720164141) -->
+ <skip />
+ <!-- no translation found for bluetooth_select_a2dp_codec_bits_per_sample_dialog_title (2096170505745650345) -->
+ <skip />
+ <!-- no translation found for bluetooth_select_a2dp_codec_channel_mode (884855779449390540) -->
+ <skip />
+ <!-- no translation found for bluetooth_select_a2dp_codec_channel_mode_dialog_title (4073812880900816325) -->
+ <skip />
+ <!-- no translation found for bluetooth_select_a2dp_codec_ldac_playback_quality (4846872213548295632) -->
+ <skip />
+ <!-- no translation found for bluetooth_select_a2dp_codec_ldac_playback_quality_dialog_title (3940973633342423717) -->
+ <skip />
<string name="wifi_display_certification_summary" msgid="1155182309166746973">"Tunjukkan pilihan untuk pensijilan paparan wayarles"</string>
<string name="wifi_verbose_logging_summary" msgid="6615071616111731958">"Tingkatkan tahap pengelogan Wi-Fi, tunjuk setiap SSID RSSI dalam Pemilih Wi-Fi"</string>
<string name="wifi_aggressive_handover_summary" msgid="6328455667642570371">"Apabila didayakan, Wi-Fi akan menjadi lebih agresif dalam menyerahkan sambungan data ke Selular, apabila isyarat Wi-Fi rendah"</string>
diff --git a/packages/SettingsLib/res/values-my-rMM/arrays.xml b/packages/SettingsLib/res/values-my-rMM/arrays.xml
index 622d0aa..4510cc8 100644
--- a/packages/SettingsLib/res/values-my-rMM/arrays.xml
+++ b/packages/SettingsLib/res/values-my-rMM/arrays.xml
@@ -58,6 +58,46 @@
<item msgid="3878793616631049349">"DRMအကြောင်းအရာအတွက် HDCPစစ်ဆေးခြင်းကိုသုံးမည်"</item>
<item msgid="45075631231212732">"HDCP checkingအားအမြဲသုံးပါ"</item>
</string-array>
+ <!-- no translation found for bluetooth_a2dp_codec_titles:0 (1852387125374225729) -->
+ <!-- no translation found for bluetooth_a2dp_codec_titles:1 (7539690996561263909) -->
+ <!-- no translation found for bluetooth_a2dp_codec_titles:2 (4260844283202960798) -->
+ <!-- no translation found for bluetooth_a2dp_codec_titles:3 (7279983368484312990) -->
+ <!-- no translation found for bluetooth_a2dp_codec_titles:4 (2301339338870319651) -->
+ <!-- no translation found for bluetooth_a2dp_codec_summaries:0 (9072025520360316957) -->
+ <!-- no translation found for bluetooth_a2dp_codec_summaries:1 (6898329690939802290) -->
+ <!-- no translation found for bluetooth_a2dp_codec_summaries:2 (1190434429082395888) -->
+ <!-- no translation found for bluetooth_a2dp_codec_summaries:3 (649699003004233053) -->
+ <!-- no translation found for bluetooth_a2dp_codec_summaries:4 (508106435710925399) -->
+ <!-- no translation found for bluetooth_a2dp_codec_sample_rate_titles:0 (7102940318360468759) -->
+ <!-- no translation found for bluetooth_a2dp_codec_sample_rate_titles:1 (8895532488906185219) -->
+ <!-- no translation found for bluetooth_a2dp_codec_sample_rate_titles:2 (2909915718994807056) -->
+ <!-- no translation found for bluetooth_a2dp_codec_sample_rate_titles:3 (3347287377354164611) -->
+ <!-- no translation found for bluetooth_a2dp_codec_sample_rate_titles:4 (1234212100239985373) -->
+ <!-- no translation found for bluetooth_a2dp_codec_sample_rate_summaries:0 (7224433008148687313) -->
+ <!-- no translation found for bluetooth_a2dp_codec_sample_rate_summaries:1 (4482862757811638365) -->
+ <!-- no translation found for bluetooth_a2dp_codec_sample_rate_summaries:2 (354495328188724404) -->
+ <!-- no translation found for bluetooth_a2dp_codec_sample_rate_summaries:3 (7329816882213695083) -->
+ <!-- no translation found for bluetooth_a2dp_codec_sample_rate_summaries:4 (6967397666254430476) -->
+ <!-- no translation found for bluetooth_a2dp_codec_bits_per_sample_titles:0 (6694044160540313386) -->
+ <!-- no translation found for bluetooth_a2dp_codec_bits_per_sample_titles:1 (5618929009984956469) -->
+ <!-- no translation found for bluetooth_a2dp_codec_bits_per_sample_titles:2 (3412640499234627248) -->
+ <!-- no translation found for bluetooth_a2dp_codec_bits_per_sample_titles:3 (121583001492929387) -->
+ <!-- no translation found for bluetooth_a2dp_codec_bits_per_sample_summaries:0 (5091076677792306320) -->
+ <!-- no translation found for bluetooth_a2dp_codec_bits_per_sample_summaries:1 (4726688794884191540) -->
+ <!-- no translation found for bluetooth_a2dp_codec_bits_per_sample_summaries:2 (305344756485516870) -->
+ <!-- no translation found for bluetooth_a2dp_codec_bits_per_sample_summaries:3 (244568657919675099) -->
+ <!-- no translation found for bluetooth_a2dp_codec_channel_mode_titles:0 (13423709606339855) -->
+ <!-- no translation found for bluetooth_a2dp_codec_channel_mode_titles:1 (4106832974775067314) -->
+ <!-- no translation found for bluetooth_a2dp_codec_channel_mode_titles:2 (5571632958424639155) -->
+ <!-- no translation found for bluetooth_a2dp_codec_channel_mode_summaries:0 (8128478683963250130) -->
+ <!-- no translation found for bluetooth_a2dp_codec_channel_mode_summaries:1 (8900559293912978337) -->
+ <!-- no translation found for bluetooth_a2dp_codec_channel_mode_summaries:2 (8883739882299884241) -->
+ <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_titles:0 (2944889121850394020) -->
+ <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_titles:1 (138837449700903545) -->
+ <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_titles:2 (4777177307869441982) -->
+ <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_summaries:0 (172302906231378902) -->
+ <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_summaries:1 (9091111147684472529) -->
+ <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_summaries:2 (3367904477834831032) -->
<string-array name="select_logd_size_titles">
<item msgid="8665206199209698501">"ပိတ်ပါ"</item>
<item msgid="1593289376502312923">"64K"</item>
diff --git a/packages/SettingsLib/res/values-my-rMM/strings.xml b/packages/SettingsLib/res/values-my-rMM/strings.xml
index 5f4dc50..5c071f6 100644
--- a/packages/SettingsLib/res/values-my-rMM/strings.xml
+++ b/packages/SettingsLib/res/values-my-rMM/strings.xml
@@ -170,6 +170,26 @@
<string name="wifi_allow_scan_with_traffic" msgid="3601853081178265786">"Wi‑Fi ရွမ်းရှာဖွေမှုကို အမြဲတမ်း ခွင့်ပြုမည်"</string>
<string name="mobile_data_always_on" msgid="7745605759775320362">"ဆဲလ်လူလာဒေတာ အမြဲတမ်းဖွင့်ထားသည်"</string>
<string name="bluetooth_disable_absolute_volume" msgid="2660673801947898809">"ပကတိ အသံနှုန်း သတ်မှတ်ချက် ပိတ်ရန်"</string>
+ <!-- no translation found for bluetooth_select_a2dp_codec_type (90597356942154882) -->
+ <skip />
+ <!-- no translation found for bluetooth_select_a2dp_codec_type_dialog_title (6470824182074383881) -->
+ <skip />
+ <!-- no translation found for bluetooth_select_a2dp_codec_sample_rate (4788245703824623062) -->
+ <skip />
+ <!-- no translation found for bluetooth_select_a2dp_codec_sample_rate_dialog_title (4263851572248033749) -->
+ <skip />
+ <!-- no translation found for bluetooth_select_a2dp_codec_bits_per_sample (2099645202720164141) -->
+ <skip />
+ <!-- no translation found for bluetooth_select_a2dp_codec_bits_per_sample_dialog_title (2096170505745650345) -->
+ <skip />
+ <!-- no translation found for bluetooth_select_a2dp_codec_channel_mode (884855779449390540) -->
+ <skip />
+ <!-- no translation found for bluetooth_select_a2dp_codec_channel_mode_dialog_title (4073812880900816325) -->
+ <skip />
+ <!-- no translation found for bluetooth_select_a2dp_codec_ldac_playback_quality (4846872213548295632) -->
+ <skip />
+ <!-- no translation found for bluetooth_select_a2dp_codec_ldac_playback_quality_dialog_title (3940973633342423717) -->
+ <skip />
<string name="wifi_display_certification_summary" msgid="1155182309166746973">"ကြိုးမဲ့ အခင်းအကျင်း အသိအမှတ်ပြုလက်မှတ်အတွက် ရွေးချယ်စရာများပြရန်"</string>
<string name="wifi_verbose_logging_summary" msgid="6615071616111731958">"Wi‑Fi မှတ်တမ်းတင်ခြင်း နှုန်းအားမြင့်ကာ၊ Wi‑Fi ရွေးရာတွင် SSID RSSI ဖြင့်ပြပါ"</string>
<string name="wifi_aggressive_handover_summary" msgid="6328455667642570371">"ဖွင့်ထားလျှင်၊ Wi‑Fi မှ ဆယ်လူလာသို့ အချက်လက် ချိတ်ဆက်မှုအား လွှဲပြောင်းရာ၌ ပိုမိုထိရောက်ပါသည်၊ WIFI အားနည်းနေချိန်တွင်"</string>
diff --git a/packages/SettingsLib/res/values-nb/arrays.xml b/packages/SettingsLib/res/values-nb/arrays.xml
index 917518c..22fe819 100644
--- a/packages/SettingsLib/res/values-nb/arrays.xml
+++ b/packages/SettingsLib/res/values-nb/arrays.xml
@@ -58,6 +58,46 @@
<item msgid="3878793616631049349">"Bruk HDCP-kontroll kun for DRM-innhold"</item>
<item msgid="45075631231212732">"Bruk alltid HDCP-kontroll"</item>
</string-array>
+ <!-- no translation found for bluetooth_a2dp_codec_titles:0 (1852387125374225729) -->
+ <!-- no translation found for bluetooth_a2dp_codec_titles:1 (7539690996561263909) -->
+ <!-- no translation found for bluetooth_a2dp_codec_titles:2 (4260844283202960798) -->
+ <!-- no translation found for bluetooth_a2dp_codec_titles:3 (7279983368484312990) -->
+ <!-- no translation found for bluetooth_a2dp_codec_titles:4 (2301339338870319651) -->
+ <!-- no translation found for bluetooth_a2dp_codec_summaries:0 (9072025520360316957) -->
+ <!-- no translation found for bluetooth_a2dp_codec_summaries:1 (6898329690939802290) -->
+ <!-- no translation found for bluetooth_a2dp_codec_summaries:2 (1190434429082395888) -->
+ <!-- no translation found for bluetooth_a2dp_codec_summaries:3 (649699003004233053) -->
+ <!-- no translation found for bluetooth_a2dp_codec_summaries:4 (508106435710925399) -->
+ <!-- no translation found for bluetooth_a2dp_codec_sample_rate_titles:0 (7102940318360468759) -->
+ <!-- no translation found for bluetooth_a2dp_codec_sample_rate_titles:1 (8895532488906185219) -->
+ <!-- no translation found for bluetooth_a2dp_codec_sample_rate_titles:2 (2909915718994807056) -->
+ <!-- no translation found for bluetooth_a2dp_codec_sample_rate_titles:3 (3347287377354164611) -->
+ <!-- no translation found for bluetooth_a2dp_codec_sample_rate_titles:4 (1234212100239985373) -->
+ <!-- no translation found for bluetooth_a2dp_codec_sample_rate_summaries:0 (7224433008148687313) -->
+ <!-- no translation found for bluetooth_a2dp_codec_sample_rate_summaries:1 (4482862757811638365) -->
+ <!-- no translation found for bluetooth_a2dp_codec_sample_rate_summaries:2 (354495328188724404) -->
+ <!-- no translation found for bluetooth_a2dp_codec_sample_rate_summaries:3 (7329816882213695083) -->
+ <!-- no translation found for bluetooth_a2dp_codec_sample_rate_summaries:4 (6967397666254430476) -->
+ <!-- no translation found for bluetooth_a2dp_codec_bits_per_sample_titles:0 (6694044160540313386) -->
+ <!-- no translation found for bluetooth_a2dp_codec_bits_per_sample_titles:1 (5618929009984956469) -->
+ <!-- no translation found for bluetooth_a2dp_codec_bits_per_sample_titles:2 (3412640499234627248) -->
+ <!-- no translation found for bluetooth_a2dp_codec_bits_per_sample_titles:3 (121583001492929387) -->
+ <!-- no translation found for bluetooth_a2dp_codec_bits_per_sample_summaries:0 (5091076677792306320) -->
+ <!-- no translation found for bluetooth_a2dp_codec_bits_per_sample_summaries:1 (4726688794884191540) -->
+ <!-- no translation found for bluetooth_a2dp_codec_bits_per_sample_summaries:2 (305344756485516870) -->
+ <!-- no translation found for bluetooth_a2dp_codec_bits_per_sample_summaries:3 (244568657919675099) -->
+ <!-- no translation found for bluetooth_a2dp_codec_channel_mode_titles:0 (13423709606339855) -->
+ <!-- no translation found for bluetooth_a2dp_codec_channel_mode_titles:1 (4106832974775067314) -->
+ <!-- no translation found for bluetooth_a2dp_codec_channel_mode_titles:2 (5571632958424639155) -->
+ <!-- no translation found for bluetooth_a2dp_codec_channel_mode_summaries:0 (8128478683963250130) -->
+ <!-- no translation found for bluetooth_a2dp_codec_channel_mode_summaries:1 (8900559293912978337) -->
+ <!-- no translation found for bluetooth_a2dp_codec_channel_mode_summaries:2 (8883739882299884241) -->
+ <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_titles:0 (2944889121850394020) -->
+ <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_titles:1 (138837449700903545) -->
+ <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_titles:2 (4777177307869441982) -->
+ <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_summaries:0 (172302906231378902) -->
+ <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_summaries:1 (9091111147684472529) -->
+ <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_summaries:2 (3367904477834831032) -->
<string-array name="select_logd_size_titles">
<item msgid="8665206199209698501">"Av"</item>
<item msgid="1593289376502312923">"64K"</item>
diff --git a/packages/SettingsLib/res/values-nb/strings.xml b/packages/SettingsLib/res/values-nb/strings.xml
index 76ff94f..16fef06 100644
--- a/packages/SettingsLib/res/values-nb/strings.xml
+++ b/packages/SettingsLib/res/values-nb/strings.xml
@@ -170,6 +170,26 @@
<string name="wifi_allow_scan_with_traffic" msgid="3601853081178265786">"Tillat alltid skanning for Wi-Fi-roaming"</string>
<string name="mobile_data_always_on" msgid="7745605759775320362">"Mobildata er alltid aktiv"</string>
<string name="bluetooth_disable_absolute_volume" msgid="2660673801947898809">"Slå av funksjonen for absolutt volum"</string>
+ <!-- no translation found for bluetooth_select_a2dp_codec_type (90597356942154882) -->
+ <skip />
+ <!-- no translation found for bluetooth_select_a2dp_codec_type_dialog_title (6470824182074383881) -->
+ <skip />
+ <!-- no translation found for bluetooth_select_a2dp_codec_sample_rate (4788245703824623062) -->
+ <skip />
+ <!-- no translation found for bluetooth_select_a2dp_codec_sample_rate_dialog_title (4263851572248033749) -->
+ <skip />
+ <!-- no translation found for bluetooth_select_a2dp_codec_bits_per_sample (2099645202720164141) -->
+ <skip />
+ <!-- no translation found for bluetooth_select_a2dp_codec_bits_per_sample_dialog_title (2096170505745650345) -->
+ <skip />
+ <!-- no translation found for bluetooth_select_a2dp_codec_channel_mode (884855779449390540) -->
+ <skip />
+ <!-- no translation found for bluetooth_select_a2dp_codec_channel_mode_dialog_title (4073812880900816325) -->
+ <skip />
+ <!-- no translation found for bluetooth_select_a2dp_codec_ldac_playback_quality (4846872213548295632) -->
+ <skip />
+ <!-- no translation found for bluetooth_select_a2dp_codec_ldac_playback_quality_dialog_title (3940973633342423717) -->
+ <skip />
<string name="wifi_display_certification_summary" msgid="1155182309166746973">"Vis alternativer for sertifisering av trådløs skjerm"</string>
<string name="wifi_verbose_logging_summary" msgid="6615071616111731958">"Øk Wi-Fi-loggenivå – vis per SSID RSSI i Wi-Fi-velgeren"</string>
<string name="wifi_aggressive_handover_summary" msgid="6328455667642570371">"Hvis dette slås på, overfører Wi-Fi-nettverket datatilkoblingen til mobil mer aggressivt når Wi-Fi-signalet er lavt"</string>
diff --git a/packages/SettingsLib/res/values-ne-rNP/arrays.xml b/packages/SettingsLib/res/values-ne-rNP/arrays.xml
index 015a034..edacd0d 100644
--- a/packages/SettingsLib/res/values-ne-rNP/arrays.xml
+++ b/packages/SettingsLib/res/values-ne-rNP/arrays.xml
@@ -58,6 +58,46 @@
<item msgid="3878793616631049349">"DRM सामग्रीको लागि मात्र HDCP जाँचको प्रयोग गर्नुहोस्"</item>
<item msgid="45075631231212732">"सधैँ HDCP जाँच प्रयोग गर्नुहोस्"</item>
</string-array>
+ <!-- no translation found for bluetooth_a2dp_codec_titles:0 (1852387125374225729) -->
+ <!-- no translation found for bluetooth_a2dp_codec_titles:1 (7539690996561263909) -->
+ <!-- no translation found for bluetooth_a2dp_codec_titles:2 (4260844283202960798) -->
+ <!-- no translation found for bluetooth_a2dp_codec_titles:3 (7279983368484312990) -->
+ <!-- no translation found for bluetooth_a2dp_codec_titles:4 (2301339338870319651) -->
+ <!-- no translation found for bluetooth_a2dp_codec_summaries:0 (9072025520360316957) -->
+ <!-- no translation found for bluetooth_a2dp_codec_summaries:1 (6898329690939802290) -->
+ <!-- no translation found for bluetooth_a2dp_codec_summaries:2 (1190434429082395888) -->
+ <!-- no translation found for bluetooth_a2dp_codec_summaries:3 (649699003004233053) -->
+ <!-- no translation found for bluetooth_a2dp_codec_summaries:4 (508106435710925399) -->
+ <!-- no translation found for bluetooth_a2dp_codec_sample_rate_titles:0 (7102940318360468759) -->
+ <!-- no translation found for bluetooth_a2dp_codec_sample_rate_titles:1 (8895532488906185219) -->
+ <!-- no translation found for bluetooth_a2dp_codec_sample_rate_titles:2 (2909915718994807056) -->
+ <!-- no translation found for bluetooth_a2dp_codec_sample_rate_titles:3 (3347287377354164611) -->
+ <!-- no translation found for bluetooth_a2dp_codec_sample_rate_titles:4 (1234212100239985373) -->
+ <!-- no translation found for bluetooth_a2dp_codec_sample_rate_summaries:0 (7224433008148687313) -->
+ <!-- no translation found for bluetooth_a2dp_codec_sample_rate_summaries:1 (4482862757811638365) -->
+ <!-- no translation found for bluetooth_a2dp_codec_sample_rate_summaries:2 (354495328188724404) -->
+ <!-- no translation found for bluetooth_a2dp_codec_sample_rate_summaries:3 (7329816882213695083) -->
+ <!-- no translation found for bluetooth_a2dp_codec_sample_rate_summaries:4 (6967397666254430476) -->
+ <!-- no translation found for bluetooth_a2dp_codec_bits_per_sample_titles:0 (6694044160540313386) -->
+ <!-- no translation found for bluetooth_a2dp_codec_bits_per_sample_titles:1 (5618929009984956469) -->
+ <!-- no translation found for bluetooth_a2dp_codec_bits_per_sample_titles:2 (3412640499234627248) -->
+ <!-- no translation found for bluetooth_a2dp_codec_bits_per_sample_titles:3 (121583001492929387) -->
+ <!-- no translation found for bluetooth_a2dp_codec_bits_per_sample_summaries:0 (5091076677792306320) -->
+ <!-- no translation found for bluetooth_a2dp_codec_bits_per_sample_summaries:1 (4726688794884191540) -->
+ <!-- no translation found for bluetooth_a2dp_codec_bits_per_sample_summaries:2 (305344756485516870) -->
+ <!-- no translation found for bluetooth_a2dp_codec_bits_per_sample_summaries:3 (244568657919675099) -->
+ <!-- no translation found for bluetooth_a2dp_codec_channel_mode_titles:0 (13423709606339855) -->
+ <!-- no translation found for bluetooth_a2dp_codec_channel_mode_titles:1 (4106832974775067314) -->
+ <!-- no translation found for bluetooth_a2dp_codec_channel_mode_titles:2 (5571632958424639155) -->
+ <!-- no translation found for bluetooth_a2dp_codec_channel_mode_summaries:0 (8128478683963250130) -->
+ <!-- no translation found for bluetooth_a2dp_codec_channel_mode_summaries:1 (8900559293912978337) -->
+ <!-- no translation found for bluetooth_a2dp_codec_channel_mode_summaries:2 (8883739882299884241) -->
+ <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_titles:0 (2944889121850394020) -->
+ <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_titles:1 (138837449700903545) -->
+ <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_titles:2 (4777177307869441982) -->
+ <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_summaries:0 (172302906231378902) -->
+ <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_summaries:1 (9091111147684472529) -->
+ <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_summaries:2 (3367904477834831032) -->
<string-array name="select_logd_size_titles">
<item msgid="8665206199209698501">"निष्क्रिय गर्नुहोस्"</item>
<item msgid="1593289376502312923">"६४के"</item>
diff --git a/packages/SettingsLib/res/values-ne-rNP/strings.xml b/packages/SettingsLib/res/values-ne-rNP/strings.xml
index 8199cde..c06818d 100644
--- a/packages/SettingsLib/res/values-ne-rNP/strings.xml
+++ b/packages/SettingsLib/res/values-ne-rNP/strings.xml
@@ -170,6 +170,26 @@
<string name="wifi_allow_scan_with_traffic" msgid="3601853081178265786">"Wi-Fi घुम्ने स्क्यान गर्न सधैँ अनुमति दिनुहोस्"</string>
<string name="mobile_data_always_on" msgid="7745605759775320362">"सेलुलर डेटा सधैं सक्रिय"</string>
<string name="bluetooth_disable_absolute_volume" msgid="2660673801947898809">"निरपेक्ष आवाज असक्षम गर्नुहोस्"</string>
+ <!-- no translation found for bluetooth_select_a2dp_codec_type (90597356942154882) -->
+ <skip />
+ <!-- no translation found for bluetooth_select_a2dp_codec_type_dialog_title (6470824182074383881) -->
+ <skip />
+ <!-- no translation found for bluetooth_select_a2dp_codec_sample_rate (4788245703824623062) -->
+ <skip />
+ <!-- no translation found for bluetooth_select_a2dp_codec_sample_rate_dialog_title (4263851572248033749) -->
+ <skip />
+ <!-- no translation found for bluetooth_select_a2dp_codec_bits_per_sample (2099645202720164141) -->
+ <skip />
+ <!-- no translation found for bluetooth_select_a2dp_codec_bits_per_sample_dialog_title (2096170505745650345) -->
+ <skip />
+ <!-- no translation found for bluetooth_select_a2dp_codec_channel_mode (884855779449390540) -->
+ <skip />
+ <!-- no translation found for bluetooth_select_a2dp_codec_channel_mode_dialog_title (4073812880900816325) -->
+ <skip />
+ <!-- no translation found for bluetooth_select_a2dp_codec_ldac_playback_quality (4846872213548295632) -->
+ <skip />
+ <!-- no translation found for bluetooth_select_a2dp_codec_ldac_playback_quality_dialog_title (3940973633342423717) -->
+ <skip />
<string name="wifi_display_certification_summary" msgid="1155182309166746973">"ताररहित प्रदर्शन प्रमाणीकरणका लागि विकल्पहरू देखाउनुहोस्"</string>
<string name="wifi_verbose_logging_summary" msgid="6615071616111731958">"Wi-Fi लग स्तर बढाउनुहोस्, Wi-Fi चयनकर्तामा प्रति SSID RSSI देखाइन्छ"</string>
<string name="wifi_aggressive_handover_summary" msgid="6328455667642570371">"Wi-Fi संकेत कम हुँदा, सक्षम जब गरिन्छ, Wi-Fi सेलुलर लागि डेटा जडान सुम्पनामा बढी आक्रामक हुनेछ"</string>
diff --git a/packages/SettingsLib/res/values-nl/arrays.xml b/packages/SettingsLib/res/values-nl/arrays.xml
index 8f73bf9..2820a16 100644
--- a/packages/SettingsLib/res/values-nl/arrays.xml
+++ b/packages/SettingsLib/res/values-nl/arrays.xml
@@ -58,6 +58,46 @@
<item msgid="3878793616631049349">"HDCP-controle alleen voor DRM-content gebruiken"</item>
<item msgid="45075631231212732">"HDCP-controle altijd gebruiken"</item>
</string-array>
+ <!-- no translation found for bluetooth_a2dp_codec_titles:0 (1852387125374225729) -->
+ <!-- no translation found for bluetooth_a2dp_codec_titles:1 (7539690996561263909) -->
+ <!-- no translation found for bluetooth_a2dp_codec_titles:2 (4260844283202960798) -->
+ <!-- no translation found for bluetooth_a2dp_codec_titles:3 (7279983368484312990) -->
+ <!-- no translation found for bluetooth_a2dp_codec_titles:4 (2301339338870319651) -->
+ <!-- no translation found for bluetooth_a2dp_codec_summaries:0 (9072025520360316957) -->
+ <!-- no translation found for bluetooth_a2dp_codec_summaries:1 (6898329690939802290) -->
+ <!-- no translation found for bluetooth_a2dp_codec_summaries:2 (1190434429082395888) -->
+ <!-- no translation found for bluetooth_a2dp_codec_summaries:3 (649699003004233053) -->
+ <!-- no translation found for bluetooth_a2dp_codec_summaries:4 (508106435710925399) -->
+ <!-- no translation found for bluetooth_a2dp_codec_sample_rate_titles:0 (7102940318360468759) -->
+ <!-- no translation found for bluetooth_a2dp_codec_sample_rate_titles:1 (8895532488906185219) -->
+ <!-- no translation found for bluetooth_a2dp_codec_sample_rate_titles:2 (2909915718994807056) -->
+ <!-- no translation found for bluetooth_a2dp_codec_sample_rate_titles:3 (3347287377354164611) -->
+ <!-- no translation found for bluetooth_a2dp_codec_sample_rate_titles:4 (1234212100239985373) -->
+ <!-- no translation found for bluetooth_a2dp_codec_sample_rate_summaries:0 (7224433008148687313) -->
+ <!-- no translation found for bluetooth_a2dp_codec_sample_rate_summaries:1 (4482862757811638365) -->
+ <!-- no translation found for bluetooth_a2dp_codec_sample_rate_summaries:2 (354495328188724404) -->
+ <!-- no translation found for bluetooth_a2dp_codec_sample_rate_summaries:3 (7329816882213695083) -->
+ <!-- no translation found for bluetooth_a2dp_codec_sample_rate_summaries:4 (6967397666254430476) -->
+ <!-- no translation found for bluetooth_a2dp_codec_bits_per_sample_titles:0 (6694044160540313386) -->
+ <!-- no translation found for bluetooth_a2dp_codec_bits_per_sample_titles:1 (5618929009984956469) -->
+ <!-- no translation found for bluetooth_a2dp_codec_bits_per_sample_titles:2 (3412640499234627248) -->
+ <!-- no translation found for bluetooth_a2dp_codec_bits_per_sample_titles:3 (121583001492929387) -->
+ <!-- no translation found for bluetooth_a2dp_codec_bits_per_sample_summaries:0 (5091076677792306320) -->
+ <!-- no translation found for bluetooth_a2dp_codec_bits_per_sample_summaries:1 (4726688794884191540) -->
+ <!-- no translation found for bluetooth_a2dp_codec_bits_per_sample_summaries:2 (305344756485516870) -->
+ <!-- no translation found for bluetooth_a2dp_codec_bits_per_sample_summaries:3 (244568657919675099) -->
+ <!-- no translation found for bluetooth_a2dp_codec_channel_mode_titles:0 (13423709606339855) -->
+ <!-- no translation found for bluetooth_a2dp_codec_channel_mode_titles:1 (4106832974775067314) -->
+ <!-- no translation found for bluetooth_a2dp_codec_channel_mode_titles:2 (5571632958424639155) -->
+ <!-- no translation found for bluetooth_a2dp_codec_channel_mode_summaries:0 (8128478683963250130) -->
+ <!-- no translation found for bluetooth_a2dp_codec_channel_mode_summaries:1 (8900559293912978337) -->
+ <!-- no translation found for bluetooth_a2dp_codec_channel_mode_summaries:2 (8883739882299884241) -->
+ <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_titles:0 (2944889121850394020) -->
+ <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_titles:1 (138837449700903545) -->
+ <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_titles:2 (4777177307869441982) -->
+ <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_summaries:0 (172302906231378902) -->
+ <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_summaries:1 (9091111147684472529) -->
+ <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_summaries:2 (3367904477834831032) -->
<string-array name="select_logd_size_titles">
<item msgid="8665206199209698501">"Uit"</item>
<item msgid="1593289376502312923">"64 K"</item>
diff --git a/packages/SettingsLib/res/values-nl/strings.xml b/packages/SettingsLib/res/values-nl/strings.xml
index 89d7fab..cb0ff8b 100644
--- a/packages/SettingsLib/res/values-nl/strings.xml
+++ b/packages/SettingsLib/res/values-nl/strings.xml
@@ -170,6 +170,26 @@
<string name="wifi_allow_scan_with_traffic" msgid="3601853081178265786">"Altijd roamingscans voor wifi toestaan"</string>
<string name="mobile_data_always_on" msgid="7745605759775320362">"Mobiele data altijd actief"</string>
<string name="bluetooth_disable_absolute_volume" msgid="2660673801947898809">"Absoluut volume uitschakelen"</string>
+ <!-- no translation found for bluetooth_select_a2dp_codec_type (90597356942154882) -->
+ <skip />
+ <!-- no translation found for bluetooth_select_a2dp_codec_type_dialog_title (6470824182074383881) -->
+ <skip />
+ <!-- no translation found for bluetooth_select_a2dp_codec_sample_rate (4788245703824623062) -->
+ <skip />
+ <!-- no translation found for bluetooth_select_a2dp_codec_sample_rate_dialog_title (4263851572248033749) -->
+ <skip />
+ <!-- no translation found for bluetooth_select_a2dp_codec_bits_per_sample (2099645202720164141) -->
+ <skip />
+ <!-- no translation found for bluetooth_select_a2dp_codec_bits_per_sample_dialog_title (2096170505745650345) -->
+ <skip />
+ <!-- no translation found for bluetooth_select_a2dp_codec_channel_mode (884855779449390540) -->
+ <skip />
+ <!-- no translation found for bluetooth_select_a2dp_codec_channel_mode_dialog_title (4073812880900816325) -->
+ <skip />
+ <!-- no translation found for bluetooth_select_a2dp_codec_ldac_playback_quality (4846872213548295632) -->
+ <skip />
+ <!-- no translation found for bluetooth_select_a2dp_codec_ldac_playback_quality_dialog_title (3940973633342423717) -->
+ <skip />
<string name="wifi_display_certification_summary" msgid="1155182309166746973">"Opties weergeven voor certificering van draadloze weergave"</string>
<string name="wifi_verbose_logging_summary" msgid="6615071616111731958">"Logniveau voor wifi verhogen, weergeven per SSID RSSI in wifi-kiezer"</string>
<string name="wifi_aggressive_handover_summary" msgid="6328455667642570371">"Indien ingeschakeld, is wifi agressiever bij het overgeven van de gegevensverbinding aan mobiel wanneer het wifi-signaal zwak is"</string>
diff --git a/packages/SettingsLib/res/values-pa-rIN/arrays.xml b/packages/SettingsLib/res/values-pa-rIN/arrays.xml
index 54565bc..97e758c 100644
--- a/packages/SettingsLib/res/values-pa-rIN/arrays.xml
+++ b/packages/SettingsLib/res/values-pa-rIN/arrays.xml
@@ -58,6 +58,46 @@
<item msgid="3878793616631049349">"ਕੇਵਲ DRM ਸਮੱਗਰੀ ਲਈ HDCP ਜਾਂਚ"</item>
<item msgid="45075631231212732">"ਹਮੇਸਾਂ HDCP ਜਾਂਚ ਵਰਤੋ"</item>
</string-array>
+ <!-- no translation found for bluetooth_a2dp_codec_titles:0 (1852387125374225729) -->
+ <!-- no translation found for bluetooth_a2dp_codec_titles:1 (7539690996561263909) -->
+ <!-- no translation found for bluetooth_a2dp_codec_titles:2 (4260844283202960798) -->
+ <!-- no translation found for bluetooth_a2dp_codec_titles:3 (7279983368484312990) -->
+ <!-- no translation found for bluetooth_a2dp_codec_titles:4 (2301339338870319651) -->
+ <!-- no translation found for bluetooth_a2dp_codec_summaries:0 (9072025520360316957) -->
+ <!-- no translation found for bluetooth_a2dp_codec_summaries:1 (6898329690939802290) -->
+ <!-- no translation found for bluetooth_a2dp_codec_summaries:2 (1190434429082395888) -->
+ <!-- no translation found for bluetooth_a2dp_codec_summaries:3 (649699003004233053) -->
+ <!-- no translation found for bluetooth_a2dp_codec_summaries:4 (508106435710925399) -->
+ <!-- no translation found for bluetooth_a2dp_codec_sample_rate_titles:0 (7102940318360468759) -->
+ <!-- no translation found for bluetooth_a2dp_codec_sample_rate_titles:1 (8895532488906185219) -->
+ <!-- no translation found for bluetooth_a2dp_codec_sample_rate_titles:2 (2909915718994807056) -->
+ <!-- no translation found for bluetooth_a2dp_codec_sample_rate_titles:3 (3347287377354164611) -->
+ <!-- no translation found for bluetooth_a2dp_codec_sample_rate_titles:4 (1234212100239985373) -->
+ <!-- no translation found for bluetooth_a2dp_codec_sample_rate_summaries:0 (7224433008148687313) -->
+ <!-- no translation found for bluetooth_a2dp_codec_sample_rate_summaries:1 (4482862757811638365) -->
+ <!-- no translation found for bluetooth_a2dp_codec_sample_rate_summaries:2 (354495328188724404) -->
+ <!-- no translation found for bluetooth_a2dp_codec_sample_rate_summaries:3 (7329816882213695083) -->
+ <!-- no translation found for bluetooth_a2dp_codec_sample_rate_summaries:4 (6967397666254430476) -->
+ <!-- no translation found for bluetooth_a2dp_codec_bits_per_sample_titles:0 (6694044160540313386) -->
+ <!-- no translation found for bluetooth_a2dp_codec_bits_per_sample_titles:1 (5618929009984956469) -->
+ <!-- no translation found for bluetooth_a2dp_codec_bits_per_sample_titles:2 (3412640499234627248) -->
+ <!-- no translation found for bluetooth_a2dp_codec_bits_per_sample_titles:3 (121583001492929387) -->
+ <!-- no translation found for bluetooth_a2dp_codec_bits_per_sample_summaries:0 (5091076677792306320) -->
+ <!-- no translation found for bluetooth_a2dp_codec_bits_per_sample_summaries:1 (4726688794884191540) -->
+ <!-- no translation found for bluetooth_a2dp_codec_bits_per_sample_summaries:2 (305344756485516870) -->
+ <!-- no translation found for bluetooth_a2dp_codec_bits_per_sample_summaries:3 (244568657919675099) -->
+ <!-- no translation found for bluetooth_a2dp_codec_channel_mode_titles:0 (13423709606339855) -->
+ <!-- no translation found for bluetooth_a2dp_codec_channel_mode_titles:1 (4106832974775067314) -->
+ <!-- no translation found for bluetooth_a2dp_codec_channel_mode_titles:2 (5571632958424639155) -->
+ <!-- no translation found for bluetooth_a2dp_codec_channel_mode_summaries:0 (8128478683963250130) -->
+ <!-- no translation found for bluetooth_a2dp_codec_channel_mode_summaries:1 (8900559293912978337) -->
+ <!-- no translation found for bluetooth_a2dp_codec_channel_mode_summaries:2 (8883739882299884241) -->
+ <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_titles:0 (2944889121850394020) -->
+ <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_titles:1 (138837449700903545) -->
+ <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_titles:2 (4777177307869441982) -->
+ <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_summaries:0 (172302906231378902) -->
+ <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_summaries:1 (9091111147684472529) -->
+ <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_summaries:2 (3367904477834831032) -->
<string-array name="select_logd_size_titles">
<item msgid="8665206199209698501">"ਬੰਦ"</item>
<item msgid="1593289376502312923">"64K"</item>
diff --git a/packages/SettingsLib/res/values-pa-rIN/strings.xml b/packages/SettingsLib/res/values-pa-rIN/strings.xml
index cb46376..7910688 100644
--- a/packages/SettingsLib/res/values-pa-rIN/strings.xml
+++ b/packages/SettingsLib/res/values-pa-rIN/strings.xml
@@ -170,6 +170,26 @@
<string name="wifi_allow_scan_with_traffic" msgid="3601853081178265786">"ਹਮੇਸ਼ਾਂ Wi‑Fi Roam Scans ਦੀ ਆਗਿਆ ਦਿਓ"</string>
<string name="mobile_data_always_on" msgid="7745605759775320362">"ਸੈਲਿਊਲਰ ਡੇਟਾ ਹਮੇਸ਼ਾ ਕਿਰਿਆਸ਼ੀਲ"</string>
<string name="bluetooth_disable_absolute_volume" msgid="2660673801947898809">"ਪੂਰਨ ਵੌਲਿਊਮ ਨੂੰ ਅਯੋਗ ਬਣਾਓ"</string>
+ <!-- no translation found for bluetooth_select_a2dp_codec_type (90597356942154882) -->
+ <skip />
+ <!-- no translation found for bluetooth_select_a2dp_codec_type_dialog_title (6470824182074383881) -->
+ <skip />
+ <!-- no translation found for bluetooth_select_a2dp_codec_sample_rate (4788245703824623062) -->
+ <skip />
+ <!-- no translation found for bluetooth_select_a2dp_codec_sample_rate_dialog_title (4263851572248033749) -->
+ <skip />
+ <!-- no translation found for bluetooth_select_a2dp_codec_bits_per_sample (2099645202720164141) -->
+ <skip />
+ <!-- no translation found for bluetooth_select_a2dp_codec_bits_per_sample_dialog_title (2096170505745650345) -->
+ <skip />
+ <!-- no translation found for bluetooth_select_a2dp_codec_channel_mode (884855779449390540) -->
+ <skip />
+ <!-- no translation found for bluetooth_select_a2dp_codec_channel_mode_dialog_title (4073812880900816325) -->
+ <skip />
+ <!-- no translation found for bluetooth_select_a2dp_codec_ldac_playback_quality (4846872213548295632) -->
+ <skip />
+ <!-- no translation found for bluetooth_select_a2dp_codec_ldac_playback_quality_dialog_title (3940973633342423717) -->
+ <skip />
<string name="wifi_display_certification_summary" msgid="1155182309166746973">"ਵਾਇਰਲੈਸ ਡਿਸਪਲੇ ਪ੍ਰਮਾਣੀਕਰਨ ਲਈ ਚੋਣਾਂ ਦਿਖਾਓ"</string>
<string name="wifi_verbose_logging_summary" msgid="6615071616111731958">"Wi‑Fi ਲੌਗਿੰਗ ਪੱਧਰ ਵਧਾਓ, Wi‑Fi Picker ਵਿੱਚ ਪ੍ਰਤੀ SSID RSSI ਦਿਖਾਓ"</string>
<string name="wifi_aggressive_handover_summary" msgid="6328455667642570371">"ਜਦੋਂ ਸਮਰਥਿਤ ਹੋਵੇ, ਤਾਂ Wi‑Fi ਸੈਲਿਊਲਰ ਨੂੰ ਡੈਟਾ ਕਨੈਕਸ਼ਨ ਹੈਂਡ ਓਵਰ ਕਰਨ ਵਿੱਚ ਵੱਧ ਅਗ੍ਰੈਸਿਵ ਹੋ ਜਾਏਗਾ, ਜਦੋਂ Wi‑Fi ਸਿਗਨਲ ਘੱਟ ਹੋਵੇ"</string>
diff --git a/packages/SettingsLib/res/values-pl/arrays.xml b/packages/SettingsLib/res/values-pl/arrays.xml
index eefca13..0e9c1b5 100644
--- a/packages/SettingsLib/res/values-pl/arrays.xml
+++ b/packages/SettingsLib/res/values-pl/arrays.xml
@@ -58,6 +58,46 @@
<item msgid="3878793616631049349">"Użyj sprawdzania HDCP tylko w przypadku treści chronionych DRM"</item>
<item msgid="45075631231212732">"Zawsze używaj sprawdzania HDCP"</item>
</string-array>
+ <!-- no translation found for bluetooth_a2dp_codec_titles:0 (1852387125374225729) -->
+ <!-- no translation found for bluetooth_a2dp_codec_titles:1 (7539690996561263909) -->
+ <!-- no translation found for bluetooth_a2dp_codec_titles:2 (4260844283202960798) -->
+ <!-- no translation found for bluetooth_a2dp_codec_titles:3 (7279983368484312990) -->
+ <!-- no translation found for bluetooth_a2dp_codec_titles:4 (2301339338870319651) -->
+ <!-- no translation found for bluetooth_a2dp_codec_summaries:0 (9072025520360316957) -->
+ <!-- no translation found for bluetooth_a2dp_codec_summaries:1 (6898329690939802290) -->
+ <!-- no translation found for bluetooth_a2dp_codec_summaries:2 (1190434429082395888) -->
+ <!-- no translation found for bluetooth_a2dp_codec_summaries:3 (649699003004233053) -->
+ <!-- no translation found for bluetooth_a2dp_codec_summaries:4 (508106435710925399) -->
+ <!-- no translation found for bluetooth_a2dp_codec_sample_rate_titles:0 (7102940318360468759) -->
+ <!-- no translation found for bluetooth_a2dp_codec_sample_rate_titles:1 (8895532488906185219) -->
+ <!-- no translation found for bluetooth_a2dp_codec_sample_rate_titles:2 (2909915718994807056) -->
+ <!-- no translation found for bluetooth_a2dp_codec_sample_rate_titles:3 (3347287377354164611) -->
+ <!-- no translation found for bluetooth_a2dp_codec_sample_rate_titles:4 (1234212100239985373) -->
+ <!-- no translation found for bluetooth_a2dp_codec_sample_rate_summaries:0 (7224433008148687313) -->
+ <!-- no translation found for bluetooth_a2dp_codec_sample_rate_summaries:1 (4482862757811638365) -->
+ <!-- no translation found for bluetooth_a2dp_codec_sample_rate_summaries:2 (354495328188724404) -->
+ <!-- no translation found for bluetooth_a2dp_codec_sample_rate_summaries:3 (7329816882213695083) -->
+ <!-- no translation found for bluetooth_a2dp_codec_sample_rate_summaries:4 (6967397666254430476) -->
+ <!-- no translation found for bluetooth_a2dp_codec_bits_per_sample_titles:0 (6694044160540313386) -->
+ <!-- no translation found for bluetooth_a2dp_codec_bits_per_sample_titles:1 (5618929009984956469) -->
+ <!-- no translation found for bluetooth_a2dp_codec_bits_per_sample_titles:2 (3412640499234627248) -->
+ <!-- no translation found for bluetooth_a2dp_codec_bits_per_sample_titles:3 (121583001492929387) -->
+ <!-- no translation found for bluetooth_a2dp_codec_bits_per_sample_summaries:0 (5091076677792306320) -->
+ <!-- no translation found for bluetooth_a2dp_codec_bits_per_sample_summaries:1 (4726688794884191540) -->
+ <!-- no translation found for bluetooth_a2dp_codec_bits_per_sample_summaries:2 (305344756485516870) -->
+ <!-- no translation found for bluetooth_a2dp_codec_bits_per_sample_summaries:3 (244568657919675099) -->
+ <!-- no translation found for bluetooth_a2dp_codec_channel_mode_titles:0 (13423709606339855) -->
+ <!-- no translation found for bluetooth_a2dp_codec_channel_mode_titles:1 (4106832974775067314) -->
+ <!-- no translation found for bluetooth_a2dp_codec_channel_mode_titles:2 (5571632958424639155) -->
+ <!-- no translation found for bluetooth_a2dp_codec_channel_mode_summaries:0 (8128478683963250130) -->
+ <!-- no translation found for bluetooth_a2dp_codec_channel_mode_summaries:1 (8900559293912978337) -->
+ <!-- no translation found for bluetooth_a2dp_codec_channel_mode_summaries:2 (8883739882299884241) -->
+ <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_titles:0 (2944889121850394020) -->
+ <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_titles:1 (138837449700903545) -->
+ <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_titles:2 (4777177307869441982) -->
+ <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_summaries:0 (172302906231378902) -->
+ <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_summaries:1 (9091111147684472529) -->
+ <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_summaries:2 (3367904477834831032) -->
<string-array name="select_logd_size_titles">
<item msgid="8665206199209698501">"Wył."</item>
<item msgid="1593289376502312923">"64 KB"</item>
diff --git a/packages/SettingsLib/res/values-pl/strings.xml b/packages/SettingsLib/res/values-pl/strings.xml
index 738974f..47ccc23 100644
--- a/packages/SettingsLib/res/values-pl/strings.xml
+++ b/packages/SettingsLib/res/values-pl/strings.xml
@@ -170,6 +170,26 @@
<string name="wifi_allow_scan_with_traffic" msgid="3601853081178265786">"Zawsze szukaj Wi-Fi w roamingu"</string>
<string name="mobile_data_always_on" msgid="7745605759775320362">"Dane komórkowe zawsze aktywne"</string>
<string name="bluetooth_disable_absolute_volume" msgid="2660673801947898809">"Wyłącz głośność bezwzględną"</string>
+ <!-- no translation found for bluetooth_select_a2dp_codec_type (90597356942154882) -->
+ <skip />
+ <!-- no translation found for bluetooth_select_a2dp_codec_type_dialog_title (6470824182074383881) -->
+ <skip />
+ <!-- no translation found for bluetooth_select_a2dp_codec_sample_rate (4788245703824623062) -->
+ <skip />
+ <!-- no translation found for bluetooth_select_a2dp_codec_sample_rate_dialog_title (4263851572248033749) -->
+ <skip />
+ <!-- no translation found for bluetooth_select_a2dp_codec_bits_per_sample (2099645202720164141) -->
+ <skip />
+ <!-- no translation found for bluetooth_select_a2dp_codec_bits_per_sample_dialog_title (2096170505745650345) -->
+ <skip />
+ <!-- no translation found for bluetooth_select_a2dp_codec_channel_mode (884855779449390540) -->
+ <skip />
+ <!-- no translation found for bluetooth_select_a2dp_codec_channel_mode_dialog_title (4073812880900816325) -->
+ <skip />
+ <!-- no translation found for bluetooth_select_a2dp_codec_ldac_playback_quality (4846872213548295632) -->
+ <skip />
+ <!-- no translation found for bluetooth_select_a2dp_codec_ldac_playback_quality_dialog_title (3940973633342423717) -->
+ <skip />
<string name="wifi_display_certification_summary" msgid="1155182309166746973">"Pokaż opcje certyfikacji wyświetlacza bezprzewodowego"</string>
<string name="wifi_verbose_logging_summary" msgid="6615071616111731958">"Zwiększ poziom rejestrowania Wi‑Fi, pokazuj według RSSI SSID w selektorze Wi‑Fi"</string>
<string name="wifi_aggressive_handover_summary" msgid="6328455667642570371">"Po włączeniu połączenie danych będzie bardziej agresywnie przełączać się z Wi-Fi na sieć komórkową przy słabym sygnale Wi-Fi"</string>
diff --git a/packages/SettingsLib/res/values-pt-rBR/arrays.xml b/packages/SettingsLib/res/values-pt-rBR/arrays.xml
index 5e49081b..a7cb364 100644
--- a/packages/SettingsLib/res/values-pt-rBR/arrays.xml
+++ b/packages/SettingsLib/res/values-pt-rBR/arrays.xml
@@ -58,6 +58,46 @@
<item msgid="3878793616631049349">"Usar a verificação HDCP somente para conteúdo DRM"</item>
<item msgid="45075631231212732">"Sempre usar a verificação HDCP"</item>
</string-array>
+ <!-- no translation found for bluetooth_a2dp_codec_titles:0 (1852387125374225729) -->
+ <!-- no translation found for bluetooth_a2dp_codec_titles:1 (7539690996561263909) -->
+ <!-- no translation found for bluetooth_a2dp_codec_titles:2 (4260844283202960798) -->
+ <!-- no translation found for bluetooth_a2dp_codec_titles:3 (7279983368484312990) -->
+ <!-- no translation found for bluetooth_a2dp_codec_titles:4 (2301339338870319651) -->
+ <!-- no translation found for bluetooth_a2dp_codec_summaries:0 (9072025520360316957) -->
+ <!-- no translation found for bluetooth_a2dp_codec_summaries:1 (6898329690939802290) -->
+ <!-- no translation found for bluetooth_a2dp_codec_summaries:2 (1190434429082395888) -->
+ <!-- no translation found for bluetooth_a2dp_codec_summaries:3 (649699003004233053) -->
+ <!-- no translation found for bluetooth_a2dp_codec_summaries:4 (508106435710925399) -->
+ <!-- no translation found for bluetooth_a2dp_codec_sample_rate_titles:0 (7102940318360468759) -->
+ <!-- no translation found for bluetooth_a2dp_codec_sample_rate_titles:1 (8895532488906185219) -->
+ <!-- no translation found for bluetooth_a2dp_codec_sample_rate_titles:2 (2909915718994807056) -->
+ <!-- no translation found for bluetooth_a2dp_codec_sample_rate_titles:3 (3347287377354164611) -->
+ <!-- no translation found for bluetooth_a2dp_codec_sample_rate_titles:4 (1234212100239985373) -->
+ <!-- no translation found for bluetooth_a2dp_codec_sample_rate_summaries:0 (7224433008148687313) -->
+ <!-- no translation found for bluetooth_a2dp_codec_sample_rate_summaries:1 (4482862757811638365) -->
+ <!-- no translation found for bluetooth_a2dp_codec_sample_rate_summaries:2 (354495328188724404) -->
+ <!-- no translation found for bluetooth_a2dp_codec_sample_rate_summaries:3 (7329816882213695083) -->
+ <!-- no translation found for bluetooth_a2dp_codec_sample_rate_summaries:4 (6967397666254430476) -->
+ <!-- no translation found for bluetooth_a2dp_codec_bits_per_sample_titles:0 (6694044160540313386) -->
+ <!-- no translation found for bluetooth_a2dp_codec_bits_per_sample_titles:1 (5618929009984956469) -->
+ <!-- no translation found for bluetooth_a2dp_codec_bits_per_sample_titles:2 (3412640499234627248) -->
+ <!-- no translation found for bluetooth_a2dp_codec_bits_per_sample_titles:3 (121583001492929387) -->
+ <!-- no translation found for bluetooth_a2dp_codec_bits_per_sample_summaries:0 (5091076677792306320) -->
+ <!-- no translation found for bluetooth_a2dp_codec_bits_per_sample_summaries:1 (4726688794884191540) -->
+ <!-- no translation found for bluetooth_a2dp_codec_bits_per_sample_summaries:2 (305344756485516870) -->
+ <!-- no translation found for bluetooth_a2dp_codec_bits_per_sample_summaries:3 (244568657919675099) -->
+ <!-- no translation found for bluetooth_a2dp_codec_channel_mode_titles:0 (13423709606339855) -->
+ <!-- no translation found for bluetooth_a2dp_codec_channel_mode_titles:1 (4106832974775067314) -->
+ <!-- no translation found for bluetooth_a2dp_codec_channel_mode_titles:2 (5571632958424639155) -->
+ <!-- no translation found for bluetooth_a2dp_codec_channel_mode_summaries:0 (8128478683963250130) -->
+ <!-- no translation found for bluetooth_a2dp_codec_channel_mode_summaries:1 (8900559293912978337) -->
+ <!-- no translation found for bluetooth_a2dp_codec_channel_mode_summaries:2 (8883739882299884241) -->
+ <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_titles:0 (2944889121850394020) -->
+ <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_titles:1 (138837449700903545) -->
+ <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_titles:2 (4777177307869441982) -->
+ <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_summaries:0 (172302906231378902) -->
+ <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_summaries:1 (9091111147684472529) -->
+ <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_summaries:2 (3367904477834831032) -->
<string-array name="select_logd_size_titles">
<item msgid="8665206199209698501">"Desativado"</item>
<item msgid="1593289376502312923">"64 K"</item>
diff --git a/packages/SettingsLib/res/values-pt-rBR/strings.xml b/packages/SettingsLib/res/values-pt-rBR/strings.xml
index ab866c8..eb435a6 100644
--- a/packages/SettingsLib/res/values-pt-rBR/strings.xml
+++ b/packages/SettingsLib/res/values-pt-rBR/strings.xml
@@ -170,6 +170,26 @@
<string name="wifi_allow_scan_with_traffic" msgid="3601853081178265786">"Sempre permitir verif. de roaming de Wi-Fi"</string>
<string name="mobile_data_always_on" msgid="7745605759775320362">"Dados da rede celular sempre ativos"</string>
<string name="bluetooth_disable_absolute_volume" msgid="2660673801947898809">"Desativar volume absoluto"</string>
+ <!-- no translation found for bluetooth_select_a2dp_codec_type (90597356942154882) -->
+ <skip />
+ <!-- no translation found for bluetooth_select_a2dp_codec_type_dialog_title (6470824182074383881) -->
+ <skip />
+ <!-- no translation found for bluetooth_select_a2dp_codec_sample_rate (4788245703824623062) -->
+ <skip />
+ <!-- no translation found for bluetooth_select_a2dp_codec_sample_rate_dialog_title (4263851572248033749) -->
+ <skip />
+ <!-- no translation found for bluetooth_select_a2dp_codec_bits_per_sample (2099645202720164141) -->
+ <skip />
+ <!-- no translation found for bluetooth_select_a2dp_codec_bits_per_sample_dialog_title (2096170505745650345) -->
+ <skip />
+ <!-- no translation found for bluetooth_select_a2dp_codec_channel_mode (884855779449390540) -->
+ <skip />
+ <!-- no translation found for bluetooth_select_a2dp_codec_channel_mode_dialog_title (4073812880900816325) -->
+ <skip />
+ <!-- no translation found for bluetooth_select_a2dp_codec_ldac_playback_quality (4846872213548295632) -->
+ <skip />
+ <!-- no translation found for bluetooth_select_a2dp_codec_ldac_playback_quality_dialog_title (3940973633342423717) -->
+ <skip />
<string name="wifi_display_certification_summary" msgid="1155182309166746973">"Mostrar opções de certificação de Display sem fio"</string>
<string name="wifi_verbose_logging_summary" msgid="6615071616111731958">"Aumentar o nível de registro do Wi-Fi; mostrar conforme o RSSI de SSID na Seleção de Wi-Fi"</string>
<string name="wifi_aggressive_handover_summary" msgid="6328455667642570371">"Quando ativada, o Wi-Fi será mais agressivo em transferir a conexão de dados para celular, quando o sinal de Wi-Fi estiver fraco"</string>
diff --git a/packages/SettingsLib/res/values-pt-rPT/arrays.xml b/packages/SettingsLib/res/values-pt-rPT/arrays.xml
index 06d4558..6fc7b2f 100644
--- a/packages/SettingsLib/res/values-pt-rPT/arrays.xml
+++ b/packages/SettingsLib/res/values-pt-rPT/arrays.xml
@@ -58,6 +58,46 @@
<item msgid="3878793616631049349">"Utilizar a verificação HDCP para conteúdo DRM apenas"</item>
<item msgid="45075631231212732">"Utilizar sempre a verificação HDCP"</item>
</string-array>
+ <!-- no translation found for bluetooth_a2dp_codec_titles:0 (1852387125374225729) -->
+ <!-- no translation found for bluetooth_a2dp_codec_titles:1 (7539690996561263909) -->
+ <!-- no translation found for bluetooth_a2dp_codec_titles:2 (4260844283202960798) -->
+ <!-- no translation found for bluetooth_a2dp_codec_titles:3 (7279983368484312990) -->
+ <!-- no translation found for bluetooth_a2dp_codec_titles:4 (2301339338870319651) -->
+ <!-- no translation found for bluetooth_a2dp_codec_summaries:0 (9072025520360316957) -->
+ <!-- no translation found for bluetooth_a2dp_codec_summaries:1 (6898329690939802290) -->
+ <!-- no translation found for bluetooth_a2dp_codec_summaries:2 (1190434429082395888) -->
+ <!-- no translation found for bluetooth_a2dp_codec_summaries:3 (649699003004233053) -->
+ <!-- no translation found for bluetooth_a2dp_codec_summaries:4 (508106435710925399) -->
+ <!-- no translation found for bluetooth_a2dp_codec_sample_rate_titles:0 (7102940318360468759) -->
+ <!-- no translation found for bluetooth_a2dp_codec_sample_rate_titles:1 (8895532488906185219) -->
+ <!-- no translation found for bluetooth_a2dp_codec_sample_rate_titles:2 (2909915718994807056) -->
+ <!-- no translation found for bluetooth_a2dp_codec_sample_rate_titles:3 (3347287377354164611) -->
+ <!-- no translation found for bluetooth_a2dp_codec_sample_rate_titles:4 (1234212100239985373) -->
+ <!-- no translation found for bluetooth_a2dp_codec_sample_rate_summaries:0 (7224433008148687313) -->
+ <!-- no translation found for bluetooth_a2dp_codec_sample_rate_summaries:1 (4482862757811638365) -->
+ <!-- no translation found for bluetooth_a2dp_codec_sample_rate_summaries:2 (354495328188724404) -->
+ <!-- no translation found for bluetooth_a2dp_codec_sample_rate_summaries:3 (7329816882213695083) -->
+ <!-- no translation found for bluetooth_a2dp_codec_sample_rate_summaries:4 (6967397666254430476) -->
+ <!-- no translation found for bluetooth_a2dp_codec_bits_per_sample_titles:0 (6694044160540313386) -->
+ <!-- no translation found for bluetooth_a2dp_codec_bits_per_sample_titles:1 (5618929009984956469) -->
+ <!-- no translation found for bluetooth_a2dp_codec_bits_per_sample_titles:2 (3412640499234627248) -->
+ <!-- no translation found for bluetooth_a2dp_codec_bits_per_sample_titles:3 (121583001492929387) -->
+ <!-- no translation found for bluetooth_a2dp_codec_bits_per_sample_summaries:0 (5091076677792306320) -->
+ <!-- no translation found for bluetooth_a2dp_codec_bits_per_sample_summaries:1 (4726688794884191540) -->
+ <!-- no translation found for bluetooth_a2dp_codec_bits_per_sample_summaries:2 (305344756485516870) -->
+ <!-- no translation found for bluetooth_a2dp_codec_bits_per_sample_summaries:3 (244568657919675099) -->
+ <!-- no translation found for bluetooth_a2dp_codec_channel_mode_titles:0 (13423709606339855) -->
+ <!-- no translation found for bluetooth_a2dp_codec_channel_mode_titles:1 (4106832974775067314) -->
+ <!-- no translation found for bluetooth_a2dp_codec_channel_mode_titles:2 (5571632958424639155) -->
+ <!-- no translation found for bluetooth_a2dp_codec_channel_mode_summaries:0 (8128478683963250130) -->
+ <!-- no translation found for bluetooth_a2dp_codec_channel_mode_summaries:1 (8900559293912978337) -->
+ <!-- no translation found for bluetooth_a2dp_codec_channel_mode_summaries:2 (8883739882299884241) -->
+ <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_titles:0 (2944889121850394020) -->
+ <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_titles:1 (138837449700903545) -->
+ <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_titles:2 (4777177307869441982) -->
+ <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_summaries:0 (172302906231378902) -->
+ <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_summaries:1 (9091111147684472529) -->
+ <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_summaries:2 (3367904477834831032) -->
<string-array name="select_logd_size_titles">
<item msgid="8665206199209698501">"Desativado"</item>
<item msgid="1593289376502312923">"64 K"</item>
diff --git a/packages/SettingsLib/res/values-pt-rPT/strings.xml b/packages/SettingsLib/res/values-pt-rPT/strings.xml
index 2e4bbdc8..df090d5 100644
--- a/packages/SettingsLib/res/values-pt-rPT/strings.xml
+++ b/packages/SettingsLib/res/values-pt-rPT/strings.xml
@@ -170,6 +170,26 @@
<string name="wifi_allow_scan_with_traffic" msgid="3601853081178265786">"Permitir sempre a deteção de Wi-Fi em roaming"</string>
<string name="mobile_data_always_on" msgid="7745605759775320362">"Dados móveis sempre ativados"</string>
<string name="bluetooth_disable_absolute_volume" msgid="2660673801947898809">"Desativar volume absoluto"</string>
+ <!-- no translation found for bluetooth_select_a2dp_codec_type (90597356942154882) -->
+ <skip />
+ <!-- no translation found for bluetooth_select_a2dp_codec_type_dialog_title (6470824182074383881) -->
+ <skip />
+ <!-- no translation found for bluetooth_select_a2dp_codec_sample_rate (4788245703824623062) -->
+ <skip />
+ <!-- no translation found for bluetooth_select_a2dp_codec_sample_rate_dialog_title (4263851572248033749) -->
+ <skip />
+ <!-- no translation found for bluetooth_select_a2dp_codec_bits_per_sample (2099645202720164141) -->
+ <skip />
+ <!-- no translation found for bluetooth_select_a2dp_codec_bits_per_sample_dialog_title (2096170505745650345) -->
+ <skip />
+ <!-- no translation found for bluetooth_select_a2dp_codec_channel_mode (884855779449390540) -->
+ <skip />
+ <!-- no translation found for bluetooth_select_a2dp_codec_channel_mode_dialog_title (4073812880900816325) -->
+ <skip />
+ <!-- no translation found for bluetooth_select_a2dp_codec_ldac_playback_quality (4846872213548295632) -->
+ <skip />
+ <!-- no translation found for bluetooth_select_a2dp_codec_ldac_playback_quality_dialog_title (3940973633342423717) -->
+ <skip />
<string name="wifi_display_certification_summary" msgid="1155182309166746973">"Mostrar opções da certificação de display sem fios"</string>
<string name="wifi_verbose_logging_summary" msgid="6615071616111731958">"Aumentar o nível de reg. de Wi-Fi, mostrar por RSSI de SSID no Selec. de Wi-Fi"</string>
<string name="wifi_aggressive_handover_summary" msgid="6328455667642570371">"Se estiver ativado, o Wi-Fi será mais agressivo ao transmitir a lig. de dados p/ a rede móvel quando o sinal Wi-Fi estiver fraco"</string>
diff --git a/packages/SettingsLib/res/values-pt/arrays.xml b/packages/SettingsLib/res/values-pt/arrays.xml
index 5e49081b..a7cb364 100644
--- a/packages/SettingsLib/res/values-pt/arrays.xml
+++ b/packages/SettingsLib/res/values-pt/arrays.xml
@@ -58,6 +58,46 @@
<item msgid="3878793616631049349">"Usar a verificação HDCP somente para conteúdo DRM"</item>
<item msgid="45075631231212732">"Sempre usar a verificação HDCP"</item>
</string-array>
+ <!-- no translation found for bluetooth_a2dp_codec_titles:0 (1852387125374225729) -->
+ <!-- no translation found for bluetooth_a2dp_codec_titles:1 (7539690996561263909) -->
+ <!-- no translation found for bluetooth_a2dp_codec_titles:2 (4260844283202960798) -->
+ <!-- no translation found for bluetooth_a2dp_codec_titles:3 (7279983368484312990) -->
+ <!-- no translation found for bluetooth_a2dp_codec_titles:4 (2301339338870319651) -->
+ <!-- no translation found for bluetooth_a2dp_codec_summaries:0 (9072025520360316957) -->
+ <!-- no translation found for bluetooth_a2dp_codec_summaries:1 (6898329690939802290) -->
+ <!-- no translation found for bluetooth_a2dp_codec_summaries:2 (1190434429082395888) -->
+ <!-- no translation found for bluetooth_a2dp_codec_summaries:3 (649699003004233053) -->
+ <!-- no translation found for bluetooth_a2dp_codec_summaries:4 (508106435710925399) -->
+ <!-- no translation found for bluetooth_a2dp_codec_sample_rate_titles:0 (7102940318360468759) -->
+ <!-- no translation found for bluetooth_a2dp_codec_sample_rate_titles:1 (8895532488906185219) -->
+ <!-- no translation found for bluetooth_a2dp_codec_sample_rate_titles:2 (2909915718994807056) -->
+ <!-- no translation found for bluetooth_a2dp_codec_sample_rate_titles:3 (3347287377354164611) -->
+ <!-- no translation found for bluetooth_a2dp_codec_sample_rate_titles:4 (1234212100239985373) -->
+ <!-- no translation found for bluetooth_a2dp_codec_sample_rate_summaries:0 (7224433008148687313) -->
+ <!-- no translation found for bluetooth_a2dp_codec_sample_rate_summaries:1 (4482862757811638365) -->
+ <!-- no translation found for bluetooth_a2dp_codec_sample_rate_summaries:2 (354495328188724404) -->
+ <!-- no translation found for bluetooth_a2dp_codec_sample_rate_summaries:3 (7329816882213695083) -->
+ <!-- no translation found for bluetooth_a2dp_codec_sample_rate_summaries:4 (6967397666254430476) -->
+ <!-- no translation found for bluetooth_a2dp_codec_bits_per_sample_titles:0 (6694044160540313386) -->
+ <!-- no translation found for bluetooth_a2dp_codec_bits_per_sample_titles:1 (5618929009984956469) -->
+ <!-- no translation found for bluetooth_a2dp_codec_bits_per_sample_titles:2 (3412640499234627248) -->
+ <!-- no translation found for bluetooth_a2dp_codec_bits_per_sample_titles:3 (121583001492929387) -->
+ <!-- no translation found for bluetooth_a2dp_codec_bits_per_sample_summaries:0 (5091076677792306320) -->
+ <!-- no translation found for bluetooth_a2dp_codec_bits_per_sample_summaries:1 (4726688794884191540) -->
+ <!-- no translation found for bluetooth_a2dp_codec_bits_per_sample_summaries:2 (305344756485516870) -->
+ <!-- no translation found for bluetooth_a2dp_codec_bits_per_sample_summaries:3 (244568657919675099) -->
+ <!-- no translation found for bluetooth_a2dp_codec_channel_mode_titles:0 (13423709606339855) -->
+ <!-- no translation found for bluetooth_a2dp_codec_channel_mode_titles:1 (4106832974775067314) -->
+ <!-- no translation found for bluetooth_a2dp_codec_channel_mode_titles:2 (5571632958424639155) -->
+ <!-- no translation found for bluetooth_a2dp_codec_channel_mode_summaries:0 (8128478683963250130) -->
+ <!-- no translation found for bluetooth_a2dp_codec_channel_mode_summaries:1 (8900559293912978337) -->
+ <!-- no translation found for bluetooth_a2dp_codec_channel_mode_summaries:2 (8883739882299884241) -->
+ <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_titles:0 (2944889121850394020) -->
+ <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_titles:1 (138837449700903545) -->
+ <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_titles:2 (4777177307869441982) -->
+ <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_summaries:0 (172302906231378902) -->
+ <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_summaries:1 (9091111147684472529) -->
+ <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_summaries:2 (3367904477834831032) -->
<string-array name="select_logd_size_titles">
<item msgid="8665206199209698501">"Desativado"</item>
<item msgid="1593289376502312923">"64 K"</item>
diff --git a/packages/SettingsLib/res/values-pt/strings.xml b/packages/SettingsLib/res/values-pt/strings.xml
index ab866c8..eb435a6 100644
--- a/packages/SettingsLib/res/values-pt/strings.xml
+++ b/packages/SettingsLib/res/values-pt/strings.xml
@@ -170,6 +170,26 @@
<string name="wifi_allow_scan_with_traffic" msgid="3601853081178265786">"Sempre permitir verif. de roaming de Wi-Fi"</string>
<string name="mobile_data_always_on" msgid="7745605759775320362">"Dados da rede celular sempre ativos"</string>
<string name="bluetooth_disable_absolute_volume" msgid="2660673801947898809">"Desativar volume absoluto"</string>
+ <!-- no translation found for bluetooth_select_a2dp_codec_type (90597356942154882) -->
+ <skip />
+ <!-- no translation found for bluetooth_select_a2dp_codec_type_dialog_title (6470824182074383881) -->
+ <skip />
+ <!-- no translation found for bluetooth_select_a2dp_codec_sample_rate (4788245703824623062) -->
+ <skip />
+ <!-- no translation found for bluetooth_select_a2dp_codec_sample_rate_dialog_title (4263851572248033749) -->
+ <skip />
+ <!-- no translation found for bluetooth_select_a2dp_codec_bits_per_sample (2099645202720164141) -->
+ <skip />
+ <!-- no translation found for bluetooth_select_a2dp_codec_bits_per_sample_dialog_title (2096170505745650345) -->
+ <skip />
+ <!-- no translation found for bluetooth_select_a2dp_codec_channel_mode (884855779449390540) -->
+ <skip />
+ <!-- no translation found for bluetooth_select_a2dp_codec_channel_mode_dialog_title (4073812880900816325) -->
+ <skip />
+ <!-- no translation found for bluetooth_select_a2dp_codec_ldac_playback_quality (4846872213548295632) -->
+ <skip />
+ <!-- no translation found for bluetooth_select_a2dp_codec_ldac_playback_quality_dialog_title (3940973633342423717) -->
+ <skip />
<string name="wifi_display_certification_summary" msgid="1155182309166746973">"Mostrar opções de certificação de Display sem fio"</string>
<string name="wifi_verbose_logging_summary" msgid="6615071616111731958">"Aumentar o nível de registro do Wi-Fi; mostrar conforme o RSSI de SSID na Seleção de Wi-Fi"</string>
<string name="wifi_aggressive_handover_summary" msgid="6328455667642570371">"Quando ativada, o Wi-Fi será mais agressivo em transferir a conexão de dados para celular, quando o sinal de Wi-Fi estiver fraco"</string>
diff --git a/packages/SettingsLib/res/values-ro/arrays.xml b/packages/SettingsLib/res/values-ro/arrays.xml
index 46773e9..24a0c3d 100644
--- a/packages/SettingsLib/res/values-ro/arrays.xml
+++ b/packages/SettingsLib/res/values-ro/arrays.xml
@@ -58,6 +58,46 @@
<item msgid="3878793616631049349">"Utilizează verificarea HDCP numai pentru conținut DRM"</item>
<item msgid="45075631231212732">"Utilizează întotdeauna verificarea HDCP"</item>
</string-array>
+ <!-- no translation found for bluetooth_a2dp_codec_titles:0 (1852387125374225729) -->
+ <!-- no translation found for bluetooth_a2dp_codec_titles:1 (7539690996561263909) -->
+ <!-- no translation found for bluetooth_a2dp_codec_titles:2 (4260844283202960798) -->
+ <!-- no translation found for bluetooth_a2dp_codec_titles:3 (7279983368484312990) -->
+ <!-- no translation found for bluetooth_a2dp_codec_titles:4 (2301339338870319651) -->
+ <!-- no translation found for bluetooth_a2dp_codec_summaries:0 (9072025520360316957) -->
+ <!-- no translation found for bluetooth_a2dp_codec_summaries:1 (6898329690939802290) -->
+ <!-- no translation found for bluetooth_a2dp_codec_summaries:2 (1190434429082395888) -->
+ <!-- no translation found for bluetooth_a2dp_codec_summaries:3 (649699003004233053) -->
+ <!-- no translation found for bluetooth_a2dp_codec_summaries:4 (508106435710925399) -->
+ <!-- no translation found for bluetooth_a2dp_codec_sample_rate_titles:0 (7102940318360468759) -->
+ <!-- no translation found for bluetooth_a2dp_codec_sample_rate_titles:1 (8895532488906185219) -->
+ <!-- no translation found for bluetooth_a2dp_codec_sample_rate_titles:2 (2909915718994807056) -->
+ <!-- no translation found for bluetooth_a2dp_codec_sample_rate_titles:3 (3347287377354164611) -->
+ <!-- no translation found for bluetooth_a2dp_codec_sample_rate_titles:4 (1234212100239985373) -->
+ <!-- no translation found for bluetooth_a2dp_codec_sample_rate_summaries:0 (7224433008148687313) -->
+ <!-- no translation found for bluetooth_a2dp_codec_sample_rate_summaries:1 (4482862757811638365) -->
+ <!-- no translation found for bluetooth_a2dp_codec_sample_rate_summaries:2 (354495328188724404) -->
+ <!-- no translation found for bluetooth_a2dp_codec_sample_rate_summaries:3 (7329816882213695083) -->
+ <!-- no translation found for bluetooth_a2dp_codec_sample_rate_summaries:4 (6967397666254430476) -->
+ <!-- no translation found for bluetooth_a2dp_codec_bits_per_sample_titles:0 (6694044160540313386) -->
+ <!-- no translation found for bluetooth_a2dp_codec_bits_per_sample_titles:1 (5618929009984956469) -->
+ <!-- no translation found for bluetooth_a2dp_codec_bits_per_sample_titles:2 (3412640499234627248) -->
+ <!-- no translation found for bluetooth_a2dp_codec_bits_per_sample_titles:3 (121583001492929387) -->
+ <!-- no translation found for bluetooth_a2dp_codec_bits_per_sample_summaries:0 (5091076677792306320) -->
+ <!-- no translation found for bluetooth_a2dp_codec_bits_per_sample_summaries:1 (4726688794884191540) -->
+ <!-- no translation found for bluetooth_a2dp_codec_bits_per_sample_summaries:2 (305344756485516870) -->
+ <!-- no translation found for bluetooth_a2dp_codec_bits_per_sample_summaries:3 (244568657919675099) -->
+ <!-- no translation found for bluetooth_a2dp_codec_channel_mode_titles:0 (13423709606339855) -->
+ <!-- no translation found for bluetooth_a2dp_codec_channel_mode_titles:1 (4106832974775067314) -->
+ <!-- no translation found for bluetooth_a2dp_codec_channel_mode_titles:2 (5571632958424639155) -->
+ <!-- no translation found for bluetooth_a2dp_codec_channel_mode_summaries:0 (8128478683963250130) -->
+ <!-- no translation found for bluetooth_a2dp_codec_channel_mode_summaries:1 (8900559293912978337) -->
+ <!-- no translation found for bluetooth_a2dp_codec_channel_mode_summaries:2 (8883739882299884241) -->
+ <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_titles:0 (2944889121850394020) -->
+ <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_titles:1 (138837449700903545) -->
+ <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_titles:2 (4777177307869441982) -->
+ <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_summaries:0 (172302906231378902) -->
+ <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_summaries:1 (9091111147684472529) -->
+ <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_summaries:2 (3367904477834831032) -->
<string-array name="select_logd_size_titles">
<item msgid="8665206199209698501">"Dezactivată"</item>
<item msgid="1593289376502312923">"64 KB"</item>
diff --git a/packages/SettingsLib/res/values-ro/strings.xml b/packages/SettingsLib/res/values-ro/strings.xml
index da2f76f..acc53ae 100644
--- a/packages/SettingsLib/res/values-ro/strings.xml
+++ b/packages/SettingsLib/res/values-ro/strings.xml
@@ -170,6 +170,26 @@
<string name="wifi_allow_scan_with_traffic" msgid="3601853081178265786">"Se permite întotdeauna scanarea traficului Wi-Fi"</string>
<string name="mobile_data_always_on" msgid="7745605759775320362">"Conexiunea de date mobile este întotdeauna activată"</string>
<string name="bluetooth_disable_absolute_volume" msgid="2660673801947898809">"Dezactivați volumul absolut"</string>
+ <!-- no translation found for bluetooth_select_a2dp_codec_type (90597356942154882) -->
+ <skip />
+ <!-- no translation found for bluetooth_select_a2dp_codec_type_dialog_title (6470824182074383881) -->
+ <skip />
+ <!-- no translation found for bluetooth_select_a2dp_codec_sample_rate (4788245703824623062) -->
+ <skip />
+ <!-- no translation found for bluetooth_select_a2dp_codec_sample_rate_dialog_title (4263851572248033749) -->
+ <skip />
+ <!-- no translation found for bluetooth_select_a2dp_codec_bits_per_sample (2099645202720164141) -->
+ <skip />
+ <!-- no translation found for bluetooth_select_a2dp_codec_bits_per_sample_dialog_title (2096170505745650345) -->
+ <skip />
+ <!-- no translation found for bluetooth_select_a2dp_codec_channel_mode (884855779449390540) -->
+ <skip />
+ <!-- no translation found for bluetooth_select_a2dp_codec_channel_mode_dialog_title (4073812880900816325) -->
+ <skip />
+ <!-- no translation found for bluetooth_select_a2dp_codec_ldac_playback_quality (4846872213548295632) -->
+ <skip />
+ <!-- no translation found for bluetooth_select_a2dp_codec_ldac_playback_quality_dialog_title (3940973633342423717) -->
+ <skip />
<string name="wifi_display_certification_summary" msgid="1155182309166746973">"Afișați opțiunile pentru certificarea Ecran wireless"</string>
<string name="wifi_verbose_logging_summary" msgid="6615071616111731958">"Măriți niv. de înr. prin Wi‑Fi, afișați în fcț. de SSID RSSI în Selectorul Wi‑Fi"</string>
<string name="wifi_aggressive_handover_summary" msgid="6328455667642570371">"Când este activată, funcția Wi-Fi va fi mai agresivă la predarea conexiunii de date către mobil când semnalul Wi-Fi este slab"</string>
diff --git a/packages/SettingsLib/res/values-ru/arrays.xml b/packages/SettingsLib/res/values-ru/arrays.xml
index 0e4816c..eef0e4a 100644
--- a/packages/SettingsLib/res/values-ru/arrays.xml
+++ b/packages/SettingsLib/res/values-ru/arrays.xml
@@ -58,6 +58,46 @@
<item msgid="3878793616631049349">"Использовать проверку HDCP только для DRM-контента"</item>
<item msgid="45075631231212732">"Всегда использовать проверку HDCP"</item>
</string-array>
+ <!-- no translation found for bluetooth_a2dp_codec_titles:0 (1852387125374225729) -->
+ <!-- no translation found for bluetooth_a2dp_codec_titles:1 (7539690996561263909) -->
+ <!-- no translation found for bluetooth_a2dp_codec_titles:2 (4260844283202960798) -->
+ <!-- no translation found for bluetooth_a2dp_codec_titles:3 (7279983368484312990) -->
+ <!-- no translation found for bluetooth_a2dp_codec_titles:4 (2301339338870319651) -->
+ <!-- no translation found for bluetooth_a2dp_codec_summaries:0 (9072025520360316957) -->
+ <!-- no translation found for bluetooth_a2dp_codec_summaries:1 (6898329690939802290) -->
+ <!-- no translation found for bluetooth_a2dp_codec_summaries:2 (1190434429082395888) -->
+ <!-- no translation found for bluetooth_a2dp_codec_summaries:3 (649699003004233053) -->
+ <!-- no translation found for bluetooth_a2dp_codec_summaries:4 (508106435710925399) -->
+ <!-- no translation found for bluetooth_a2dp_codec_sample_rate_titles:0 (7102940318360468759) -->
+ <!-- no translation found for bluetooth_a2dp_codec_sample_rate_titles:1 (8895532488906185219) -->
+ <!-- no translation found for bluetooth_a2dp_codec_sample_rate_titles:2 (2909915718994807056) -->
+ <!-- no translation found for bluetooth_a2dp_codec_sample_rate_titles:3 (3347287377354164611) -->
+ <!-- no translation found for bluetooth_a2dp_codec_sample_rate_titles:4 (1234212100239985373) -->
+ <!-- no translation found for bluetooth_a2dp_codec_sample_rate_summaries:0 (7224433008148687313) -->
+ <!-- no translation found for bluetooth_a2dp_codec_sample_rate_summaries:1 (4482862757811638365) -->
+ <!-- no translation found for bluetooth_a2dp_codec_sample_rate_summaries:2 (354495328188724404) -->
+ <!-- no translation found for bluetooth_a2dp_codec_sample_rate_summaries:3 (7329816882213695083) -->
+ <!-- no translation found for bluetooth_a2dp_codec_sample_rate_summaries:4 (6967397666254430476) -->
+ <!-- no translation found for bluetooth_a2dp_codec_bits_per_sample_titles:0 (6694044160540313386) -->
+ <!-- no translation found for bluetooth_a2dp_codec_bits_per_sample_titles:1 (5618929009984956469) -->
+ <!-- no translation found for bluetooth_a2dp_codec_bits_per_sample_titles:2 (3412640499234627248) -->
+ <!-- no translation found for bluetooth_a2dp_codec_bits_per_sample_titles:3 (121583001492929387) -->
+ <!-- no translation found for bluetooth_a2dp_codec_bits_per_sample_summaries:0 (5091076677792306320) -->
+ <!-- no translation found for bluetooth_a2dp_codec_bits_per_sample_summaries:1 (4726688794884191540) -->
+ <!-- no translation found for bluetooth_a2dp_codec_bits_per_sample_summaries:2 (305344756485516870) -->
+ <!-- no translation found for bluetooth_a2dp_codec_bits_per_sample_summaries:3 (244568657919675099) -->
+ <!-- no translation found for bluetooth_a2dp_codec_channel_mode_titles:0 (13423709606339855) -->
+ <!-- no translation found for bluetooth_a2dp_codec_channel_mode_titles:1 (4106832974775067314) -->
+ <!-- no translation found for bluetooth_a2dp_codec_channel_mode_titles:2 (5571632958424639155) -->
+ <!-- no translation found for bluetooth_a2dp_codec_channel_mode_summaries:0 (8128478683963250130) -->
+ <!-- no translation found for bluetooth_a2dp_codec_channel_mode_summaries:1 (8900559293912978337) -->
+ <!-- no translation found for bluetooth_a2dp_codec_channel_mode_summaries:2 (8883739882299884241) -->
+ <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_titles:0 (2944889121850394020) -->
+ <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_titles:1 (138837449700903545) -->
+ <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_titles:2 (4777177307869441982) -->
+ <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_summaries:0 (172302906231378902) -->
+ <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_summaries:1 (9091111147684472529) -->
+ <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_summaries:2 (3367904477834831032) -->
<string-array name="select_logd_size_titles">
<item msgid="8665206199209698501">"Выкл."</item>
<item msgid="1593289376502312923">"64 КБ"</item>
diff --git a/packages/SettingsLib/res/values-ru/strings.xml b/packages/SettingsLib/res/values-ru/strings.xml
index 9600027..5904c70 100644
--- a/packages/SettingsLib/res/values-ru/strings.xml
+++ b/packages/SettingsLib/res/values-ru/strings.xml
@@ -170,6 +170,26 @@
<string name="wifi_allow_scan_with_traffic" msgid="3601853081178265786">"Всегда включать поиск сетей Wi-Fi"</string>
<string name="mobile_data_always_on" msgid="7745605759775320362">"Не отключать передачу данных"</string>
<string name="bluetooth_disable_absolute_volume" msgid="2660673801947898809">"Отключить абсолютный уровень громкости"</string>
+ <!-- no translation found for bluetooth_select_a2dp_codec_type (90597356942154882) -->
+ <skip />
+ <!-- no translation found for bluetooth_select_a2dp_codec_type_dialog_title (6470824182074383881) -->
+ <skip />
+ <!-- no translation found for bluetooth_select_a2dp_codec_sample_rate (4788245703824623062) -->
+ <skip />
+ <!-- no translation found for bluetooth_select_a2dp_codec_sample_rate_dialog_title (4263851572248033749) -->
+ <skip />
+ <!-- no translation found for bluetooth_select_a2dp_codec_bits_per_sample (2099645202720164141) -->
+ <skip />
+ <!-- no translation found for bluetooth_select_a2dp_codec_bits_per_sample_dialog_title (2096170505745650345) -->
+ <skip />
+ <!-- no translation found for bluetooth_select_a2dp_codec_channel_mode (884855779449390540) -->
+ <skip />
+ <!-- no translation found for bluetooth_select_a2dp_codec_channel_mode_dialog_title (4073812880900816325) -->
+ <skip />
+ <!-- no translation found for bluetooth_select_a2dp_codec_ldac_playback_quality (4846872213548295632) -->
+ <skip />
+ <!-- no translation found for bluetooth_select_a2dp_codec_ldac_playback_quality_dialog_title (3940973633342423717) -->
+ <skip />
<string name="wifi_display_certification_summary" msgid="1155182309166746973">"Показывать параметры сертификации беспроводных мониторов"</string>
<string name="wifi_verbose_logging_summary" msgid="6615071616111731958">"При выборе Wi‑Fi указывать в журнале RSSI для каждого SSID"</string>
<string name="wifi_aggressive_handover_summary" msgid="6328455667642570371">"Принудительно переключаться на мобильную сеть, если сигнал Wi-Fi слабый"</string>
diff --git a/packages/SettingsLib/res/values-si-rLK/arrays.xml b/packages/SettingsLib/res/values-si-rLK/arrays.xml
index ac1a6fe..45b6cf3 100644
--- a/packages/SettingsLib/res/values-si-rLK/arrays.xml
+++ b/packages/SettingsLib/res/values-si-rLK/arrays.xml
@@ -58,6 +58,46 @@
<item msgid="3878793616631049349">"DRM අන්තර්ගත සඳහා පමණක් HDCP පරික්ෂාව භාවිතා කරන්න"</item>
<item msgid="45075631231212732">"සැමවිටම HDCP පිරික්සුම භාවිතා කරන්න"</item>
</string-array>
+ <!-- no translation found for bluetooth_a2dp_codec_titles:0 (1852387125374225729) -->
+ <!-- no translation found for bluetooth_a2dp_codec_titles:1 (7539690996561263909) -->
+ <!-- no translation found for bluetooth_a2dp_codec_titles:2 (4260844283202960798) -->
+ <!-- no translation found for bluetooth_a2dp_codec_titles:3 (7279983368484312990) -->
+ <!-- no translation found for bluetooth_a2dp_codec_titles:4 (2301339338870319651) -->
+ <!-- no translation found for bluetooth_a2dp_codec_summaries:0 (9072025520360316957) -->
+ <!-- no translation found for bluetooth_a2dp_codec_summaries:1 (6898329690939802290) -->
+ <!-- no translation found for bluetooth_a2dp_codec_summaries:2 (1190434429082395888) -->
+ <!-- no translation found for bluetooth_a2dp_codec_summaries:3 (649699003004233053) -->
+ <!-- no translation found for bluetooth_a2dp_codec_summaries:4 (508106435710925399) -->
+ <!-- no translation found for bluetooth_a2dp_codec_sample_rate_titles:0 (7102940318360468759) -->
+ <!-- no translation found for bluetooth_a2dp_codec_sample_rate_titles:1 (8895532488906185219) -->
+ <!-- no translation found for bluetooth_a2dp_codec_sample_rate_titles:2 (2909915718994807056) -->
+ <!-- no translation found for bluetooth_a2dp_codec_sample_rate_titles:3 (3347287377354164611) -->
+ <!-- no translation found for bluetooth_a2dp_codec_sample_rate_titles:4 (1234212100239985373) -->
+ <!-- no translation found for bluetooth_a2dp_codec_sample_rate_summaries:0 (7224433008148687313) -->
+ <!-- no translation found for bluetooth_a2dp_codec_sample_rate_summaries:1 (4482862757811638365) -->
+ <!-- no translation found for bluetooth_a2dp_codec_sample_rate_summaries:2 (354495328188724404) -->
+ <!-- no translation found for bluetooth_a2dp_codec_sample_rate_summaries:3 (7329816882213695083) -->
+ <!-- no translation found for bluetooth_a2dp_codec_sample_rate_summaries:4 (6967397666254430476) -->
+ <!-- no translation found for bluetooth_a2dp_codec_bits_per_sample_titles:0 (6694044160540313386) -->
+ <!-- no translation found for bluetooth_a2dp_codec_bits_per_sample_titles:1 (5618929009984956469) -->
+ <!-- no translation found for bluetooth_a2dp_codec_bits_per_sample_titles:2 (3412640499234627248) -->
+ <!-- no translation found for bluetooth_a2dp_codec_bits_per_sample_titles:3 (121583001492929387) -->
+ <!-- no translation found for bluetooth_a2dp_codec_bits_per_sample_summaries:0 (5091076677792306320) -->
+ <!-- no translation found for bluetooth_a2dp_codec_bits_per_sample_summaries:1 (4726688794884191540) -->
+ <!-- no translation found for bluetooth_a2dp_codec_bits_per_sample_summaries:2 (305344756485516870) -->
+ <!-- no translation found for bluetooth_a2dp_codec_bits_per_sample_summaries:3 (244568657919675099) -->
+ <!-- no translation found for bluetooth_a2dp_codec_channel_mode_titles:0 (13423709606339855) -->
+ <!-- no translation found for bluetooth_a2dp_codec_channel_mode_titles:1 (4106832974775067314) -->
+ <!-- no translation found for bluetooth_a2dp_codec_channel_mode_titles:2 (5571632958424639155) -->
+ <!-- no translation found for bluetooth_a2dp_codec_channel_mode_summaries:0 (8128478683963250130) -->
+ <!-- no translation found for bluetooth_a2dp_codec_channel_mode_summaries:1 (8900559293912978337) -->
+ <!-- no translation found for bluetooth_a2dp_codec_channel_mode_summaries:2 (8883739882299884241) -->
+ <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_titles:0 (2944889121850394020) -->
+ <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_titles:1 (138837449700903545) -->
+ <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_titles:2 (4777177307869441982) -->
+ <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_summaries:0 (172302906231378902) -->
+ <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_summaries:1 (9091111147684472529) -->
+ <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_summaries:2 (3367904477834831032) -->
<string-array name="select_logd_size_titles">
<item msgid="8665206199209698501">"ක්රියාවිරහිතය"</item>
<item msgid="1593289376502312923">"64K"</item>
diff --git a/packages/SettingsLib/res/values-si-rLK/strings.xml b/packages/SettingsLib/res/values-si-rLK/strings.xml
index b775db6..3347b12 100644
--- a/packages/SettingsLib/res/values-si-rLK/strings.xml
+++ b/packages/SettingsLib/res/values-si-rLK/strings.xml
@@ -170,6 +170,26 @@
<string name="wifi_allow_scan_with_traffic" msgid="3601853081178265786">"Wi‑Fi රෝම් පරිලෝකන වෙතට සැමවිට අවසර දෙන්න"</string>
<string name="mobile_data_always_on" msgid="7745605759775320362">"සෙලියුලර් දත්ත සැමවිට ක්රියාකාරීය"</string>
<string name="bluetooth_disable_absolute_volume" msgid="2660673801947898809">"නිරපේක්ෂ හඩ පරිමාව අබල කරන්න"</string>
+ <!-- no translation found for bluetooth_select_a2dp_codec_type (90597356942154882) -->
+ <skip />
+ <!-- no translation found for bluetooth_select_a2dp_codec_type_dialog_title (6470824182074383881) -->
+ <skip />
+ <!-- no translation found for bluetooth_select_a2dp_codec_sample_rate (4788245703824623062) -->
+ <skip />
+ <!-- no translation found for bluetooth_select_a2dp_codec_sample_rate_dialog_title (4263851572248033749) -->
+ <skip />
+ <!-- no translation found for bluetooth_select_a2dp_codec_bits_per_sample (2099645202720164141) -->
+ <skip />
+ <!-- no translation found for bluetooth_select_a2dp_codec_bits_per_sample_dialog_title (2096170505745650345) -->
+ <skip />
+ <!-- no translation found for bluetooth_select_a2dp_codec_channel_mode (884855779449390540) -->
+ <skip />
+ <!-- no translation found for bluetooth_select_a2dp_codec_channel_mode_dialog_title (4073812880900816325) -->
+ <skip />
+ <!-- no translation found for bluetooth_select_a2dp_codec_ldac_playback_quality (4846872213548295632) -->
+ <skip />
+ <!-- no translation found for bluetooth_select_a2dp_codec_ldac_playback_quality_dialog_title (3940973633342423717) -->
+ <skip />
<string name="wifi_display_certification_summary" msgid="1155182309166746973">"නොරැහැන් සංදර්ශක සහතිකය සඳහා විකල්ප පෙන්වන්න"</string>
<string name="wifi_verbose_logging_summary" msgid="6615071616111731958">"Wi‑Fi ලොග් මට්ටම වැඩි කරන්න, Wi‑Fi තෝරනයෙහි SSID RSSI අනුව පෙන්වන්න"</string>
<string name="wifi_aggressive_handover_summary" msgid="6328455667642570371">"සබල විට Wi‑Fi සිග්නලය අඩු විට Wi‑Fi දත්ත සම්බන්ධතාවය සෙලියුලර් වෙත භාර දීමට වඩා ආක්රමණික වේ"</string>
diff --git a/packages/SettingsLib/res/values-sk/arrays.xml b/packages/SettingsLib/res/values-sk/arrays.xml
index 77fa6fd..f386de1 100644
--- a/packages/SettingsLib/res/values-sk/arrays.xml
+++ b/packages/SettingsLib/res/values-sk/arrays.xml
@@ -58,6 +58,46 @@
<item msgid="3878793616631049349">"Použiť kontrolu HDCP len pre obsah DRM"</item>
<item msgid="45075631231212732">"Vždy používať kontrolu HDCP"</item>
</string-array>
+ <!-- no translation found for bluetooth_a2dp_codec_titles:0 (1852387125374225729) -->
+ <!-- no translation found for bluetooth_a2dp_codec_titles:1 (7539690996561263909) -->
+ <!-- no translation found for bluetooth_a2dp_codec_titles:2 (4260844283202960798) -->
+ <!-- no translation found for bluetooth_a2dp_codec_titles:3 (7279983368484312990) -->
+ <!-- no translation found for bluetooth_a2dp_codec_titles:4 (2301339338870319651) -->
+ <!-- no translation found for bluetooth_a2dp_codec_summaries:0 (9072025520360316957) -->
+ <!-- no translation found for bluetooth_a2dp_codec_summaries:1 (6898329690939802290) -->
+ <!-- no translation found for bluetooth_a2dp_codec_summaries:2 (1190434429082395888) -->
+ <!-- no translation found for bluetooth_a2dp_codec_summaries:3 (649699003004233053) -->
+ <!-- no translation found for bluetooth_a2dp_codec_summaries:4 (508106435710925399) -->
+ <!-- no translation found for bluetooth_a2dp_codec_sample_rate_titles:0 (7102940318360468759) -->
+ <!-- no translation found for bluetooth_a2dp_codec_sample_rate_titles:1 (8895532488906185219) -->
+ <!-- no translation found for bluetooth_a2dp_codec_sample_rate_titles:2 (2909915718994807056) -->
+ <!-- no translation found for bluetooth_a2dp_codec_sample_rate_titles:3 (3347287377354164611) -->
+ <!-- no translation found for bluetooth_a2dp_codec_sample_rate_titles:4 (1234212100239985373) -->
+ <!-- no translation found for bluetooth_a2dp_codec_sample_rate_summaries:0 (7224433008148687313) -->
+ <!-- no translation found for bluetooth_a2dp_codec_sample_rate_summaries:1 (4482862757811638365) -->
+ <!-- no translation found for bluetooth_a2dp_codec_sample_rate_summaries:2 (354495328188724404) -->
+ <!-- no translation found for bluetooth_a2dp_codec_sample_rate_summaries:3 (7329816882213695083) -->
+ <!-- no translation found for bluetooth_a2dp_codec_sample_rate_summaries:4 (6967397666254430476) -->
+ <!-- no translation found for bluetooth_a2dp_codec_bits_per_sample_titles:0 (6694044160540313386) -->
+ <!-- no translation found for bluetooth_a2dp_codec_bits_per_sample_titles:1 (5618929009984956469) -->
+ <!-- no translation found for bluetooth_a2dp_codec_bits_per_sample_titles:2 (3412640499234627248) -->
+ <!-- no translation found for bluetooth_a2dp_codec_bits_per_sample_titles:3 (121583001492929387) -->
+ <!-- no translation found for bluetooth_a2dp_codec_bits_per_sample_summaries:0 (5091076677792306320) -->
+ <!-- no translation found for bluetooth_a2dp_codec_bits_per_sample_summaries:1 (4726688794884191540) -->
+ <!-- no translation found for bluetooth_a2dp_codec_bits_per_sample_summaries:2 (305344756485516870) -->
+ <!-- no translation found for bluetooth_a2dp_codec_bits_per_sample_summaries:3 (244568657919675099) -->
+ <!-- no translation found for bluetooth_a2dp_codec_channel_mode_titles:0 (13423709606339855) -->
+ <!-- no translation found for bluetooth_a2dp_codec_channel_mode_titles:1 (4106832974775067314) -->
+ <!-- no translation found for bluetooth_a2dp_codec_channel_mode_titles:2 (5571632958424639155) -->
+ <!-- no translation found for bluetooth_a2dp_codec_channel_mode_summaries:0 (8128478683963250130) -->
+ <!-- no translation found for bluetooth_a2dp_codec_channel_mode_summaries:1 (8900559293912978337) -->
+ <!-- no translation found for bluetooth_a2dp_codec_channel_mode_summaries:2 (8883739882299884241) -->
+ <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_titles:0 (2944889121850394020) -->
+ <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_titles:1 (138837449700903545) -->
+ <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_titles:2 (4777177307869441982) -->
+ <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_summaries:0 (172302906231378902) -->
+ <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_summaries:1 (9091111147684472529) -->
+ <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_summaries:2 (3367904477834831032) -->
<string-array name="select_logd_size_titles">
<item msgid="8665206199209698501">"Vypnuté"</item>
<item msgid="1593289376502312923">"64 kB"</item>
diff --git a/packages/SettingsLib/res/values-sk/strings.xml b/packages/SettingsLib/res/values-sk/strings.xml
index 8130866..ea0dd49 100644
--- a/packages/SettingsLib/res/values-sk/strings.xml
+++ b/packages/SettingsLib/res/values-sk/strings.xml
@@ -170,6 +170,26 @@
<string name="wifi_allow_scan_with_traffic" msgid="3601853081178265786">"Vždy povoliť funkciu Wi-Fi Roam Scans"</string>
<string name="mobile_data_always_on" msgid="7745605759775320362">"Mobilné dáta vždy aktívne"</string>
<string name="bluetooth_disable_absolute_volume" msgid="2660673801947898809">"Zakázať absolútnu hlasitosť"</string>
+ <!-- no translation found for bluetooth_select_a2dp_codec_type (90597356942154882) -->
+ <skip />
+ <!-- no translation found for bluetooth_select_a2dp_codec_type_dialog_title (6470824182074383881) -->
+ <skip />
+ <!-- no translation found for bluetooth_select_a2dp_codec_sample_rate (4788245703824623062) -->
+ <skip />
+ <!-- no translation found for bluetooth_select_a2dp_codec_sample_rate_dialog_title (4263851572248033749) -->
+ <skip />
+ <!-- no translation found for bluetooth_select_a2dp_codec_bits_per_sample (2099645202720164141) -->
+ <skip />
+ <!-- no translation found for bluetooth_select_a2dp_codec_bits_per_sample_dialog_title (2096170505745650345) -->
+ <skip />
+ <!-- no translation found for bluetooth_select_a2dp_codec_channel_mode (884855779449390540) -->
+ <skip />
+ <!-- no translation found for bluetooth_select_a2dp_codec_channel_mode_dialog_title (4073812880900816325) -->
+ <skip />
+ <!-- no translation found for bluetooth_select_a2dp_codec_ldac_playback_quality (4846872213548295632) -->
+ <skip />
+ <!-- no translation found for bluetooth_select_a2dp_codec_ldac_playback_quality_dialog_title (3940973633342423717) -->
+ <skip />
<string name="wifi_display_certification_summary" msgid="1155182309166746973">"Zobraziť možnosti certifikácie bezdrôtového zobrazenia"</string>
<string name="wifi_verbose_logging_summary" msgid="6615071616111731958">"Zvýšiť úroveň denníkov Wi-Fi, zobrazovať podľa SSID RSSI pri výbere siete Wi-Fi"</string>
<string name="wifi_aggressive_handover_summary" msgid="6328455667642570371">"Keď túto možnosť zapnete, Wi-Fi bude agresívnejšie odovzdávať dát. pripoj. na mob. sieť vtedy, keď bude slabý signál Wi-Fi"</string>
diff --git a/packages/SettingsLib/res/values-sl/arrays.xml b/packages/SettingsLib/res/values-sl/arrays.xml
index 54cdd0e..aad81e8 100644
--- a/packages/SettingsLib/res/values-sl/arrays.xml
+++ b/packages/SettingsLib/res/values-sl/arrays.xml
@@ -58,6 +58,46 @@
<item msgid="3878793616631049349">"Preverjanje HDCP uporabi samo za vsebino DRM"</item>
<item msgid="45075631231212732">"Vedno uporabi preverjanje HDCP"</item>
</string-array>
+ <!-- no translation found for bluetooth_a2dp_codec_titles:0 (1852387125374225729) -->
+ <!-- no translation found for bluetooth_a2dp_codec_titles:1 (7539690996561263909) -->
+ <!-- no translation found for bluetooth_a2dp_codec_titles:2 (4260844283202960798) -->
+ <!-- no translation found for bluetooth_a2dp_codec_titles:3 (7279983368484312990) -->
+ <!-- no translation found for bluetooth_a2dp_codec_titles:4 (2301339338870319651) -->
+ <!-- no translation found for bluetooth_a2dp_codec_summaries:0 (9072025520360316957) -->
+ <!-- no translation found for bluetooth_a2dp_codec_summaries:1 (6898329690939802290) -->
+ <!-- no translation found for bluetooth_a2dp_codec_summaries:2 (1190434429082395888) -->
+ <!-- no translation found for bluetooth_a2dp_codec_summaries:3 (649699003004233053) -->
+ <!-- no translation found for bluetooth_a2dp_codec_summaries:4 (508106435710925399) -->
+ <!-- no translation found for bluetooth_a2dp_codec_sample_rate_titles:0 (7102940318360468759) -->
+ <!-- no translation found for bluetooth_a2dp_codec_sample_rate_titles:1 (8895532488906185219) -->
+ <!-- no translation found for bluetooth_a2dp_codec_sample_rate_titles:2 (2909915718994807056) -->
+ <!-- no translation found for bluetooth_a2dp_codec_sample_rate_titles:3 (3347287377354164611) -->
+ <!-- no translation found for bluetooth_a2dp_codec_sample_rate_titles:4 (1234212100239985373) -->
+ <!-- no translation found for bluetooth_a2dp_codec_sample_rate_summaries:0 (7224433008148687313) -->
+ <!-- no translation found for bluetooth_a2dp_codec_sample_rate_summaries:1 (4482862757811638365) -->
+ <!-- no translation found for bluetooth_a2dp_codec_sample_rate_summaries:2 (354495328188724404) -->
+ <!-- no translation found for bluetooth_a2dp_codec_sample_rate_summaries:3 (7329816882213695083) -->
+ <!-- no translation found for bluetooth_a2dp_codec_sample_rate_summaries:4 (6967397666254430476) -->
+ <!-- no translation found for bluetooth_a2dp_codec_bits_per_sample_titles:0 (6694044160540313386) -->
+ <!-- no translation found for bluetooth_a2dp_codec_bits_per_sample_titles:1 (5618929009984956469) -->
+ <!-- no translation found for bluetooth_a2dp_codec_bits_per_sample_titles:2 (3412640499234627248) -->
+ <!-- no translation found for bluetooth_a2dp_codec_bits_per_sample_titles:3 (121583001492929387) -->
+ <!-- no translation found for bluetooth_a2dp_codec_bits_per_sample_summaries:0 (5091076677792306320) -->
+ <!-- no translation found for bluetooth_a2dp_codec_bits_per_sample_summaries:1 (4726688794884191540) -->
+ <!-- no translation found for bluetooth_a2dp_codec_bits_per_sample_summaries:2 (305344756485516870) -->
+ <!-- no translation found for bluetooth_a2dp_codec_bits_per_sample_summaries:3 (244568657919675099) -->
+ <!-- no translation found for bluetooth_a2dp_codec_channel_mode_titles:0 (13423709606339855) -->
+ <!-- no translation found for bluetooth_a2dp_codec_channel_mode_titles:1 (4106832974775067314) -->
+ <!-- no translation found for bluetooth_a2dp_codec_channel_mode_titles:2 (5571632958424639155) -->
+ <!-- no translation found for bluetooth_a2dp_codec_channel_mode_summaries:0 (8128478683963250130) -->
+ <!-- no translation found for bluetooth_a2dp_codec_channel_mode_summaries:1 (8900559293912978337) -->
+ <!-- no translation found for bluetooth_a2dp_codec_channel_mode_summaries:2 (8883739882299884241) -->
+ <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_titles:0 (2944889121850394020) -->
+ <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_titles:1 (138837449700903545) -->
+ <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_titles:2 (4777177307869441982) -->
+ <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_summaries:0 (172302906231378902) -->
+ <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_summaries:1 (9091111147684472529) -->
+ <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_summaries:2 (3367904477834831032) -->
<string-array name="select_logd_size_titles">
<item msgid="8665206199209698501">"Izklopljeno"</item>
<item msgid="1593289376502312923">"64 K"</item>
diff --git a/packages/SettingsLib/res/values-sl/strings.xml b/packages/SettingsLib/res/values-sl/strings.xml
index a3b666ca..881a3dd 100644
--- a/packages/SettingsLib/res/values-sl/strings.xml
+++ b/packages/SettingsLib/res/values-sl/strings.xml
@@ -170,6 +170,26 @@
<string name="wifi_allow_scan_with_traffic" msgid="3601853081178265786">"Vedno omogoči iskanje omrežij Wi-Fi za gostovanje"</string>
<string name="mobile_data_always_on" msgid="7745605759775320362">"Prenos podatkov v mobilnih omrežjih je vedno aktiven"</string>
<string name="bluetooth_disable_absolute_volume" msgid="2660673801947898809">"Onemogočanje absolutnega praga glasnosti"</string>
+ <!-- no translation found for bluetooth_select_a2dp_codec_type (90597356942154882) -->
+ <skip />
+ <!-- no translation found for bluetooth_select_a2dp_codec_type_dialog_title (6470824182074383881) -->
+ <skip />
+ <!-- no translation found for bluetooth_select_a2dp_codec_sample_rate (4788245703824623062) -->
+ <skip />
+ <!-- no translation found for bluetooth_select_a2dp_codec_sample_rate_dialog_title (4263851572248033749) -->
+ <skip />
+ <!-- no translation found for bluetooth_select_a2dp_codec_bits_per_sample (2099645202720164141) -->
+ <skip />
+ <!-- no translation found for bluetooth_select_a2dp_codec_bits_per_sample_dialog_title (2096170505745650345) -->
+ <skip />
+ <!-- no translation found for bluetooth_select_a2dp_codec_channel_mode (884855779449390540) -->
+ <skip />
+ <!-- no translation found for bluetooth_select_a2dp_codec_channel_mode_dialog_title (4073812880900816325) -->
+ <skip />
+ <!-- no translation found for bluetooth_select_a2dp_codec_ldac_playback_quality (4846872213548295632) -->
+ <skip />
+ <!-- no translation found for bluetooth_select_a2dp_codec_ldac_playback_quality_dialog_title (3940973633342423717) -->
+ <skip />
<string name="wifi_display_certification_summary" msgid="1155182309166746973">"Pokaži možnosti za potrdilo brezžičnega zaslona"</string>
<string name="wifi_verbose_logging_summary" msgid="6615071616111731958">"Povečaj raven zapis. dnev. za Wi-Fi; v izbir. Wi‑Fi-ja pokaži glede na SSID RSSI"</string>
<string name="wifi_aggressive_handover_summary" msgid="6328455667642570371">"Če je ta možnost omogočena, Wi-Fi odločneje preda podatkovno povezavo mobilnemu omrežju, ko je signal Wi-Fi šibek"</string>
diff --git a/packages/SettingsLib/res/values-sq-rAL/arrays.xml b/packages/SettingsLib/res/values-sq-rAL/arrays.xml
index 8fab1dc..39c5819 100644
--- a/packages/SettingsLib/res/values-sq-rAL/arrays.xml
+++ b/packages/SettingsLib/res/values-sq-rAL/arrays.xml
@@ -58,6 +58,46 @@
<item msgid="3878793616631049349">"Përdor kontrollin e HDCP-së vetëm për përmbajtjet DRM"</item>
<item msgid="45075631231212732">"Përdor gjithmonë kontrollin e HDCP-së"</item>
</string-array>
+ <!-- no translation found for bluetooth_a2dp_codec_titles:0 (1852387125374225729) -->
+ <!-- no translation found for bluetooth_a2dp_codec_titles:1 (7539690996561263909) -->
+ <!-- no translation found for bluetooth_a2dp_codec_titles:2 (4260844283202960798) -->
+ <!-- no translation found for bluetooth_a2dp_codec_titles:3 (7279983368484312990) -->
+ <!-- no translation found for bluetooth_a2dp_codec_titles:4 (2301339338870319651) -->
+ <!-- no translation found for bluetooth_a2dp_codec_summaries:0 (9072025520360316957) -->
+ <!-- no translation found for bluetooth_a2dp_codec_summaries:1 (6898329690939802290) -->
+ <!-- no translation found for bluetooth_a2dp_codec_summaries:2 (1190434429082395888) -->
+ <!-- no translation found for bluetooth_a2dp_codec_summaries:3 (649699003004233053) -->
+ <!-- no translation found for bluetooth_a2dp_codec_summaries:4 (508106435710925399) -->
+ <!-- no translation found for bluetooth_a2dp_codec_sample_rate_titles:0 (7102940318360468759) -->
+ <!-- no translation found for bluetooth_a2dp_codec_sample_rate_titles:1 (8895532488906185219) -->
+ <!-- no translation found for bluetooth_a2dp_codec_sample_rate_titles:2 (2909915718994807056) -->
+ <!-- no translation found for bluetooth_a2dp_codec_sample_rate_titles:3 (3347287377354164611) -->
+ <!-- no translation found for bluetooth_a2dp_codec_sample_rate_titles:4 (1234212100239985373) -->
+ <!-- no translation found for bluetooth_a2dp_codec_sample_rate_summaries:0 (7224433008148687313) -->
+ <!-- no translation found for bluetooth_a2dp_codec_sample_rate_summaries:1 (4482862757811638365) -->
+ <!-- no translation found for bluetooth_a2dp_codec_sample_rate_summaries:2 (354495328188724404) -->
+ <!-- no translation found for bluetooth_a2dp_codec_sample_rate_summaries:3 (7329816882213695083) -->
+ <!-- no translation found for bluetooth_a2dp_codec_sample_rate_summaries:4 (6967397666254430476) -->
+ <!-- no translation found for bluetooth_a2dp_codec_bits_per_sample_titles:0 (6694044160540313386) -->
+ <!-- no translation found for bluetooth_a2dp_codec_bits_per_sample_titles:1 (5618929009984956469) -->
+ <!-- no translation found for bluetooth_a2dp_codec_bits_per_sample_titles:2 (3412640499234627248) -->
+ <!-- no translation found for bluetooth_a2dp_codec_bits_per_sample_titles:3 (121583001492929387) -->
+ <!-- no translation found for bluetooth_a2dp_codec_bits_per_sample_summaries:0 (5091076677792306320) -->
+ <!-- no translation found for bluetooth_a2dp_codec_bits_per_sample_summaries:1 (4726688794884191540) -->
+ <!-- no translation found for bluetooth_a2dp_codec_bits_per_sample_summaries:2 (305344756485516870) -->
+ <!-- no translation found for bluetooth_a2dp_codec_bits_per_sample_summaries:3 (244568657919675099) -->
+ <!-- no translation found for bluetooth_a2dp_codec_channel_mode_titles:0 (13423709606339855) -->
+ <!-- no translation found for bluetooth_a2dp_codec_channel_mode_titles:1 (4106832974775067314) -->
+ <!-- no translation found for bluetooth_a2dp_codec_channel_mode_titles:2 (5571632958424639155) -->
+ <!-- no translation found for bluetooth_a2dp_codec_channel_mode_summaries:0 (8128478683963250130) -->
+ <!-- no translation found for bluetooth_a2dp_codec_channel_mode_summaries:1 (8900559293912978337) -->
+ <!-- no translation found for bluetooth_a2dp_codec_channel_mode_summaries:2 (8883739882299884241) -->
+ <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_titles:0 (2944889121850394020) -->
+ <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_titles:1 (138837449700903545) -->
+ <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_titles:2 (4777177307869441982) -->
+ <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_summaries:0 (172302906231378902) -->
+ <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_summaries:1 (9091111147684472529) -->
+ <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_summaries:2 (3367904477834831032) -->
<string-array name="select_logd_size_titles">
<item msgid="8665206199209698501">"Joaktiv"</item>
<item msgid="1593289376502312923">"64 mijë"</item>
diff --git a/packages/SettingsLib/res/values-sq-rAL/strings.xml b/packages/SettingsLib/res/values-sq-rAL/strings.xml
index 232ca0a..c92ec2b 100644
--- a/packages/SettingsLib/res/values-sq-rAL/strings.xml
+++ b/packages/SettingsLib/res/values-sq-rAL/strings.xml
@@ -170,6 +170,26 @@
<string name="wifi_allow_scan_with_traffic" msgid="3601853081178265786">"Lejo gjithmonë skanimet për Wi-Fi edhe kur je në lëvizje"</string>
<string name="mobile_data_always_on" msgid="7745605759775320362">"Të dhënat celulare gjithmonë aktive"</string>
<string name="bluetooth_disable_absolute_volume" msgid="2660673801947898809">"Çaktivizo volumin absolut"</string>
+ <!-- no translation found for bluetooth_select_a2dp_codec_type (90597356942154882) -->
+ <skip />
+ <!-- no translation found for bluetooth_select_a2dp_codec_type_dialog_title (6470824182074383881) -->
+ <skip />
+ <!-- no translation found for bluetooth_select_a2dp_codec_sample_rate (4788245703824623062) -->
+ <skip />
+ <!-- no translation found for bluetooth_select_a2dp_codec_sample_rate_dialog_title (4263851572248033749) -->
+ <skip />
+ <!-- no translation found for bluetooth_select_a2dp_codec_bits_per_sample (2099645202720164141) -->
+ <skip />
+ <!-- no translation found for bluetooth_select_a2dp_codec_bits_per_sample_dialog_title (2096170505745650345) -->
+ <skip />
+ <!-- no translation found for bluetooth_select_a2dp_codec_channel_mode (884855779449390540) -->
+ <skip />
+ <!-- no translation found for bluetooth_select_a2dp_codec_channel_mode_dialog_title (4073812880900816325) -->
+ <skip />
+ <!-- no translation found for bluetooth_select_a2dp_codec_ldac_playback_quality (4846872213548295632) -->
+ <skip />
+ <!-- no translation found for bluetooth_select_a2dp_codec_ldac_playback_quality_dialog_title (3940973633342423717) -->
+ <skip />
<string name="wifi_display_certification_summary" msgid="1155182309166746973">"Shfaq opsionet për certifikimin e ekranit valor"</string>
<string name="wifi_verbose_logging_summary" msgid="6615071616111731958">"Rrit nivelin regjistrues të Wi‑Fi duke shfaqur SSID RSSI-në te Zgjedhësi i Wi‑Fi"</string>
<string name="wifi_aggressive_handover_summary" msgid="6328455667642570371">"Kur ky funksion aktivizohet, Wi‑Fi bëhet më agresiv në kalimin e lidhjes së të dhënave te rrjeti celular, në rastet kur sinjali Wi‑Fi është i dobët"</string>
diff --git a/packages/SettingsLib/res/values-sr/arrays.xml b/packages/SettingsLib/res/values-sr/arrays.xml
index 97a01db..5f13d6d 100644
--- a/packages/SettingsLib/res/values-sr/arrays.xml
+++ b/packages/SettingsLib/res/values-sr/arrays.xml
@@ -58,6 +58,46 @@
<item msgid="3878793616631049349">"Користи HDCP проверу само за DRM садржај"</item>
<item msgid="45075631231212732">"Увек користи HDCP проверу"</item>
</string-array>
+ <!-- no translation found for bluetooth_a2dp_codec_titles:0 (1852387125374225729) -->
+ <!-- no translation found for bluetooth_a2dp_codec_titles:1 (7539690996561263909) -->
+ <!-- no translation found for bluetooth_a2dp_codec_titles:2 (4260844283202960798) -->
+ <!-- no translation found for bluetooth_a2dp_codec_titles:3 (7279983368484312990) -->
+ <!-- no translation found for bluetooth_a2dp_codec_titles:4 (2301339338870319651) -->
+ <!-- no translation found for bluetooth_a2dp_codec_summaries:0 (9072025520360316957) -->
+ <!-- no translation found for bluetooth_a2dp_codec_summaries:1 (6898329690939802290) -->
+ <!-- no translation found for bluetooth_a2dp_codec_summaries:2 (1190434429082395888) -->
+ <!-- no translation found for bluetooth_a2dp_codec_summaries:3 (649699003004233053) -->
+ <!-- no translation found for bluetooth_a2dp_codec_summaries:4 (508106435710925399) -->
+ <!-- no translation found for bluetooth_a2dp_codec_sample_rate_titles:0 (7102940318360468759) -->
+ <!-- no translation found for bluetooth_a2dp_codec_sample_rate_titles:1 (8895532488906185219) -->
+ <!-- no translation found for bluetooth_a2dp_codec_sample_rate_titles:2 (2909915718994807056) -->
+ <!-- no translation found for bluetooth_a2dp_codec_sample_rate_titles:3 (3347287377354164611) -->
+ <!-- no translation found for bluetooth_a2dp_codec_sample_rate_titles:4 (1234212100239985373) -->
+ <!-- no translation found for bluetooth_a2dp_codec_sample_rate_summaries:0 (7224433008148687313) -->
+ <!-- no translation found for bluetooth_a2dp_codec_sample_rate_summaries:1 (4482862757811638365) -->
+ <!-- no translation found for bluetooth_a2dp_codec_sample_rate_summaries:2 (354495328188724404) -->
+ <!-- no translation found for bluetooth_a2dp_codec_sample_rate_summaries:3 (7329816882213695083) -->
+ <!-- no translation found for bluetooth_a2dp_codec_sample_rate_summaries:4 (6967397666254430476) -->
+ <!-- no translation found for bluetooth_a2dp_codec_bits_per_sample_titles:0 (6694044160540313386) -->
+ <!-- no translation found for bluetooth_a2dp_codec_bits_per_sample_titles:1 (5618929009984956469) -->
+ <!-- no translation found for bluetooth_a2dp_codec_bits_per_sample_titles:2 (3412640499234627248) -->
+ <!-- no translation found for bluetooth_a2dp_codec_bits_per_sample_titles:3 (121583001492929387) -->
+ <!-- no translation found for bluetooth_a2dp_codec_bits_per_sample_summaries:0 (5091076677792306320) -->
+ <!-- no translation found for bluetooth_a2dp_codec_bits_per_sample_summaries:1 (4726688794884191540) -->
+ <!-- no translation found for bluetooth_a2dp_codec_bits_per_sample_summaries:2 (305344756485516870) -->
+ <!-- no translation found for bluetooth_a2dp_codec_bits_per_sample_summaries:3 (244568657919675099) -->
+ <!-- no translation found for bluetooth_a2dp_codec_channel_mode_titles:0 (13423709606339855) -->
+ <!-- no translation found for bluetooth_a2dp_codec_channel_mode_titles:1 (4106832974775067314) -->
+ <!-- no translation found for bluetooth_a2dp_codec_channel_mode_titles:2 (5571632958424639155) -->
+ <!-- no translation found for bluetooth_a2dp_codec_channel_mode_summaries:0 (8128478683963250130) -->
+ <!-- no translation found for bluetooth_a2dp_codec_channel_mode_summaries:1 (8900559293912978337) -->
+ <!-- no translation found for bluetooth_a2dp_codec_channel_mode_summaries:2 (8883739882299884241) -->
+ <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_titles:0 (2944889121850394020) -->
+ <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_titles:1 (138837449700903545) -->
+ <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_titles:2 (4777177307869441982) -->
+ <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_summaries:0 (172302906231378902) -->
+ <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_summaries:1 (9091111147684472529) -->
+ <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_summaries:2 (3367904477834831032) -->
<string-array name="select_logd_size_titles">
<item msgid="8665206199209698501">"Искључено"</item>
<item msgid="1593289376502312923">"64 kB"</item>
diff --git a/packages/SettingsLib/res/values-sr/strings.xml b/packages/SettingsLib/res/values-sr/strings.xml
index 5fd58a5..73c4923 100644
--- a/packages/SettingsLib/res/values-sr/strings.xml
+++ b/packages/SettingsLib/res/values-sr/strings.xml
@@ -170,6 +170,26 @@
<string name="wifi_allow_scan_with_traffic" msgid="3601853081178265786">"Увек дозволи скенирање Wi‑Fi-ја у ромингу"</string>
<string name="mobile_data_always_on" msgid="7745605759775320362">"Подаци за мобилне уређаје су увек активни"</string>
<string name="bluetooth_disable_absolute_volume" msgid="2660673801947898809">"Онемогући главно подешавање јачине звука"</string>
+ <!-- no translation found for bluetooth_select_a2dp_codec_type (90597356942154882) -->
+ <skip />
+ <!-- no translation found for bluetooth_select_a2dp_codec_type_dialog_title (6470824182074383881) -->
+ <skip />
+ <!-- no translation found for bluetooth_select_a2dp_codec_sample_rate (4788245703824623062) -->
+ <skip />
+ <!-- no translation found for bluetooth_select_a2dp_codec_sample_rate_dialog_title (4263851572248033749) -->
+ <skip />
+ <!-- no translation found for bluetooth_select_a2dp_codec_bits_per_sample (2099645202720164141) -->
+ <skip />
+ <!-- no translation found for bluetooth_select_a2dp_codec_bits_per_sample_dialog_title (2096170505745650345) -->
+ <skip />
+ <!-- no translation found for bluetooth_select_a2dp_codec_channel_mode (884855779449390540) -->
+ <skip />
+ <!-- no translation found for bluetooth_select_a2dp_codec_channel_mode_dialog_title (4073812880900816325) -->
+ <skip />
+ <!-- no translation found for bluetooth_select_a2dp_codec_ldac_playback_quality (4846872213548295632) -->
+ <skip />
+ <!-- no translation found for bluetooth_select_a2dp_codec_ldac_playback_quality_dialog_title (3940973633342423717) -->
+ <skip />
<string name="wifi_display_certification_summary" msgid="1155182309166746973">"Приказ опција за сертификацију бежичног екрана"</string>
<string name="wifi_verbose_logging_summary" msgid="6615071616111731958">"Повећава ниво евидентирања за Wi‑Fi. Приказ по SSID RSSI-у у бирачу Wi‑Fi мреже"</string>
<string name="wifi_aggressive_handover_summary" msgid="6328455667642570371">"Када се омогући, Wi‑Fi ће бити агресивнији при пребацивању мреже за пренос података на Мобилну, када је Wi‑Fi сигнал слаб"</string>
diff --git a/packages/SettingsLib/res/values-sv/arrays.xml b/packages/SettingsLib/res/values-sv/arrays.xml
index 746bc15..8985048 100644
--- a/packages/SettingsLib/res/values-sv/arrays.xml
+++ b/packages/SettingsLib/res/values-sv/arrays.xml
@@ -58,6 +58,46 @@
<item msgid="3878793616631049349">"Använd bara HDCP-kontroll för DRM-innehåll"</item>
<item msgid="45075631231212732">"Använd alltid HDCP-kontroll"</item>
</string-array>
+ <!-- no translation found for bluetooth_a2dp_codec_titles:0 (1852387125374225729) -->
+ <!-- no translation found for bluetooth_a2dp_codec_titles:1 (7539690996561263909) -->
+ <!-- no translation found for bluetooth_a2dp_codec_titles:2 (4260844283202960798) -->
+ <!-- no translation found for bluetooth_a2dp_codec_titles:3 (7279983368484312990) -->
+ <!-- no translation found for bluetooth_a2dp_codec_titles:4 (2301339338870319651) -->
+ <!-- no translation found for bluetooth_a2dp_codec_summaries:0 (9072025520360316957) -->
+ <!-- no translation found for bluetooth_a2dp_codec_summaries:1 (6898329690939802290) -->
+ <!-- no translation found for bluetooth_a2dp_codec_summaries:2 (1190434429082395888) -->
+ <!-- no translation found for bluetooth_a2dp_codec_summaries:3 (649699003004233053) -->
+ <!-- no translation found for bluetooth_a2dp_codec_summaries:4 (508106435710925399) -->
+ <!-- no translation found for bluetooth_a2dp_codec_sample_rate_titles:0 (7102940318360468759) -->
+ <!-- no translation found for bluetooth_a2dp_codec_sample_rate_titles:1 (8895532488906185219) -->
+ <!-- no translation found for bluetooth_a2dp_codec_sample_rate_titles:2 (2909915718994807056) -->
+ <!-- no translation found for bluetooth_a2dp_codec_sample_rate_titles:3 (3347287377354164611) -->
+ <!-- no translation found for bluetooth_a2dp_codec_sample_rate_titles:4 (1234212100239985373) -->
+ <!-- no translation found for bluetooth_a2dp_codec_sample_rate_summaries:0 (7224433008148687313) -->
+ <!-- no translation found for bluetooth_a2dp_codec_sample_rate_summaries:1 (4482862757811638365) -->
+ <!-- no translation found for bluetooth_a2dp_codec_sample_rate_summaries:2 (354495328188724404) -->
+ <!-- no translation found for bluetooth_a2dp_codec_sample_rate_summaries:3 (7329816882213695083) -->
+ <!-- no translation found for bluetooth_a2dp_codec_sample_rate_summaries:4 (6967397666254430476) -->
+ <!-- no translation found for bluetooth_a2dp_codec_bits_per_sample_titles:0 (6694044160540313386) -->
+ <!-- no translation found for bluetooth_a2dp_codec_bits_per_sample_titles:1 (5618929009984956469) -->
+ <!-- no translation found for bluetooth_a2dp_codec_bits_per_sample_titles:2 (3412640499234627248) -->
+ <!-- no translation found for bluetooth_a2dp_codec_bits_per_sample_titles:3 (121583001492929387) -->
+ <!-- no translation found for bluetooth_a2dp_codec_bits_per_sample_summaries:0 (5091076677792306320) -->
+ <!-- no translation found for bluetooth_a2dp_codec_bits_per_sample_summaries:1 (4726688794884191540) -->
+ <!-- no translation found for bluetooth_a2dp_codec_bits_per_sample_summaries:2 (305344756485516870) -->
+ <!-- no translation found for bluetooth_a2dp_codec_bits_per_sample_summaries:3 (244568657919675099) -->
+ <!-- no translation found for bluetooth_a2dp_codec_channel_mode_titles:0 (13423709606339855) -->
+ <!-- no translation found for bluetooth_a2dp_codec_channel_mode_titles:1 (4106832974775067314) -->
+ <!-- no translation found for bluetooth_a2dp_codec_channel_mode_titles:2 (5571632958424639155) -->
+ <!-- no translation found for bluetooth_a2dp_codec_channel_mode_summaries:0 (8128478683963250130) -->
+ <!-- no translation found for bluetooth_a2dp_codec_channel_mode_summaries:1 (8900559293912978337) -->
+ <!-- no translation found for bluetooth_a2dp_codec_channel_mode_summaries:2 (8883739882299884241) -->
+ <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_titles:0 (2944889121850394020) -->
+ <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_titles:1 (138837449700903545) -->
+ <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_titles:2 (4777177307869441982) -->
+ <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_summaries:0 (172302906231378902) -->
+ <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_summaries:1 (9091111147684472529) -->
+ <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_summaries:2 (3367904477834831032) -->
<string-array name="select_logd_size_titles">
<item msgid="8665206199209698501">"Av"</item>
<item msgid="1593289376502312923">"64 kB"</item>
diff --git a/packages/SettingsLib/res/values-sv/strings.xml b/packages/SettingsLib/res/values-sv/strings.xml
index ee93622..fa7b264 100644
--- a/packages/SettingsLib/res/values-sv/strings.xml
+++ b/packages/SettingsLib/res/values-sv/strings.xml
@@ -170,6 +170,26 @@
<string name="wifi_allow_scan_with_traffic" msgid="3601853081178265786">"Tillåt alltid sökning efter Wi-Fi-roaming"</string>
<string name="mobile_data_always_on" msgid="7745605759775320362">"Mobildata alltid aktiverad"</string>
<string name="bluetooth_disable_absolute_volume" msgid="2660673801947898809">"Inaktivera Absolute volume"</string>
+ <!-- no translation found for bluetooth_select_a2dp_codec_type (90597356942154882) -->
+ <skip />
+ <!-- no translation found for bluetooth_select_a2dp_codec_type_dialog_title (6470824182074383881) -->
+ <skip />
+ <!-- no translation found for bluetooth_select_a2dp_codec_sample_rate (4788245703824623062) -->
+ <skip />
+ <!-- no translation found for bluetooth_select_a2dp_codec_sample_rate_dialog_title (4263851572248033749) -->
+ <skip />
+ <!-- no translation found for bluetooth_select_a2dp_codec_bits_per_sample (2099645202720164141) -->
+ <skip />
+ <!-- no translation found for bluetooth_select_a2dp_codec_bits_per_sample_dialog_title (2096170505745650345) -->
+ <skip />
+ <!-- no translation found for bluetooth_select_a2dp_codec_channel_mode (884855779449390540) -->
+ <skip />
+ <!-- no translation found for bluetooth_select_a2dp_codec_channel_mode_dialog_title (4073812880900816325) -->
+ <skip />
+ <!-- no translation found for bluetooth_select_a2dp_codec_ldac_playback_quality (4846872213548295632) -->
+ <skip />
+ <!-- no translation found for bluetooth_select_a2dp_codec_ldac_playback_quality_dialog_title (3940973633342423717) -->
+ <skip />
<string name="wifi_display_certification_summary" msgid="1155182309166746973">"Visa certifieringsalternativ för Wi-Fi-skärmdelning"</string>
<string name="wifi_verbose_logging_summary" msgid="6615071616111731958">"Öka loggningsnivån för Wi-Fi, visa per SSID RSSI i Wi‑Fi Picker"</string>
<string name="wifi_aggressive_handover_summary" msgid="6328455667642570371">"När funktionen har aktiverats kommer dataanslutningen lämnas över från Wi-Fi till mobilen på ett aggressivare sätt när Wi-Fi-signalen är svag"</string>
diff --git a/packages/SettingsLib/res/values-sw/arrays.xml b/packages/SettingsLib/res/values-sw/arrays.xml
index f56961b..7039d90 100644
--- a/packages/SettingsLib/res/values-sw/arrays.xml
+++ b/packages/SettingsLib/res/values-sw/arrays.xml
@@ -58,6 +58,46 @@
<item msgid="3878793616631049349">"Tumia ukaguaji wa HDCP kwa maudhui ya DRM pekee"</item>
<item msgid="45075631231212732">"Kila wakati tumia ukakuaji wa HDCP"</item>
</string-array>
+ <!-- no translation found for bluetooth_a2dp_codec_titles:0 (1852387125374225729) -->
+ <!-- no translation found for bluetooth_a2dp_codec_titles:1 (7539690996561263909) -->
+ <!-- no translation found for bluetooth_a2dp_codec_titles:2 (4260844283202960798) -->
+ <!-- no translation found for bluetooth_a2dp_codec_titles:3 (7279983368484312990) -->
+ <!-- no translation found for bluetooth_a2dp_codec_titles:4 (2301339338870319651) -->
+ <!-- no translation found for bluetooth_a2dp_codec_summaries:0 (9072025520360316957) -->
+ <!-- no translation found for bluetooth_a2dp_codec_summaries:1 (6898329690939802290) -->
+ <!-- no translation found for bluetooth_a2dp_codec_summaries:2 (1190434429082395888) -->
+ <!-- no translation found for bluetooth_a2dp_codec_summaries:3 (649699003004233053) -->
+ <!-- no translation found for bluetooth_a2dp_codec_summaries:4 (508106435710925399) -->
+ <!-- no translation found for bluetooth_a2dp_codec_sample_rate_titles:0 (7102940318360468759) -->
+ <!-- no translation found for bluetooth_a2dp_codec_sample_rate_titles:1 (8895532488906185219) -->
+ <!-- no translation found for bluetooth_a2dp_codec_sample_rate_titles:2 (2909915718994807056) -->
+ <!-- no translation found for bluetooth_a2dp_codec_sample_rate_titles:3 (3347287377354164611) -->
+ <!-- no translation found for bluetooth_a2dp_codec_sample_rate_titles:4 (1234212100239985373) -->
+ <!-- no translation found for bluetooth_a2dp_codec_sample_rate_summaries:0 (7224433008148687313) -->
+ <!-- no translation found for bluetooth_a2dp_codec_sample_rate_summaries:1 (4482862757811638365) -->
+ <!-- no translation found for bluetooth_a2dp_codec_sample_rate_summaries:2 (354495328188724404) -->
+ <!-- no translation found for bluetooth_a2dp_codec_sample_rate_summaries:3 (7329816882213695083) -->
+ <!-- no translation found for bluetooth_a2dp_codec_sample_rate_summaries:4 (6967397666254430476) -->
+ <!-- no translation found for bluetooth_a2dp_codec_bits_per_sample_titles:0 (6694044160540313386) -->
+ <!-- no translation found for bluetooth_a2dp_codec_bits_per_sample_titles:1 (5618929009984956469) -->
+ <!-- no translation found for bluetooth_a2dp_codec_bits_per_sample_titles:2 (3412640499234627248) -->
+ <!-- no translation found for bluetooth_a2dp_codec_bits_per_sample_titles:3 (121583001492929387) -->
+ <!-- no translation found for bluetooth_a2dp_codec_bits_per_sample_summaries:0 (5091076677792306320) -->
+ <!-- no translation found for bluetooth_a2dp_codec_bits_per_sample_summaries:1 (4726688794884191540) -->
+ <!-- no translation found for bluetooth_a2dp_codec_bits_per_sample_summaries:2 (305344756485516870) -->
+ <!-- no translation found for bluetooth_a2dp_codec_bits_per_sample_summaries:3 (244568657919675099) -->
+ <!-- no translation found for bluetooth_a2dp_codec_channel_mode_titles:0 (13423709606339855) -->
+ <!-- no translation found for bluetooth_a2dp_codec_channel_mode_titles:1 (4106832974775067314) -->
+ <!-- no translation found for bluetooth_a2dp_codec_channel_mode_titles:2 (5571632958424639155) -->
+ <!-- no translation found for bluetooth_a2dp_codec_channel_mode_summaries:0 (8128478683963250130) -->
+ <!-- no translation found for bluetooth_a2dp_codec_channel_mode_summaries:1 (8900559293912978337) -->
+ <!-- no translation found for bluetooth_a2dp_codec_channel_mode_summaries:2 (8883739882299884241) -->
+ <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_titles:0 (2944889121850394020) -->
+ <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_titles:1 (138837449700903545) -->
+ <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_titles:2 (4777177307869441982) -->
+ <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_summaries:0 (172302906231378902) -->
+ <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_summaries:1 (9091111147684472529) -->
+ <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_summaries:2 (3367904477834831032) -->
<string-array name="select_logd_size_titles">
<item msgid="8665206199209698501">"Imezimwa"</item>
<item msgid="1593289376502312923">"K64"</item>
diff --git a/packages/SettingsLib/res/values-sw/strings.xml b/packages/SettingsLib/res/values-sw/strings.xml
index 3c06d72..c478445 100644
--- a/packages/SettingsLib/res/values-sw/strings.xml
+++ b/packages/SettingsLib/res/values-sw/strings.xml
@@ -170,6 +170,26 @@
<string name="wifi_allow_scan_with_traffic" msgid="3601853081178265786">"Ruhusu Uchanganuzi wa Matumizi ya Mitandao mingine"</string>
<string name="mobile_data_always_on" msgid="7745605759775320362">"Data ya kifaa cha mkononi inatumika kila wakati"</string>
<string name="bluetooth_disable_absolute_volume" msgid="2660673801947898809">"Zima sauti kamili"</string>
+ <!-- no translation found for bluetooth_select_a2dp_codec_type (90597356942154882) -->
+ <skip />
+ <!-- no translation found for bluetooth_select_a2dp_codec_type_dialog_title (6470824182074383881) -->
+ <skip />
+ <!-- no translation found for bluetooth_select_a2dp_codec_sample_rate (4788245703824623062) -->
+ <skip />
+ <!-- no translation found for bluetooth_select_a2dp_codec_sample_rate_dialog_title (4263851572248033749) -->
+ <skip />
+ <!-- no translation found for bluetooth_select_a2dp_codec_bits_per_sample (2099645202720164141) -->
+ <skip />
+ <!-- no translation found for bluetooth_select_a2dp_codec_bits_per_sample_dialog_title (2096170505745650345) -->
+ <skip />
+ <!-- no translation found for bluetooth_select_a2dp_codec_channel_mode (884855779449390540) -->
+ <skip />
+ <!-- no translation found for bluetooth_select_a2dp_codec_channel_mode_dialog_title (4073812880900816325) -->
+ <skip />
+ <!-- no translation found for bluetooth_select_a2dp_codec_ldac_playback_quality (4846872213548295632) -->
+ <skip />
+ <!-- no translation found for bluetooth_select_a2dp_codec_ldac_playback_quality_dialog_title (3940973633342423717) -->
+ <skip />
<string name="wifi_display_certification_summary" msgid="1155182309166746973">"Onyesha chaguo za cheti cha kuonyesha pasiwaya"</string>
<string name="wifi_verbose_logging_summary" msgid="6615071616111731958">"Ongeza hatua ya uwekaji kumbukumbu ya Wi-Fi, onyesha kwa kila SSID RSSI kwenye Kichukuzi cha Wi-Fi"</string>
<string name="wifi_aggressive_handover_summary" msgid="6328455667642570371">"Ikiwashwa, Wifi itakabidhi kwa hima muunganisho wa data kwa mtandao wa Simu za Mkononi, mawimbi ya Wifi yanapokuwa hafifu"</string>
diff --git a/packages/SettingsLib/res/values-ta-rIN/arrays.xml b/packages/SettingsLib/res/values-ta-rIN/arrays.xml
index e21e1c4..b48f8bc 100644
--- a/packages/SettingsLib/res/values-ta-rIN/arrays.xml
+++ b/packages/SettingsLib/res/values-ta-rIN/arrays.xml
@@ -58,6 +58,46 @@
<item msgid="3878793616631049349">"DRM உள்ளடக்கத்திற்கு மட்டும் HDCP சோதனையைப் பயன்படுத்து"</item>
<item msgid="45075631231212732">"HDCP சரிபார்ப்பை எப்போதும் பயன்படுத்து"</item>
</string-array>
+ <!-- no translation found for bluetooth_a2dp_codec_titles:0 (1852387125374225729) -->
+ <!-- no translation found for bluetooth_a2dp_codec_titles:1 (7539690996561263909) -->
+ <!-- no translation found for bluetooth_a2dp_codec_titles:2 (4260844283202960798) -->
+ <!-- no translation found for bluetooth_a2dp_codec_titles:3 (7279983368484312990) -->
+ <!-- no translation found for bluetooth_a2dp_codec_titles:4 (2301339338870319651) -->
+ <!-- no translation found for bluetooth_a2dp_codec_summaries:0 (9072025520360316957) -->
+ <!-- no translation found for bluetooth_a2dp_codec_summaries:1 (6898329690939802290) -->
+ <!-- no translation found for bluetooth_a2dp_codec_summaries:2 (1190434429082395888) -->
+ <!-- no translation found for bluetooth_a2dp_codec_summaries:3 (649699003004233053) -->
+ <!-- no translation found for bluetooth_a2dp_codec_summaries:4 (508106435710925399) -->
+ <!-- no translation found for bluetooth_a2dp_codec_sample_rate_titles:0 (7102940318360468759) -->
+ <!-- no translation found for bluetooth_a2dp_codec_sample_rate_titles:1 (8895532488906185219) -->
+ <!-- no translation found for bluetooth_a2dp_codec_sample_rate_titles:2 (2909915718994807056) -->
+ <!-- no translation found for bluetooth_a2dp_codec_sample_rate_titles:3 (3347287377354164611) -->
+ <!-- no translation found for bluetooth_a2dp_codec_sample_rate_titles:4 (1234212100239985373) -->
+ <!-- no translation found for bluetooth_a2dp_codec_sample_rate_summaries:0 (7224433008148687313) -->
+ <!-- no translation found for bluetooth_a2dp_codec_sample_rate_summaries:1 (4482862757811638365) -->
+ <!-- no translation found for bluetooth_a2dp_codec_sample_rate_summaries:2 (354495328188724404) -->
+ <!-- no translation found for bluetooth_a2dp_codec_sample_rate_summaries:3 (7329816882213695083) -->
+ <!-- no translation found for bluetooth_a2dp_codec_sample_rate_summaries:4 (6967397666254430476) -->
+ <!-- no translation found for bluetooth_a2dp_codec_bits_per_sample_titles:0 (6694044160540313386) -->
+ <!-- no translation found for bluetooth_a2dp_codec_bits_per_sample_titles:1 (5618929009984956469) -->
+ <!-- no translation found for bluetooth_a2dp_codec_bits_per_sample_titles:2 (3412640499234627248) -->
+ <!-- no translation found for bluetooth_a2dp_codec_bits_per_sample_titles:3 (121583001492929387) -->
+ <!-- no translation found for bluetooth_a2dp_codec_bits_per_sample_summaries:0 (5091076677792306320) -->
+ <!-- no translation found for bluetooth_a2dp_codec_bits_per_sample_summaries:1 (4726688794884191540) -->
+ <!-- no translation found for bluetooth_a2dp_codec_bits_per_sample_summaries:2 (305344756485516870) -->
+ <!-- no translation found for bluetooth_a2dp_codec_bits_per_sample_summaries:3 (244568657919675099) -->
+ <!-- no translation found for bluetooth_a2dp_codec_channel_mode_titles:0 (13423709606339855) -->
+ <!-- no translation found for bluetooth_a2dp_codec_channel_mode_titles:1 (4106832974775067314) -->
+ <!-- no translation found for bluetooth_a2dp_codec_channel_mode_titles:2 (5571632958424639155) -->
+ <!-- no translation found for bluetooth_a2dp_codec_channel_mode_summaries:0 (8128478683963250130) -->
+ <!-- no translation found for bluetooth_a2dp_codec_channel_mode_summaries:1 (8900559293912978337) -->
+ <!-- no translation found for bluetooth_a2dp_codec_channel_mode_summaries:2 (8883739882299884241) -->
+ <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_titles:0 (2944889121850394020) -->
+ <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_titles:1 (138837449700903545) -->
+ <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_titles:2 (4777177307869441982) -->
+ <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_summaries:0 (172302906231378902) -->
+ <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_summaries:1 (9091111147684472529) -->
+ <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_summaries:2 (3367904477834831032) -->
<string-array name="select_logd_size_titles">
<item msgid="8665206199209698501">"முடக்கு"</item>
<item msgid="1593289376502312923">"64K"</item>
diff --git a/packages/SettingsLib/res/values-ta-rIN/strings.xml b/packages/SettingsLib/res/values-ta-rIN/strings.xml
index daf3ff2..60aa419 100644
--- a/packages/SettingsLib/res/values-ta-rIN/strings.xml
+++ b/packages/SettingsLib/res/values-ta-rIN/strings.xml
@@ -170,6 +170,26 @@
<string name="wifi_allow_scan_with_traffic" msgid="3601853081178265786">"எப்போதும் வைஃபை ரோமிங் ஸ்கேன்களை அனுமதி"</string>
<string name="mobile_data_always_on" msgid="7745605759775320362">"செல்லுலார் தரவு எப்போதும் இயக்கத்தில்"</string>
<string name="bluetooth_disable_absolute_volume" msgid="2660673801947898809">"அப்சல்யூட் ஒலியளவு அம்சத்தை முடக்கு"</string>
+ <!-- no translation found for bluetooth_select_a2dp_codec_type (90597356942154882) -->
+ <skip />
+ <!-- no translation found for bluetooth_select_a2dp_codec_type_dialog_title (6470824182074383881) -->
+ <skip />
+ <!-- no translation found for bluetooth_select_a2dp_codec_sample_rate (4788245703824623062) -->
+ <skip />
+ <!-- no translation found for bluetooth_select_a2dp_codec_sample_rate_dialog_title (4263851572248033749) -->
+ <skip />
+ <!-- no translation found for bluetooth_select_a2dp_codec_bits_per_sample (2099645202720164141) -->
+ <skip />
+ <!-- no translation found for bluetooth_select_a2dp_codec_bits_per_sample_dialog_title (2096170505745650345) -->
+ <skip />
+ <!-- no translation found for bluetooth_select_a2dp_codec_channel_mode (884855779449390540) -->
+ <skip />
+ <!-- no translation found for bluetooth_select_a2dp_codec_channel_mode_dialog_title (4073812880900816325) -->
+ <skip />
+ <!-- no translation found for bluetooth_select_a2dp_codec_ldac_playback_quality (4846872213548295632) -->
+ <skip />
+ <!-- no translation found for bluetooth_select_a2dp_codec_ldac_playback_quality_dialog_title (3940973633342423717) -->
+ <skip />
<string name="wifi_display_certification_summary" msgid="1155182309166746973">"வயர்லெஸ் காட்சி சான்றுக்கான விருப்பங்களைக் காட்டு"</string>
<string name="wifi_verbose_logging_summary" msgid="6615071616111731958">"Wifi நுழைவு அளவை அதிகரித்து, வைஃபை தேர்வியில் ஒவ்வொன்றிற்கும் SSID RSSI ஐ காட்டுக"</string>
<string name="wifi_aggressive_handover_summary" msgid="6328455667642570371">"இயக்கப்பட்டதும், வைஃபை சிக்னல் குறையும் போது, வைஃபை முழுமையாக ஒத்துழைக்காமல் இருப்பதால் செல்லுலாரின் தரவு இணைப்புக்கு மாறும்"</string>
diff --git a/packages/SettingsLib/res/values-te-rIN/arrays.xml b/packages/SettingsLib/res/values-te-rIN/arrays.xml
index f1d20b7..ac69bd5 100644
--- a/packages/SettingsLib/res/values-te-rIN/arrays.xml
+++ b/packages/SettingsLib/res/values-te-rIN/arrays.xml
@@ -58,6 +58,46 @@
<item msgid="3878793616631049349">"DRM కంటెంట్కు మాత్రమే HDCP తనిఖీని ఉపయోగించండి"</item>
<item msgid="45075631231212732">"ఎప్పటికీ HDCP తనిఖీని ఉపయోగించు"</item>
</string-array>
+ <!-- no translation found for bluetooth_a2dp_codec_titles:0 (1852387125374225729) -->
+ <!-- no translation found for bluetooth_a2dp_codec_titles:1 (7539690996561263909) -->
+ <!-- no translation found for bluetooth_a2dp_codec_titles:2 (4260844283202960798) -->
+ <!-- no translation found for bluetooth_a2dp_codec_titles:3 (7279983368484312990) -->
+ <!-- no translation found for bluetooth_a2dp_codec_titles:4 (2301339338870319651) -->
+ <!-- no translation found for bluetooth_a2dp_codec_summaries:0 (9072025520360316957) -->
+ <!-- no translation found for bluetooth_a2dp_codec_summaries:1 (6898329690939802290) -->
+ <!-- no translation found for bluetooth_a2dp_codec_summaries:2 (1190434429082395888) -->
+ <!-- no translation found for bluetooth_a2dp_codec_summaries:3 (649699003004233053) -->
+ <!-- no translation found for bluetooth_a2dp_codec_summaries:4 (508106435710925399) -->
+ <!-- no translation found for bluetooth_a2dp_codec_sample_rate_titles:0 (7102940318360468759) -->
+ <!-- no translation found for bluetooth_a2dp_codec_sample_rate_titles:1 (8895532488906185219) -->
+ <!-- no translation found for bluetooth_a2dp_codec_sample_rate_titles:2 (2909915718994807056) -->
+ <!-- no translation found for bluetooth_a2dp_codec_sample_rate_titles:3 (3347287377354164611) -->
+ <!-- no translation found for bluetooth_a2dp_codec_sample_rate_titles:4 (1234212100239985373) -->
+ <!-- no translation found for bluetooth_a2dp_codec_sample_rate_summaries:0 (7224433008148687313) -->
+ <!-- no translation found for bluetooth_a2dp_codec_sample_rate_summaries:1 (4482862757811638365) -->
+ <!-- no translation found for bluetooth_a2dp_codec_sample_rate_summaries:2 (354495328188724404) -->
+ <!-- no translation found for bluetooth_a2dp_codec_sample_rate_summaries:3 (7329816882213695083) -->
+ <!-- no translation found for bluetooth_a2dp_codec_sample_rate_summaries:4 (6967397666254430476) -->
+ <!-- no translation found for bluetooth_a2dp_codec_bits_per_sample_titles:0 (6694044160540313386) -->
+ <!-- no translation found for bluetooth_a2dp_codec_bits_per_sample_titles:1 (5618929009984956469) -->
+ <!-- no translation found for bluetooth_a2dp_codec_bits_per_sample_titles:2 (3412640499234627248) -->
+ <!-- no translation found for bluetooth_a2dp_codec_bits_per_sample_titles:3 (121583001492929387) -->
+ <!-- no translation found for bluetooth_a2dp_codec_bits_per_sample_summaries:0 (5091076677792306320) -->
+ <!-- no translation found for bluetooth_a2dp_codec_bits_per_sample_summaries:1 (4726688794884191540) -->
+ <!-- no translation found for bluetooth_a2dp_codec_bits_per_sample_summaries:2 (305344756485516870) -->
+ <!-- no translation found for bluetooth_a2dp_codec_bits_per_sample_summaries:3 (244568657919675099) -->
+ <!-- no translation found for bluetooth_a2dp_codec_channel_mode_titles:0 (13423709606339855) -->
+ <!-- no translation found for bluetooth_a2dp_codec_channel_mode_titles:1 (4106832974775067314) -->
+ <!-- no translation found for bluetooth_a2dp_codec_channel_mode_titles:2 (5571632958424639155) -->
+ <!-- no translation found for bluetooth_a2dp_codec_channel_mode_summaries:0 (8128478683963250130) -->
+ <!-- no translation found for bluetooth_a2dp_codec_channel_mode_summaries:1 (8900559293912978337) -->
+ <!-- no translation found for bluetooth_a2dp_codec_channel_mode_summaries:2 (8883739882299884241) -->
+ <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_titles:0 (2944889121850394020) -->
+ <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_titles:1 (138837449700903545) -->
+ <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_titles:2 (4777177307869441982) -->
+ <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_summaries:0 (172302906231378902) -->
+ <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_summaries:1 (9091111147684472529) -->
+ <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_summaries:2 (3367904477834831032) -->
<string-array name="select_logd_size_titles">
<item msgid="8665206199209698501">"ఆఫ్"</item>
<item msgid="1593289376502312923">"64K"</item>
diff --git a/packages/SettingsLib/res/values-te-rIN/strings.xml b/packages/SettingsLib/res/values-te-rIN/strings.xml
index 31defb6..b7183e7 100644
--- a/packages/SettingsLib/res/values-te-rIN/strings.xml
+++ b/packages/SettingsLib/res/values-te-rIN/strings.xml
@@ -170,6 +170,26 @@
<string name="wifi_allow_scan_with_traffic" msgid="3601853081178265786">"Wi‑Fi సంచార స్కాన్లను ఎల్లప్పుడూ అనుమతించు"</string>
<string name="mobile_data_always_on" msgid="7745605759775320362">"ఎల్లప్పుడూ సెల్యులార్ డేటాను సక్రియంగా ఉంచు"</string>
<string name="bluetooth_disable_absolute_volume" msgid="2660673801947898809">"సంపూర్ణ వాల్యూమ్ను నిలిపివేయి"</string>
+ <!-- no translation found for bluetooth_select_a2dp_codec_type (90597356942154882) -->
+ <skip />
+ <!-- no translation found for bluetooth_select_a2dp_codec_type_dialog_title (6470824182074383881) -->
+ <skip />
+ <!-- no translation found for bluetooth_select_a2dp_codec_sample_rate (4788245703824623062) -->
+ <skip />
+ <!-- no translation found for bluetooth_select_a2dp_codec_sample_rate_dialog_title (4263851572248033749) -->
+ <skip />
+ <!-- no translation found for bluetooth_select_a2dp_codec_bits_per_sample (2099645202720164141) -->
+ <skip />
+ <!-- no translation found for bluetooth_select_a2dp_codec_bits_per_sample_dialog_title (2096170505745650345) -->
+ <skip />
+ <!-- no translation found for bluetooth_select_a2dp_codec_channel_mode (884855779449390540) -->
+ <skip />
+ <!-- no translation found for bluetooth_select_a2dp_codec_channel_mode_dialog_title (4073812880900816325) -->
+ <skip />
+ <!-- no translation found for bluetooth_select_a2dp_codec_ldac_playback_quality (4846872213548295632) -->
+ <skip />
+ <!-- no translation found for bluetooth_select_a2dp_codec_ldac_playback_quality_dialog_title (3940973633342423717) -->
+ <skip />
<string name="wifi_display_certification_summary" msgid="1155182309166746973">"వైర్లెస్ ప్రదర్శన ప్రమాణపత్రం కోసం ఎంపికలను చూపు"</string>
<string name="wifi_verbose_logging_summary" msgid="6615071616111731958">"Wi‑Fi ఎంపికలో SSID RSSI ప్రకారం చూపబడే Wi‑Fi లాగింగ్ స్థాయిని పెంచండి"</string>
<string name="wifi_aggressive_handover_summary" msgid="6328455667642570371">"ప్రారంభించబడినప్పుడు, Wi‑Fi సిగ్నల్ బలహీనంగా ఉంటే డేటా కనెక్షన్ను సెల్యులార్కి మార్చేలా Wi‑Fiపై మరింత తీవ్ర ఒత్తిడి కలుగుతుంది"</string>
diff --git a/packages/SettingsLib/res/values-th/arrays.xml b/packages/SettingsLib/res/values-th/arrays.xml
index 7ac53d9..2961d76 100644
--- a/packages/SettingsLib/res/values-th/arrays.xml
+++ b/packages/SettingsLib/res/values-th/arrays.xml
@@ -58,6 +58,46 @@
<item msgid="3878793616631049349">"ใช้การตรวจสอบ HDCP สำหรับเนื้อหา DRM เท่านั้น"</item>
<item msgid="45075631231212732">"ใช้การตรวจสอบ HDCP เสมอ"</item>
</string-array>
+ <!-- no translation found for bluetooth_a2dp_codec_titles:0 (1852387125374225729) -->
+ <!-- no translation found for bluetooth_a2dp_codec_titles:1 (7539690996561263909) -->
+ <!-- no translation found for bluetooth_a2dp_codec_titles:2 (4260844283202960798) -->
+ <!-- no translation found for bluetooth_a2dp_codec_titles:3 (7279983368484312990) -->
+ <!-- no translation found for bluetooth_a2dp_codec_titles:4 (2301339338870319651) -->
+ <!-- no translation found for bluetooth_a2dp_codec_summaries:0 (9072025520360316957) -->
+ <!-- no translation found for bluetooth_a2dp_codec_summaries:1 (6898329690939802290) -->
+ <!-- no translation found for bluetooth_a2dp_codec_summaries:2 (1190434429082395888) -->
+ <!-- no translation found for bluetooth_a2dp_codec_summaries:3 (649699003004233053) -->
+ <!-- no translation found for bluetooth_a2dp_codec_summaries:4 (508106435710925399) -->
+ <!-- no translation found for bluetooth_a2dp_codec_sample_rate_titles:0 (7102940318360468759) -->
+ <!-- no translation found for bluetooth_a2dp_codec_sample_rate_titles:1 (8895532488906185219) -->
+ <!-- no translation found for bluetooth_a2dp_codec_sample_rate_titles:2 (2909915718994807056) -->
+ <!-- no translation found for bluetooth_a2dp_codec_sample_rate_titles:3 (3347287377354164611) -->
+ <!-- no translation found for bluetooth_a2dp_codec_sample_rate_titles:4 (1234212100239985373) -->
+ <!-- no translation found for bluetooth_a2dp_codec_sample_rate_summaries:0 (7224433008148687313) -->
+ <!-- no translation found for bluetooth_a2dp_codec_sample_rate_summaries:1 (4482862757811638365) -->
+ <!-- no translation found for bluetooth_a2dp_codec_sample_rate_summaries:2 (354495328188724404) -->
+ <!-- no translation found for bluetooth_a2dp_codec_sample_rate_summaries:3 (7329816882213695083) -->
+ <!-- no translation found for bluetooth_a2dp_codec_sample_rate_summaries:4 (6967397666254430476) -->
+ <!-- no translation found for bluetooth_a2dp_codec_bits_per_sample_titles:0 (6694044160540313386) -->
+ <!-- no translation found for bluetooth_a2dp_codec_bits_per_sample_titles:1 (5618929009984956469) -->
+ <!-- no translation found for bluetooth_a2dp_codec_bits_per_sample_titles:2 (3412640499234627248) -->
+ <!-- no translation found for bluetooth_a2dp_codec_bits_per_sample_titles:3 (121583001492929387) -->
+ <!-- no translation found for bluetooth_a2dp_codec_bits_per_sample_summaries:0 (5091076677792306320) -->
+ <!-- no translation found for bluetooth_a2dp_codec_bits_per_sample_summaries:1 (4726688794884191540) -->
+ <!-- no translation found for bluetooth_a2dp_codec_bits_per_sample_summaries:2 (305344756485516870) -->
+ <!-- no translation found for bluetooth_a2dp_codec_bits_per_sample_summaries:3 (244568657919675099) -->
+ <!-- no translation found for bluetooth_a2dp_codec_channel_mode_titles:0 (13423709606339855) -->
+ <!-- no translation found for bluetooth_a2dp_codec_channel_mode_titles:1 (4106832974775067314) -->
+ <!-- no translation found for bluetooth_a2dp_codec_channel_mode_titles:2 (5571632958424639155) -->
+ <!-- no translation found for bluetooth_a2dp_codec_channel_mode_summaries:0 (8128478683963250130) -->
+ <!-- no translation found for bluetooth_a2dp_codec_channel_mode_summaries:1 (8900559293912978337) -->
+ <!-- no translation found for bluetooth_a2dp_codec_channel_mode_summaries:2 (8883739882299884241) -->
+ <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_titles:0 (2944889121850394020) -->
+ <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_titles:1 (138837449700903545) -->
+ <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_titles:2 (4777177307869441982) -->
+ <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_summaries:0 (172302906231378902) -->
+ <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_summaries:1 (9091111147684472529) -->
+ <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_summaries:2 (3367904477834831032) -->
<string-array name="select_logd_size_titles">
<item msgid="8665206199209698501">"ปิด"</item>
<item msgid="1593289376502312923">"64 K"</item>
diff --git a/packages/SettingsLib/res/values-th/strings.xml b/packages/SettingsLib/res/values-th/strings.xml
index 5ec5871..5f3f706 100644
--- a/packages/SettingsLib/res/values-th/strings.xml
+++ b/packages/SettingsLib/res/values-th/strings.xml
@@ -170,6 +170,26 @@
<string name="wifi_allow_scan_with_traffic" msgid="3601853081178265786">"ใช้การสแกน Wi-Fi ข้ามเครือข่ายเสมอ"</string>
<string name="mobile_data_always_on" msgid="7745605759775320362">"เปิดใช้ข้อมูลมือถือเสมอ"</string>
<string name="bluetooth_disable_absolute_volume" msgid="2660673801947898809">"ปิดใช้การควบคุมระดับเสียงของอุปกรณ์อื่น"</string>
+ <!-- no translation found for bluetooth_select_a2dp_codec_type (90597356942154882) -->
+ <skip />
+ <!-- no translation found for bluetooth_select_a2dp_codec_type_dialog_title (6470824182074383881) -->
+ <skip />
+ <!-- no translation found for bluetooth_select_a2dp_codec_sample_rate (4788245703824623062) -->
+ <skip />
+ <!-- no translation found for bluetooth_select_a2dp_codec_sample_rate_dialog_title (4263851572248033749) -->
+ <skip />
+ <!-- no translation found for bluetooth_select_a2dp_codec_bits_per_sample (2099645202720164141) -->
+ <skip />
+ <!-- no translation found for bluetooth_select_a2dp_codec_bits_per_sample_dialog_title (2096170505745650345) -->
+ <skip />
+ <!-- no translation found for bluetooth_select_a2dp_codec_channel_mode (884855779449390540) -->
+ <skip />
+ <!-- no translation found for bluetooth_select_a2dp_codec_channel_mode_dialog_title (4073812880900816325) -->
+ <skip />
+ <!-- no translation found for bluetooth_select_a2dp_codec_ldac_playback_quality (4846872213548295632) -->
+ <skip />
+ <!-- no translation found for bluetooth_select_a2dp_codec_ldac_playback_quality_dialog_title (3940973633342423717) -->
+ <skip />
<string name="wifi_display_certification_summary" msgid="1155182309166746973">"แสดงตัวเลือกสำหรับการรับรองการแสดงผล แบบไร้สาย"</string>
<string name="wifi_verbose_logging_summary" msgid="6615071616111731958">"เพิ่มระดับการบันทึก Wi‑Fi แสดงต่อ SSID RSSI ในตัวเลือก Wi‑Fi"</string>
<string name="wifi_aggressive_handover_summary" msgid="6328455667642570371">"เมื่อเปิดใช้แล้ว Wi-Fi จะส่งผ่านการเชื่อมต่อข้อมูลไปยังเครือข่ายมือถือในทันทีที่พบสัญญาณ Wi-Fi อ่อน"</string>
diff --git a/packages/SettingsLib/res/values-tl/arrays.xml b/packages/SettingsLib/res/values-tl/arrays.xml
index 756e865..fb6270e 100644
--- a/packages/SettingsLib/res/values-tl/arrays.xml
+++ b/packages/SettingsLib/res/values-tl/arrays.xml
@@ -58,6 +58,46 @@
<item msgid="3878793616631049349">"Gamitin lang ang pagsusuring HDCP para sa nilalamang DRM"</item>
<item msgid="45075631231212732">"Palaging gumamit ng pagsusuring HDCP"</item>
</string-array>
+ <!-- no translation found for bluetooth_a2dp_codec_titles:0 (1852387125374225729) -->
+ <!-- no translation found for bluetooth_a2dp_codec_titles:1 (7539690996561263909) -->
+ <!-- no translation found for bluetooth_a2dp_codec_titles:2 (4260844283202960798) -->
+ <!-- no translation found for bluetooth_a2dp_codec_titles:3 (7279983368484312990) -->
+ <!-- no translation found for bluetooth_a2dp_codec_titles:4 (2301339338870319651) -->
+ <!-- no translation found for bluetooth_a2dp_codec_summaries:0 (9072025520360316957) -->
+ <!-- no translation found for bluetooth_a2dp_codec_summaries:1 (6898329690939802290) -->
+ <!-- no translation found for bluetooth_a2dp_codec_summaries:2 (1190434429082395888) -->
+ <!-- no translation found for bluetooth_a2dp_codec_summaries:3 (649699003004233053) -->
+ <!-- no translation found for bluetooth_a2dp_codec_summaries:4 (508106435710925399) -->
+ <!-- no translation found for bluetooth_a2dp_codec_sample_rate_titles:0 (7102940318360468759) -->
+ <!-- no translation found for bluetooth_a2dp_codec_sample_rate_titles:1 (8895532488906185219) -->
+ <!-- no translation found for bluetooth_a2dp_codec_sample_rate_titles:2 (2909915718994807056) -->
+ <!-- no translation found for bluetooth_a2dp_codec_sample_rate_titles:3 (3347287377354164611) -->
+ <!-- no translation found for bluetooth_a2dp_codec_sample_rate_titles:4 (1234212100239985373) -->
+ <!-- no translation found for bluetooth_a2dp_codec_sample_rate_summaries:0 (7224433008148687313) -->
+ <!-- no translation found for bluetooth_a2dp_codec_sample_rate_summaries:1 (4482862757811638365) -->
+ <!-- no translation found for bluetooth_a2dp_codec_sample_rate_summaries:2 (354495328188724404) -->
+ <!-- no translation found for bluetooth_a2dp_codec_sample_rate_summaries:3 (7329816882213695083) -->
+ <!-- no translation found for bluetooth_a2dp_codec_sample_rate_summaries:4 (6967397666254430476) -->
+ <!-- no translation found for bluetooth_a2dp_codec_bits_per_sample_titles:0 (6694044160540313386) -->
+ <!-- no translation found for bluetooth_a2dp_codec_bits_per_sample_titles:1 (5618929009984956469) -->
+ <!-- no translation found for bluetooth_a2dp_codec_bits_per_sample_titles:2 (3412640499234627248) -->
+ <!-- no translation found for bluetooth_a2dp_codec_bits_per_sample_titles:3 (121583001492929387) -->
+ <!-- no translation found for bluetooth_a2dp_codec_bits_per_sample_summaries:0 (5091076677792306320) -->
+ <!-- no translation found for bluetooth_a2dp_codec_bits_per_sample_summaries:1 (4726688794884191540) -->
+ <!-- no translation found for bluetooth_a2dp_codec_bits_per_sample_summaries:2 (305344756485516870) -->
+ <!-- no translation found for bluetooth_a2dp_codec_bits_per_sample_summaries:3 (244568657919675099) -->
+ <!-- no translation found for bluetooth_a2dp_codec_channel_mode_titles:0 (13423709606339855) -->
+ <!-- no translation found for bluetooth_a2dp_codec_channel_mode_titles:1 (4106832974775067314) -->
+ <!-- no translation found for bluetooth_a2dp_codec_channel_mode_titles:2 (5571632958424639155) -->
+ <!-- no translation found for bluetooth_a2dp_codec_channel_mode_summaries:0 (8128478683963250130) -->
+ <!-- no translation found for bluetooth_a2dp_codec_channel_mode_summaries:1 (8900559293912978337) -->
+ <!-- no translation found for bluetooth_a2dp_codec_channel_mode_summaries:2 (8883739882299884241) -->
+ <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_titles:0 (2944889121850394020) -->
+ <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_titles:1 (138837449700903545) -->
+ <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_titles:2 (4777177307869441982) -->
+ <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_summaries:0 (172302906231378902) -->
+ <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_summaries:1 (9091111147684472529) -->
+ <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_summaries:2 (3367904477834831032) -->
<string-array name="select_logd_size_titles">
<item msgid="8665206199209698501">"I-off"</item>
<item msgid="1593289376502312923">"64K"</item>
diff --git a/packages/SettingsLib/res/values-tl/strings.xml b/packages/SettingsLib/res/values-tl/strings.xml
index 07e1c8bd..e6017a2 100644
--- a/packages/SettingsLib/res/values-tl/strings.xml
+++ b/packages/SettingsLib/res/values-tl/strings.xml
@@ -170,6 +170,26 @@
<string name="wifi_allow_scan_with_traffic" msgid="3601853081178265786">"Palaging payagan ang Mga Pag-scan sa Roaming ng Wi‑Fi"</string>
<string name="mobile_data_always_on" msgid="7745605759775320362">"Palaging aktibo ang cellular data"</string>
<string name="bluetooth_disable_absolute_volume" msgid="2660673801947898809">"I-disable ang absolute volume"</string>
+ <!-- no translation found for bluetooth_select_a2dp_codec_type (90597356942154882) -->
+ <skip />
+ <!-- no translation found for bluetooth_select_a2dp_codec_type_dialog_title (6470824182074383881) -->
+ <skip />
+ <!-- no translation found for bluetooth_select_a2dp_codec_sample_rate (4788245703824623062) -->
+ <skip />
+ <!-- no translation found for bluetooth_select_a2dp_codec_sample_rate_dialog_title (4263851572248033749) -->
+ <skip />
+ <!-- no translation found for bluetooth_select_a2dp_codec_bits_per_sample (2099645202720164141) -->
+ <skip />
+ <!-- no translation found for bluetooth_select_a2dp_codec_bits_per_sample_dialog_title (2096170505745650345) -->
+ <skip />
+ <!-- no translation found for bluetooth_select_a2dp_codec_channel_mode (884855779449390540) -->
+ <skip />
+ <!-- no translation found for bluetooth_select_a2dp_codec_channel_mode_dialog_title (4073812880900816325) -->
+ <skip />
+ <!-- no translation found for bluetooth_select_a2dp_codec_ldac_playback_quality (4846872213548295632) -->
+ <skip />
+ <!-- no translation found for bluetooth_select_a2dp_codec_ldac_playback_quality_dialog_title (3940973633342423717) -->
+ <skip />
<string name="wifi_display_certification_summary" msgid="1155182309166746973">"Ipakita ang mga opsyon para sa certification ng wireless display"</string>
<string name="wifi_verbose_logging_summary" msgid="6615071616111731958">"Pataasin ang antas ng Wi‑Fi logging, ipakita sa bawat SSID RSSI sa Wi‑Fi Picker"</string>
<string name="wifi_aggressive_handover_summary" msgid="6328455667642570371">"Kapag naka-enable, mas magiging agresibo ang Wi‑Fi sa paglipat ng koneksyon ng data sa Cellular, kapag mahina ang signal ng Wi‑Fi"</string>
diff --git a/packages/SettingsLib/res/values-tr/arrays.xml b/packages/SettingsLib/res/values-tr/arrays.xml
index ec989a4..f54c42d 100644
--- a/packages/SettingsLib/res/values-tr/arrays.xml
+++ b/packages/SettingsLib/res/values-tr/arrays.xml
@@ -58,6 +58,46 @@
<item msgid="3878793616631049349">"HDCP denetimini yalnızca DRM içeriği için kullan"</item>
<item msgid="45075631231212732">"HDCP denetimini her zaman kullan"</item>
</string-array>
+ <!-- no translation found for bluetooth_a2dp_codec_titles:0 (1852387125374225729) -->
+ <!-- no translation found for bluetooth_a2dp_codec_titles:1 (7539690996561263909) -->
+ <!-- no translation found for bluetooth_a2dp_codec_titles:2 (4260844283202960798) -->
+ <!-- no translation found for bluetooth_a2dp_codec_titles:3 (7279983368484312990) -->
+ <!-- no translation found for bluetooth_a2dp_codec_titles:4 (2301339338870319651) -->
+ <!-- no translation found for bluetooth_a2dp_codec_summaries:0 (9072025520360316957) -->
+ <!-- no translation found for bluetooth_a2dp_codec_summaries:1 (6898329690939802290) -->
+ <!-- no translation found for bluetooth_a2dp_codec_summaries:2 (1190434429082395888) -->
+ <!-- no translation found for bluetooth_a2dp_codec_summaries:3 (649699003004233053) -->
+ <!-- no translation found for bluetooth_a2dp_codec_summaries:4 (508106435710925399) -->
+ <!-- no translation found for bluetooth_a2dp_codec_sample_rate_titles:0 (7102940318360468759) -->
+ <!-- no translation found for bluetooth_a2dp_codec_sample_rate_titles:1 (8895532488906185219) -->
+ <!-- no translation found for bluetooth_a2dp_codec_sample_rate_titles:2 (2909915718994807056) -->
+ <!-- no translation found for bluetooth_a2dp_codec_sample_rate_titles:3 (3347287377354164611) -->
+ <!-- no translation found for bluetooth_a2dp_codec_sample_rate_titles:4 (1234212100239985373) -->
+ <!-- no translation found for bluetooth_a2dp_codec_sample_rate_summaries:0 (7224433008148687313) -->
+ <!-- no translation found for bluetooth_a2dp_codec_sample_rate_summaries:1 (4482862757811638365) -->
+ <!-- no translation found for bluetooth_a2dp_codec_sample_rate_summaries:2 (354495328188724404) -->
+ <!-- no translation found for bluetooth_a2dp_codec_sample_rate_summaries:3 (7329816882213695083) -->
+ <!-- no translation found for bluetooth_a2dp_codec_sample_rate_summaries:4 (6967397666254430476) -->
+ <!-- no translation found for bluetooth_a2dp_codec_bits_per_sample_titles:0 (6694044160540313386) -->
+ <!-- no translation found for bluetooth_a2dp_codec_bits_per_sample_titles:1 (5618929009984956469) -->
+ <!-- no translation found for bluetooth_a2dp_codec_bits_per_sample_titles:2 (3412640499234627248) -->
+ <!-- no translation found for bluetooth_a2dp_codec_bits_per_sample_titles:3 (121583001492929387) -->
+ <!-- no translation found for bluetooth_a2dp_codec_bits_per_sample_summaries:0 (5091076677792306320) -->
+ <!-- no translation found for bluetooth_a2dp_codec_bits_per_sample_summaries:1 (4726688794884191540) -->
+ <!-- no translation found for bluetooth_a2dp_codec_bits_per_sample_summaries:2 (305344756485516870) -->
+ <!-- no translation found for bluetooth_a2dp_codec_bits_per_sample_summaries:3 (244568657919675099) -->
+ <!-- no translation found for bluetooth_a2dp_codec_channel_mode_titles:0 (13423709606339855) -->
+ <!-- no translation found for bluetooth_a2dp_codec_channel_mode_titles:1 (4106832974775067314) -->
+ <!-- no translation found for bluetooth_a2dp_codec_channel_mode_titles:2 (5571632958424639155) -->
+ <!-- no translation found for bluetooth_a2dp_codec_channel_mode_summaries:0 (8128478683963250130) -->
+ <!-- no translation found for bluetooth_a2dp_codec_channel_mode_summaries:1 (8900559293912978337) -->
+ <!-- no translation found for bluetooth_a2dp_codec_channel_mode_summaries:2 (8883739882299884241) -->
+ <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_titles:0 (2944889121850394020) -->
+ <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_titles:1 (138837449700903545) -->
+ <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_titles:2 (4777177307869441982) -->
+ <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_summaries:0 (172302906231378902) -->
+ <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_summaries:1 (9091111147684472529) -->
+ <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_summaries:2 (3367904477834831032) -->
<string-array name="select_logd_size_titles">
<item msgid="8665206199209698501">"Kapalı"</item>
<item msgid="1593289376502312923">"64 KB"</item>
diff --git a/packages/SettingsLib/res/values-tr/strings.xml b/packages/SettingsLib/res/values-tr/strings.xml
index 78b4a61..fa91388 100644
--- a/packages/SettingsLib/res/values-tr/strings.xml
+++ b/packages/SettingsLib/res/values-tr/strings.xml
@@ -170,6 +170,26 @@
<string name="wifi_allow_scan_with_traffic" msgid="3601853081178265786">"Kablosuz Dolaşım Taramalarına daima izin ver"</string>
<string name="mobile_data_always_on" msgid="7745605759775320362">"Hücresel veri her zaman etkin"</string>
<string name="bluetooth_disable_absolute_volume" msgid="2660673801947898809">"Mutlak sesi iptal et"</string>
+ <!-- no translation found for bluetooth_select_a2dp_codec_type (90597356942154882) -->
+ <skip />
+ <!-- no translation found for bluetooth_select_a2dp_codec_type_dialog_title (6470824182074383881) -->
+ <skip />
+ <!-- no translation found for bluetooth_select_a2dp_codec_sample_rate (4788245703824623062) -->
+ <skip />
+ <!-- no translation found for bluetooth_select_a2dp_codec_sample_rate_dialog_title (4263851572248033749) -->
+ <skip />
+ <!-- no translation found for bluetooth_select_a2dp_codec_bits_per_sample (2099645202720164141) -->
+ <skip />
+ <!-- no translation found for bluetooth_select_a2dp_codec_bits_per_sample_dialog_title (2096170505745650345) -->
+ <skip />
+ <!-- no translation found for bluetooth_select_a2dp_codec_channel_mode (884855779449390540) -->
+ <skip />
+ <!-- no translation found for bluetooth_select_a2dp_codec_channel_mode_dialog_title (4073812880900816325) -->
+ <skip />
+ <!-- no translation found for bluetooth_select_a2dp_codec_ldac_playback_quality (4846872213548295632) -->
+ <skip />
+ <!-- no translation found for bluetooth_select_a2dp_codec_ldac_playback_quality_dialog_title (3940973633342423717) -->
+ <skip />
<string name="wifi_display_certification_summary" msgid="1155182309166746973">"Kablosuz ekran sertifikası seçeneklerini göster"</string>
<string name="wifi_verbose_logging_summary" msgid="6615071616111731958">"Kablosuz günlük kaydı seviyesini artır. Kablosuz Seçici\'de her bir SSID RSSI için göster."</string>
<string name="wifi_aggressive_handover_summary" msgid="6328455667642570371">"Etkinleştirildiğinde, Kablosuz ağ sinyali zayıfken veri bağlantısının Hücresel ağa geçirilmesinde daha agresif olunur"</string>
diff --git a/packages/SettingsLib/res/values-uk/arrays.xml b/packages/SettingsLib/res/values-uk/arrays.xml
index e546fa2..2fa8ace 100644
--- a/packages/SettingsLib/res/values-uk/arrays.xml
+++ b/packages/SettingsLib/res/values-uk/arrays.xml
@@ -58,6 +58,46 @@
<item msgid="3878793616631049349">"Використовувати перевірку HDCP лише для вмісту, захищеного DRM"</item>
<item msgid="45075631231212732">"Завжди використовувати перевірку HDCP"</item>
</string-array>
+ <!-- no translation found for bluetooth_a2dp_codec_titles:0 (1852387125374225729) -->
+ <!-- no translation found for bluetooth_a2dp_codec_titles:1 (7539690996561263909) -->
+ <!-- no translation found for bluetooth_a2dp_codec_titles:2 (4260844283202960798) -->
+ <!-- no translation found for bluetooth_a2dp_codec_titles:3 (7279983368484312990) -->
+ <!-- no translation found for bluetooth_a2dp_codec_titles:4 (2301339338870319651) -->
+ <!-- no translation found for bluetooth_a2dp_codec_summaries:0 (9072025520360316957) -->
+ <!-- no translation found for bluetooth_a2dp_codec_summaries:1 (6898329690939802290) -->
+ <!-- no translation found for bluetooth_a2dp_codec_summaries:2 (1190434429082395888) -->
+ <!-- no translation found for bluetooth_a2dp_codec_summaries:3 (649699003004233053) -->
+ <!-- no translation found for bluetooth_a2dp_codec_summaries:4 (508106435710925399) -->
+ <!-- no translation found for bluetooth_a2dp_codec_sample_rate_titles:0 (7102940318360468759) -->
+ <!-- no translation found for bluetooth_a2dp_codec_sample_rate_titles:1 (8895532488906185219) -->
+ <!-- no translation found for bluetooth_a2dp_codec_sample_rate_titles:2 (2909915718994807056) -->
+ <!-- no translation found for bluetooth_a2dp_codec_sample_rate_titles:3 (3347287377354164611) -->
+ <!-- no translation found for bluetooth_a2dp_codec_sample_rate_titles:4 (1234212100239985373) -->
+ <!-- no translation found for bluetooth_a2dp_codec_sample_rate_summaries:0 (7224433008148687313) -->
+ <!-- no translation found for bluetooth_a2dp_codec_sample_rate_summaries:1 (4482862757811638365) -->
+ <!-- no translation found for bluetooth_a2dp_codec_sample_rate_summaries:2 (354495328188724404) -->
+ <!-- no translation found for bluetooth_a2dp_codec_sample_rate_summaries:3 (7329816882213695083) -->
+ <!-- no translation found for bluetooth_a2dp_codec_sample_rate_summaries:4 (6967397666254430476) -->
+ <!-- no translation found for bluetooth_a2dp_codec_bits_per_sample_titles:0 (6694044160540313386) -->
+ <!-- no translation found for bluetooth_a2dp_codec_bits_per_sample_titles:1 (5618929009984956469) -->
+ <!-- no translation found for bluetooth_a2dp_codec_bits_per_sample_titles:2 (3412640499234627248) -->
+ <!-- no translation found for bluetooth_a2dp_codec_bits_per_sample_titles:3 (121583001492929387) -->
+ <!-- no translation found for bluetooth_a2dp_codec_bits_per_sample_summaries:0 (5091076677792306320) -->
+ <!-- no translation found for bluetooth_a2dp_codec_bits_per_sample_summaries:1 (4726688794884191540) -->
+ <!-- no translation found for bluetooth_a2dp_codec_bits_per_sample_summaries:2 (305344756485516870) -->
+ <!-- no translation found for bluetooth_a2dp_codec_bits_per_sample_summaries:3 (244568657919675099) -->
+ <!-- no translation found for bluetooth_a2dp_codec_channel_mode_titles:0 (13423709606339855) -->
+ <!-- no translation found for bluetooth_a2dp_codec_channel_mode_titles:1 (4106832974775067314) -->
+ <!-- no translation found for bluetooth_a2dp_codec_channel_mode_titles:2 (5571632958424639155) -->
+ <!-- no translation found for bluetooth_a2dp_codec_channel_mode_summaries:0 (8128478683963250130) -->
+ <!-- no translation found for bluetooth_a2dp_codec_channel_mode_summaries:1 (8900559293912978337) -->
+ <!-- no translation found for bluetooth_a2dp_codec_channel_mode_summaries:2 (8883739882299884241) -->
+ <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_titles:0 (2944889121850394020) -->
+ <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_titles:1 (138837449700903545) -->
+ <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_titles:2 (4777177307869441982) -->
+ <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_summaries:0 (172302906231378902) -->
+ <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_summaries:1 (9091111147684472529) -->
+ <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_summaries:2 (3367904477834831032) -->
<string-array name="select_logd_size_titles">
<item msgid="8665206199209698501">"Вимкнено"</item>
<item msgid="1593289376502312923">"64 Кб"</item>
diff --git a/packages/SettingsLib/res/values-uk/strings.xml b/packages/SettingsLib/res/values-uk/strings.xml
index 29557ec..9d4c69b 100644
--- a/packages/SettingsLib/res/values-uk/strings.xml
+++ b/packages/SettingsLib/res/values-uk/strings.xml
@@ -170,6 +170,26 @@
<string name="wifi_allow_scan_with_traffic" msgid="3601853081178265786">"Завжди шукати мережі Wi-Fi"</string>
<string name="mobile_data_always_on" msgid="7745605759775320362">"Не вимикати передавання даних"</string>
<string name="bluetooth_disable_absolute_volume" msgid="2660673801947898809">"Вимкнути абсолютну гучність"</string>
+ <!-- no translation found for bluetooth_select_a2dp_codec_type (90597356942154882) -->
+ <skip />
+ <!-- no translation found for bluetooth_select_a2dp_codec_type_dialog_title (6470824182074383881) -->
+ <skip />
+ <!-- no translation found for bluetooth_select_a2dp_codec_sample_rate (4788245703824623062) -->
+ <skip />
+ <!-- no translation found for bluetooth_select_a2dp_codec_sample_rate_dialog_title (4263851572248033749) -->
+ <skip />
+ <!-- no translation found for bluetooth_select_a2dp_codec_bits_per_sample (2099645202720164141) -->
+ <skip />
+ <!-- no translation found for bluetooth_select_a2dp_codec_bits_per_sample_dialog_title (2096170505745650345) -->
+ <skip />
+ <!-- no translation found for bluetooth_select_a2dp_codec_channel_mode (884855779449390540) -->
+ <skip />
+ <!-- no translation found for bluetooth_select_a2dp_codec_channel_mode_dialog_title (4073812880900816325) -->
+ <skip />
+ <!-- no translation found for bluetooth_select_a2dp_codec_ldac_playback_quality (4846872213548295632) -->
+ <skip />
+ <!-- no translation found for bluetooth_select_a2dp_codec_ldac_playback_quality_dialog_title (3940973633342423717) -->
+ <skip />
<string name="wifi_display_certification_summary" msgid="1155182309166746973">"Показати параметри сертифікації бездротового екрана"</string>
<string name="wifi_verbose_logging_summary" msgid="6615071616111731958">"Показувати в журналі RSSI для кожного SSID під час вибору Wi-Fi"</string>
<string name="wifi_aggressive_handover_summary" msgid="6328455667642570371">"Примусово перемикатися на мобільну мережу, коли сигнал Wi-Fi слабкий"</string>
diff --git a/packages/SettingsLib/res/values-ur-rPK/arrays.xml b/packages/SettingsLib/res/values-ur-rPK/arrays.xml
index 245fed8..3a692ffa4 100644
--- a/packages/SettingsLib/res/values-ur-rPK/arrays.xml
+++ b/packages/SettingsLib/res/values-ur-rPK/arrays.xml
@@ -58,6 +58,46 @@
<item msgid="3878793616631049349">"HDCP چیکنگ صرف DRM مواد کیلئے استعمال کریں"</item>
<item msgid="45075631231212732">"ہمیشہ HDCP چیکنگ استعمال کریں"</item>
</string-array>
+ <!-- no translation found for bluetooth_a2dp_codec_titles:0 (1852387125374225729) -->
+ <!-- no translation found for bluetooth_a2dp_codec_titles:1 (7539690996561263909) -->
+ <!-- no translation found for bluetooth_a2dp_codec_titles:2 (4260844283202960798) -->
+ <!-- no translation found for bluetooth_a2dp_codec_titles:3 (7279983368484312990) -->
+ <!-- no translation found for bluetooth_a2dp_codec_titles:4 (2301339338870319651) -->
+ <!-- no translation found for bluetooth_a2dp_codec_summaries:0 (9072025520360316957) -->
+ <!-- no translation found for bluetooth_a2dp_codec_summaries:1 (6898329690939802290) -->
+ <!-- no translation found for bluetooth_a2dp_codec_summaries:2 (1190434429082395888) -->
+ <!-- no translation found for bluetooth_a2dp_codec_summaries:3 (649699003004233053) -->
+ <!-- no translation found for bluetooth_a2dp_codec_summaries:4 (508106435710925399) -->
+ <!-- no translation found for bluetooth_a2dp_codec_sample_rate_titles:0 (7102940318360468759) -->
+ <!-- no translation found for bluetooth_a2dp_codec_sample_rate_titles:1 (8895532488906185219) -->
+ <!-- no translation found for bluetooth_a2dp_codec_sample_rate_titles:2 (2909915718994807056) -->
+ <!-- no translation found for bluetooth_a2dp_codec_sample_rate_titles:3 (3347287377354164611) -->
+ <!-- no translation found for bluetooth_a2dp_codec_sample_rate_titles:4 (1234212100239985373) -->
+ <!-- no translation found for bluetooth_a2dp_codec_sample_rate_summaries:0 (7224433008148687313) -->
+ <!-- no translation found for bluetooth_a2dp_codec_sample_rate_summaries:1 (4482862757811638365) -->
+ <!-- no translation found for bluetooth_a2dp_codec_sample_rate_summaries:2 (354495328188724404) -->
+ <!-- no translation found for bluetooth_a2dp_codec_sample_rate_summaries:3 (7329816882213695083) -->
+ <!-- no translation found for bluetooth_a2dp_codec_sample_rate_summaries:4 (6967397666254430476) -->
+ <!-- no translation found for bluetooth_a2dp_codec_bits_per_sample_titles:0 (6694044160540313386) -->
+ <!-- no translation found for bluetooth_a2dp_codec_bits_per_sample_titles:1 (5618929009984956469) -->
+ <!-- no translation found for bluetooth_a2dp_codec_bits_per_sample_titles:2 (3412640499234627248) -->
+ <!-- no translation found for bluetooth_a2dp_codec_bits_per_sample_titles:3 (121583001492929387) -->
+ <!-- no translation found for bluetooth_a2dp_codec_bits_per_sample_summaries:0 (5091076677792306320) -->
+ <!-- no translation found for bluetooth_a2dp_codec_bits_per_sample_summaries:1 (4726688794884191540) -->
+ <!-- no translation found for bluetooth_a2dp_codec_bits_per_sample_summaries:2 (305344756485516870) -->
+ <!-- no translation found for bluetooth_a2dp_codec_bits_per_sample_summaries:3 (244568657919675099) -->
+ <!-- no translation found for bluetooth_a2dp_codec_channel_mode_titles:0 (13423709606339855) -->
+ <!-- no translation found for bluetooth_a2dp_codec_channel_mode_titles:1 (4106832974775067314) -->
+ <!-- no translation found for bluetooth_a2dp_codec_channel_mode_titles:2 (5571632958424639155) -->
+ <!-- no translation found for bluetooth_a2dp_codec_channel_mode_summaries:0 (8128478683963250130) -->
+ <!-- no translation found for bluetooth_a2dp_codec_channel_mode_summaries:1 (8900559293912978337) -->
+ <!-- no translation found for bluetooth_a2dp_codec_channel_mode_summaries:2 (8883739882299884241) -->
+ <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_titles:0 (2944889121850394020) -->
+ <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_titles:1 (138837449700903545) -->
+ <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_titles:2 (4777177307869441982) -->
+ <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_summaries:0 (172302906231378902) -->
+ <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_summaries:1 (9091111147684472529) -->
+ <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_summaries:2 (3367904477834831032) -->
<string-array name="select_logd_size_titles">
<item msgid="8665206199209698501">"آف"</item>
<item msgid="1593289376502312923">"64K"</item>
diff --git a/packages/SettingsLib/res/values-ur-rPK/strings.xml b/packages/SettingsLib/res/values-ur-rPK/strings.xml
index e1b545f..785dba9 100644
--- a/packages/SettingsLib/res/values-ur-rPK/strings.xml
+++ b/packages/SettingsLib/res/values-ur-rPK/strings.xml
@@ -170,6 +170,26 @@
<string name="wifi_allow_scan_with_traffic" msgid="3601853081178265786">"ہمیشہ Wi‑Fi روم اسکینز کی اجازت دیں"</string>
<string name="mobile_data_always_on" msgid="7745605759775320362">"سیلولر ڈیٹا کو ہمیشہ فعال رکھیں"</string>
<string name="bluetooth_disable_absolute_volume" msgid="2660673801947898809">"مطلق والیوم کو غیر فعال کریں"</string>
+ <!-- no translation found for bluetooth_select_a2dp_codec_type (90597356942154882) -->
+ <skip />
+ <!-- no translation found for bluetooth_select_a2dp_codec_type_dialog_title (6470824182074383881) -->
+ <skip />
+ <!-- no translation found for bluetooth_select_a2dp_codec_sample_rate (4788245703824623062) -->
+ <skip />
+ <!-- no translation found for bluetooth_select_a2dp_codec_sample_rate_dialog_title (4263851572248033749) -->
+ <skip />
+ <!-- no translation found for bluetooth_select_a2dp_codec_bits_per_sample (2099645202720164141) -->
+ <skip />
+ <!-- no translation found for bluetooth_select_a2dp_codec_bits_per_sample_dialog_title (2096170505745650345) -->
+ <skip />
+ <!-- no translation found for bluetooth_select_a2dp_codec_channel_mode (884855779449390540) -->
+ <skip />
+ <!-- no translation found for bluetooth_select_a2dp_codec_channel_mode_dialog_title (4073812880900816325) -->
+ <skip />
+ <!-- no translation found for bluetooth_select_a2dp_codec_ldac_playback_quality (4846872213548295632) -->
+ <skip />
+ <!-- no translation found for bluetooth_select_a2dp_codec_ldac_playback_quality_dialog_title (3940973633342423717) -->
+ <skip />
<string name="wifi_display_certification_summary" msgid="1155182309166746973">"وائرلیس ڈسپلے سرٹیفیکیشن کیلئے اختیارات دکھائیں"</string>
<string name="wifi_verbose_logging_summary" msgid="6615071616111731958">"Wi‑Fi لاگنگ لیول میں اضافہ کریں، Wi‑Fi منتخب کنندہ میں فی SSID RSSI دکھائیں"</string>
<string name="wifi_aggressive_handover_summary" msgid="6328455667642570371">"فعال ہونے پر، جب Wi‑Fi سگنل کمزور ہوگا تو Wi‑Fi سیلولر پر ڈیٹا کنکشن بھیجنے کیلئے مزید جارحانہ کاروائی کرے گا۔"</string>
diff --git a/packages/SettingsLib/res/values-uz-rUZ/arrays.xml b/packages/SettingsLib/res/values-uz-rUZ/arrays.xml
index 69b9bfb..0db5a9a 100644
--- a/packages/SettingsLib/res/values-uz-rUZ/arrays.xml
+++ b/packages/SettingsLib/res/values-uz-rUZ/arrays.xml
@@ -58,6 +58,46 @@
<item msgid="3878793616631049349">"HDCP tekshiruvi faqat DRM kontent uchun ishlatilsin"</item>
<item msgid="45075631231212732">"Har doim HDCP tekshiruvidan foydalanilsin"</item>
</string-array>
+ <!-- no translation found for bluetooth_a2dp_codec_titles:0 (1852387125374225729) -->
+ <!-- no translation found for bluetooth_a2dp_codec_titles:1 (7539690996561263909) -->
+ <!-- no translation found for bluetooth_a2dp_codec_titles:2 (4260844283202960798) -->
+ <!-- no translation found for bluetooth_a2dp_codec_titles:3 (7279983368484312990) -->
+ <!-- no translation found for bluetooth_a2dp_codec_titles:4 (2301339338870319651) -->
+ <!-- no translation found for bluetooth_a2dp_codec_summaries:0 (9072025520360316957) -->
+ <!-- no translation found for bluetooth_a2dp_codec_summaries:1 (6898329690939802290) -->
+ <!-- no translation found for bluetooth_a2dp_codec_summaries:2 (1190434429082395888) -->
+ <!-- no translation found for bluetooth_a2dp_codec_summaries:3 (649699003004233053) -->
+ <!-- no translation found for bluetooth_a2dp_codec_summaries:4 (508106435710925399) -->
+ <!-- no translation found for bluetooth_a2dp_codec_sample_rate_titles:0 (7102940318360468759) -->
+ <!-- no translation found for bluetooth_a2dp_codec_sample_rate_titles:1 (8895532488906185219) -->
+ <!-- no translation found for bluetooth_a2dp_codec_sample_rate_titles:2 (2909915718994807056) -->
+ <!-- no translation found for bluetooth_a2dp_codec_sample_rate_titles:3 (3347287377354164611) -->
+ <!-- no translation found for bluetooth_a2dp_codec_sample_rate_titles:4 (1234212100239985373) -->
+ <!-- no translation found for bluetooth_a2dp_codec_sample_rate_summaries:0 (7224433008148687313) -->
+ <!-- no translation found for bluetooth_a2dp_codec_sample_rate_summaries:1 (4482862757811638365) -->
+ <!-- no translation found for bluetooth_a2dp_codec_sample_rate_summaries:2 (354495328188724404) -->
+ <!-- no translation found for bluetooth_a2dp_codec_sample_rate_summaries:3 (7329816882213695083) -->
+ <!-- no translation found for bluetooth_a2dp_codec_sample_rate_summaries:4 (6967397666254430476) -->
+ <!-- no translation found for bluetooth_a2dp_codec_bits_per_sample_titles:0 (6694044160540313386) -->
+ <!-- no translation found for bluetooth_a2dp_codec_bits_per_sample_titles:1 (5618929009984956469) -->
+ <!-- no translation found for bluetooth_a2dp_codec_bits_per_sample_titles:2 (3412640499234627248) -->
+ <!-- no translation found for bluetooth_a2dp_codec_bits_per_sample_titles:3 (121583001492929387) -->
+ <!-- no translation found for bluetooth_a2dp_codec_bits_per_sample_summaries:0 (5091076677792306320) -->
+ <!-- no translation found for bluetooth_a2dp_codec_bits_per_sample_summaries:1 (4726688794884191540) -->
+ <!-- no translation found for bluetooth_a2dp_codec_bits_per_sample_summaries:2 (305344756485516870) -->
+ <!-- no translation found for bluetooth_a2dp_codec_bits_per_sample_summaries:3 (244568657919675099) -->
+ <!-- no translation found for bluetooth_a2dp_codec_channel_mode_titles:0 (13423709606339855) -->
+ <!-- no translation found for bluetooth_a2dp_codec_channel_mode_titles:1 (4106832974775067314) -->
+ <!-- no translation found for bluetooth_a2dp_codec_channel_mode_titles:2 (5571632958424639155) -->
+ <!-- no translation found for bluetooth_a2dp_codec_channel_mode_summaries:0 (8128478683963250130) -->
+ <!-- no translation found for bluetooth_a2dp_codec_channel_mode_summaries:1 (8900559293912978337) -->
+ <!-- no translation found for bluetooth_a2dp_codec_channel_mode_summaries:2 (8883739882299884241) -->
+ <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_titles:0 (2944889121850394020) -->
+ <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_titles:1 (138837449700903545) -->
+ <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_titles:2 (4777177307869441982) -->
+ <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_summaries:0 (172302906231378902) -->
+ <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_summaries:1 (9091111147684472529) -->
+ <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_summaries:2 (3367904477834831032) -->
<string-array name="select_logd_size_titles">
<item msgid="8665206199209698501">"O‘chiq"</item>
<item msgid="1593289376502312923">"64 KB"</item>
diff --git a/packages/SettingsLib/res/values-uz-rUZ/strings.xml b/packages/SettingsLib/res/values-uz-rUZ/strings.xml
index 05879a2..d105b5f 100644
--- a/packages/SettingsLib/res/values-uz-rUZ/strings.xml
+++ b/packages/SettingsLib/res/values-uz-rUZ/strings.xml
@@ -170,6 +170,26 @@
<string name="wifi_allow_scan_with_traffic" msgid="3601853081178265786">"Wi-Fi tarmoqlarini qidirishga doim ruxsat"</string>
<string name="mobile_data_always_on" msgid="7745605759775320362">"Mobil internet o‘chirilmasin"</string>
<string name="bluetooth_disable_absolute_volume" msgid="2660673801947898809">"Ovoz balangligining mutlaq darajasini o‘chirib qo‘yish"</string>
+ <!-- no translation found for bluetooth_select_a2dp_codec_type (90597356942154882) -->
+ <skip />
+ <!-- no translation found for bluetooth_select_a2dp_codec_type_dialog_title (6470824182074383881) -->
+ <skip />
+ <!-- no translation found for bluetooth_select_a2dp_codec_sample_rate (4788245703824623062) -->
+ <skip />
+ <!-- no translation found for bluetooth_select_a2dp_codec_sample_rate_dialog_title (4263851572248033749) -->
+ <skip />
+ <!-- no translation found for bluetooth_select_a2dp_codec_bits_per_sample (2099645202720164141) -->
+ <skip />
+ <!-- no translation found for bluetooth_select_a2dp_codec_bits_per_sample_dialog_title (2096170505745650345) -->
+ <skip />
+ <!-- no translation found for bluetooth_select_a2dp_codec_channel_mode (884855779449390540) -->
+ <skip />
+ <!-- no translation found for bluetooth_select_a2dp_codec_channel_mode_dialog_title (4073812880900816325) -->
+ <skip />
+ <!-- no translation found for bluetooth_select_a2dp_codec_ldac_playback_quality (4846872213548295632) -->
+ <skip />
+ <!-- no translation found for bluetooth_select_a2dp_codec_ldac_playback_quality_dialog_title (3940973633342423717) -->
+ <skip />
<string name="wifi_display_certification_summary" msgid="1155182309166746973">"Simsiz monitorlarni sertifikatlash parametrini ko‘rsatish"</string>
<string name="wifi_verbose_logging_summary" msgid="6615071616111731958">"Wi-Fi ulanishini tanlashda har bir SSID uchun jurnalda ko‘rsatilsin"</string>
<string name="wifi_aggressive_handover_summary" msgid="6328455667642570371">"Agar ushbu funksiya yoqilsa, Wi-Fi signali past bo‘lganda internetga ulanish majburiy ravishda mobil internetga o‘tkaziladi."</string>
diff --git a/packages/SettingsLib/res/values-vi/arrays.xml b/packages/SettingsLib/res/values-vi/arrays.xml
index 4d79d39..b1f4d80 100644
--- a/packages/SettingsLib/res/values-vi/arrays.xml
+++ b/packages/SettingsLib/res/values-vi/arrays.xml
@@ -58,6 +58,46 @@
<item msgid="3878793616631049349">"Chỉ sử dụng kiểm tra HDCP cho nội dung DRM"</item>
<item msgid="45075631231212732">"Luôn sử dụng kiểm tra HDCP"</item>
</string-array>
+ <!-- no translation found for bluetooth_a2dp_codec_titles:0 (1852387125374225729) -->
+ <!-- no translation found for bluetooth_a2dp_codec_titles:1 (7539690996561263909) -->
+ <!-- no translation found for bluetooth_a2dp_codec_titles:2 (4260844283202960798) -->
+ <!-- no translation found for bluetooth_a2dp_codec_titles:3 (7279983368484312990) -->
+ <!-- no translation found for bluetooth_a2dp_codec_titles:4 (2301339338870319651) -->
+ <!-- no translation found for bluetooth_a2dp_codec_summaries:0 (9072025520360316957) -->
+ <!-- no translation found for bluetooth_a2dp_codec_summaries:1 (6898329690939802290) -->
+ <!-- no translation found for bluetooth_a2dp_codec_summaries:2 (1190434429082395888) -->
+ <!-- no translation found for bluetooth_a2dp_codec_summaries:3 (649699003004233053) -->
+ <!-- no translation found for bluetooth_a2dp_codec_summaries:4 (508106435710925399) -->
+ <!-- no translation found for bluetooth_a2dp_codec_sample_rate_titles:0 (7102940318360468759) -->
+ <!-- no translation found for bluetooth_a2dp_codec_sample_rate_titles:1 (8895532488906185219) -->
+ <!-- no translation found for bluetooth_a2dp_codec_sample_rate_titles:2 (2909915718994807056) -->
+ <!-- no translation found for bluetooth_a2dp_codec_sample_rate_titles:3 (3347287377354164611) -->
+ <!-- no translation found for bluetooth_a2dp_codec_sample_rate_titles:4 (1234212100239985373) -->
+ <!-- no translation found for bluetooth_a2dp_codec_sample_rate_summaries:0 (7224433008148687313) -->
+ <!-- no translation found for bluetooth_a2dp_codec_sample_rate_summaries:1 (4482862757811638365) -->
+ <!-- no translation found for bluetooth_a2dp_codec_sample_rate_summaries:2 (354495328188724404) -->
+ <!-- no translation found for bluetooth_a2dp_codec_sample_rate_summaries:3 (7329816882213695083) -->
+ <!-- no translation found for bluetooth_a2dp_codec_sample_rate_summaries:4 (6967397666254430476) -->
+ <!-- no translation found for bluetooth_a2dp_codec_bits_per_sample_titles:0 (6694044160540313386) -->
+ <!-- no translation found for bluetooth_a2dp_codec_bits_per_sample_titles:1 (5618929009984956469) -->
+ <!-- no translation found for bluetooth_a2dp_codec_bits_per_sample_titles:2 (3412640499234627248) -->
+ <!-- no translation found for bluetooth_a2dp_codec_bits_per_sample_titles:3 (121583001492929387) -->
+ <!-- no translation found for bluetooth_a2dp_codec_bits_per_sample_summaries:0 (5091076677792306320) -->
+ <!-- no translation found for bluetooth_a2dp_codec_bits_per_sample_summaries:1 (4726688794884191540) -->
+ <!-- no translation found for bluetooth_a2dp_codec_bits_per_sample_summaries:2 (305344756485516870) -->
+ <!-- no translation found for bluetooth_a2dp_codec_bits_per_sample_summaries:3 (244568657919675099) -->
+ <!-- no translation found for bluetooth_a2dp_codec_channel_mode_titles:0 (13423709606339855) -->
+ <!-- no translation found for bluetooth_a2dp_codec_channel_mode_titles:1 (4106832974775067314) -->
+ <!-- no translation found for bluetooth_a2dp_codec_channel_mode_titles:2 (5571632958424639155) -->
+ <!-- no translation found for bluetooth_a2dp_codec_channel_mode_summaries:0 (8128478683963250130) -->
+ <!-- no translation found for bluetooth_a2dp_codec_channel_mode_summaries:1 (8900559293912978337) -->
+ <!-- no translation found for bluetooth_a2dp_codec_channel_mode_summaries:2 (8883739882299884241) -->
+ <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_titles:0 (2944889121850394020) -->
+ <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_titles:1 (138837449700903545) -->
+ <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_titles:2 (4777177307869441982) -->
+ <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_summaries:0 (172302906231378902) -->
+ <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_summaries:1 (9091111147684472529) -->
+ <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_summaries:2 (3367904477834831032) -->
<string-array name="select_logd_size_titles">
<item msgid="8665206199209698501">"Tắt"</item>
<item msgid="1593289376502312923">"64K"</item>
diff --git a/packages/SettingsLib/res/values-vi/strings.xml b/packages/SettingsLib/res/values-vi/strings.xml
index 28dbe51..db3a18f 100644
--- a/packages/SettingsLib/res/values-vi/strings.xml
+++ b/packages/SettingsLib/res/values-vi/strings.xml
@@ -170,6 +170,26 @@
<string name="wifi_allow_scan_with_traffic" msgid="3601853081178265786">"Luôn cho phép quét chuyển vùng Wi‑Fi"</string>
<string name="mobile_data_always_on" msgid="7745605759775320362">"Dữ liệu di động luôn hoạt động"</string>
<string name="bluetooth_disable_absolute_volume" msgid="2660673801947898809">"Vô hiệu hóa âm lượng tuyệt đối"</string>
+ <!-- no translation found for bluetooth_select_a2dp_codec_type (90597356942154882) -->
+ <skip />
+ <!-- no translation found for bluetooth_select_a2dp_codec_type_dialog_title (6470824182074383881) -->
+ <skip />
+ <!-- no translation found for bluetooth_select_a2dp_codec_sample_rate (4788245703824623062) -->
+ <skip />
+ <!-- no translation found for bluetooth_select_a2dp_codec_sample_rate_dialog_title (4263851572248033749) -->
+ <skip />
+ <!-- no translation found for bluetooth_select_a2dp_codec_bits_per_sample (2099645202720164141) -->
+ <skip />
+ <!-- no translation found for bluetooth_select_a2dp_codec_bits_per_sample_dialog_title (2096170505745650345) -->
+ <skip />
+ <!-- no translation found for bluetooth_select_a2dp_codec_channel_mode (884855779449390540) -->
+ <skip />
+ <!-- no translation found for bluetooth_select_a2dp_codec_channel_mode_dialog_title (4073812880900816325) -->
+ <skip />
+ <!-- no translation found for bluetooth_select_a2dp_codec_ldac_playback_quality (4846872213548295632) -->
+ <skip />
+ <!-- no translation found for bluetooth_select_a2dp_codec_ldac_playback_quality_dialog_title (3940973633342423717) -->
+ <skip />
<string name="wifi_display_certification_summary" msgid="1155182309166746973">"Hiển thị tùy chọn chứng nhận hiển thị không dây"</string>
<string name="wifi_verbose_logging_summary" msgid="6615071616111731958">"Tăng mức ghi nhật ký Wi‑Fi, hiển thị mỗi SSID RSSI trong bộ chọn Wi‑Fi"</string>
<string name="wifi_aggressive_handover_summary" msgid="6328455667642570371">"Khi được bật, Wi‑Fi sẽ tích cực hơn trong việc chuyển vùng kết nối dữ liệu sang mạng di động khi tín hiệu Wi‑Fi yếu"</string>
diff --git a/packages/SettingsLib/res/values-zh-rCN/arrays.xml b/packages/SettingsLib/res/values-zh-rCN/arrays.xml
index f449a94..10bd5a6 100644
--- a/packages/SettingsLib/res/values-zh-rCN/arrays.xml
+++ b/packages/SettingsLib/res/values-zh-rCN/arrays.xml
@@ -58,6 +58,46 @@
<item msgid="3878793616631049349">"仅使用 HDCP 检查 DRM 内容"</item>
<item msgid="45075631231212732">"始终使用 HDCP 检查"</item>
</string-array>
+ <!-- no translation found for bluetooth_a2dp_codec_titles:0 (1852387125374225729) -->
+ <!-- no translation found for bluetooth_a2dp_codec_titles:1 (7539690996561263909) -->
+ <!-- no translation found for bluetooth_a2dp_codec_titles:2 (4260844283202960798) -->
+ <!-- no translation found for bluetooth_a2dp_codec_titles:3 (7279983368484312990) -->
+ <!-- no translation found for bluetooth_a2dp_codec_titles:4 (2301339338870319651) -->
+ <!-- no translation found for bluetooth_a2dp_codec_summaries:0 (9072025520360316957) -->
+ <!-- no translation found for bluetooth_a2dp_codec_summaries:1 (6898329690939802290) -->
+ <!-- no translation found for bluetooth_a2dp_codec_summaries:2 (1190434429082395888) -->
+ <!-- no translation found for bluetooth_a2dp_codec_summaries:3 (649699003004233053) -->
+ <!-- no translation found for bluetooth_a2dp_codec_summaries:4 (508106435710925399) -->
+ <!-- no translation found for bluetooth_a2dp_codec_sample_rate_titles:0 (7102940318360468759) -->
+ <!-- no translation found for bluetooth_a2dp_codec_sample_rate_titles:1 (8895532488906185219) -->
+ <!-- no translation found for bluetooth_a2dp_codec_sample_rate_titles:2 (2909915718994807056) -->
+ <!-- no translation found for bluetooth_a2dp_codec_sample_rate_titles:3 (3347287377354164611) -->
+ <!-- no translation found for bluetooth_a2dp_codec_sample_rate_titles:4 (1234212100239985373) -->
+ <!-- no translation found for bluetooth_a2dp_codec_sample_rate_summaries:0 (7224433008148687313) -->
+ <!-- no translation found for bluetooth_a2dp_codec_sample_rate_summaries:1 (4482862757811638365) -->
+ <!-- no translation found for bluetooth_a2dp_codec_sample_rate_summaries:2 (354495328188724404) -->
+ <!-- no translation found for bluetooth_a2dp_codec_sample_rate_summaries:3 (7329816882213695083) -->
+ <!-- no translation found for bluetooth_a2dp_codec_sample_rate_summaries:4 (6967397666254430476) -->
+ <!-- no translation found for bluetooth_a2dp_codec_bits_per_sample_titles:0 (6694044160540313386) -->
+ <!-- no translation found for bluetooth_a2dp_codec_bits_per_sample_titles:1 (5618929009984956469) -->
+ <!-- no translation found for bluetooth_a2dp_codec_bits_per_sample_titles:2 (3412640499234627248) -->
+ <!-- no translation found for bluetooth_a2dp_codec_bits_per_sample_titles:3 (121583001492929387) -->
+ <!-- no translation found for bluetooth_a2dp_codec_bits_per_sample_summaries:0 (5091076677792306320) -->
+ <!-- no translation found for bluetooth_a2dp_codec_bits_per_sample_summaries:1 (4726688794884191540) -->
+ <!-- no translation found for bluetooth_a2dp_codec_bits_per_sample_summaries:2 (305344756485516870) -->
+ <!-- no translation found for bluetooth_a2dp_codec_bits_per_sample_summaries:3 (244568657919675099) -->
+ <!-- no translation found for bluetooth_a2dp_codec_channel_mode_titles:0 (13423709606339855) -->
+ <!-- no translation found for bluetooth_a2dp_codec_channel_mode_titles:1 (4106832974775067314) -->
+ <!-- no translation found for bluetooth_a2dp_codec_channel_mode_titles:2 (5571632958424639155) -->
+ <!-- no translation found for bluetooth_a2dp_codec_channel_mode_summaries:0 (8128478683963250130) -->
+ <!-- no translation found for bluetooth_a2dp_codec_channel_mode_summaries:1 (8900559293912978337) -->
+ <!-- no translation found for bluetooth_a2dp_codec_channel_mode_summaries:2 (8883739882299884241) -->
+ <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_titles:0 (2944889121850394020) -->
+ <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_titles:1 (138837449700903545) -->
+ <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_titles:2 (4777177307869441982) -->
+ <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_summaries:0 (172302906231378902) -->
+ <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_summaries:1 (9091111147684472529) -->
+ <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_summaries:2 (3367904477834831032) -->
<string-array name="select_logd_size_titles">
<item msgid="8665206199209698501">"关闭"</item>
<item msgid="1593289376502312923">"64K"</item>
diff --git a/packages/SettingsLib/res/values-zh-rCN/strings.xml b/packages/SettingsLib/res/values-zh-rCN/strings.xml
index 7c8bb20..975dc4f 100644
--- a/packages/SettingsLib/res/values-zh-rCN/strings.xml
+++ b/packages/SettingsLib/res/values-zh-rCN/strings.xml
@@ -170,6 +170,26 @@
<string name="wifi_allow_scan_with_traffic" msgid="3601853081178265786">"一律允许WLAN漫游扫描"</string>
<string name="mobile_data_always_on" msgid="7745605759775320362">"始终开启移动数据网络"</string>
<string name="bluetooth_disable_absolute_volume" msgid="2660673801947898809">"停用绝对音量功能"</string>
+ <!-- no translation found for bluetooth_select_a2dp_codec_type (90597356942154882) -->
+ <skip />
+ <!-- no translation found for bluetooth_select_a2dp_codec_type_dialog_title (6470824182074383881) -->
+ <skip />
+ <!-- no translation found for bluetooth_select_a2dp_codec_sample_rate (4788245703824623062) -->
+ <skip />
+ <!-- no translation found for bluetooth_select_a2dp_codec_sample_rate_dialog_title (4263851572248033749) -->
+ <skip />
+ <!-- no translation found for bluetooth_select_a2dp_codec_bits_per_sample (2099645202720164141) -->
+ <skip />
+ <!-- no translation found for bluetooth_select_a2dp_codec_bits_per_sample_dialog_title (2096170505745650345) -->
+ <skip />
+ <!-- no translation found for bluetooth_select_a2dp_codec_channel_mode (884855779449390540) -->
+ <skip />
+ <!-- no translation found for bluetooth_select_a2dp_codec_channel_mode_dialog_title (4073812880900816325) -->
+ <skip />
+ <!-- no translation found for bluetooth_select_a2dp_codec_ldac_playback_quality (4846872213548295632) -->
+ <skip />
+ <!-- no translation found for bluetooth_select_a2dp_codec_ldac_playback_quality_dialog_title (3940973633342423717) -->
+ <skip />
<string name="wifi_display_certification_summary" msgid="1155182309166746973">"显示无线显示认证选项"</string>
<string name="wifi_verbose_logging_summary" msgid="6615071616111731958">"提升WLAN日志记录级别(在WLAN选择器中显示每个SSID的RSSI)"</string>
<string name="wifi_aggressive_handover_summary" msgid="6328455667642570371">"开启此设置后,系统会在WLAN信号较弱时,主动将网络模式从WLAN网络切换到移动数据网络"</string>
diff --git a/packages/SettingsLib/res/values-zh-rHK/arrays.xml b/packages/SettingsLib/res/values-zh-rHK/arrays.xml
index 949bbce..bb64500 100644
--- a/packages/SettingsLib/res/values-zh-rHK/arrays.xml
+++ b/packages/SettingsLib/res/values-zh-rHK/arrays.xml
@@ -58,6 +58,46 @@
<item msgid="3878793616631049349">"僅使用 HDCP 檢查 DRM 內容"</item>
<item msgid="45075631231212732">"永遠使用 HDCP 檢查"</item>
</string-array>
+ <!-- no translation found for bluetooth_a2dp_codec_titles:0 (1852387125374225729) -->
+ <!-- no translation found for bluetooth_a2dp_codec_titles:1 (7539690996561263909) -->
+ <!-- no translation found for bluetooth_a2dp_codec_titles:2 (4260844283202960798) -->
+ <!-- no translation found for bluetooth_a2dp_codec_titles:3 (7279983368484312990) -->
+ <!-- no translation found for bluetooth_a2dp_codec_titles:4 (2301339338870319651) -->
+ <!-- no translation found for bluetooth_a2dp_codec_summaries:0 (9072025520360316957) -->
+ <!-- no translation found for bluetooth_a2dp_codec_summaries:1 (6898329690939802290) -->
+ <!-- no translation found for bluetooth_a2dp_codec_summaries:2 (1190434429082395888) -->
+ <!-- no translation found for bluetooth_a2dp_codec_summaries:3 (649699003004233053) -->
+ <!-- no translation found for bluetooth_a2dp_codec_summaries:4 (508106435710925399) -->
+ <!-- no translation found for bluetooth_a2dp_codec_sample_rate_titles:0 (7102940318360468759) -->
+ <!-- no translation found for bluetooth_a2dp_codec_sample_rate_titles:1 (8895532488906185219) -->
+ <!-- no translation found for bluetooth_a2dp_codec_sample_rate_titles:2 (2909915718994807056) -->
+ <!-- no translation found for bluetooth_a2dp_codec_sample_rate_titles:3 (3347287377354164611) -->
+ <!-- no translation found for bluetooth_a2dp_codec_sample_rate_titles:4 (1234212100239985373) -->
+ <!-- no translation found for bluetooth_a2dp_codec_sample_rate_summaries:0 (7224433008148687313) -->
+ <!-- no translation found for bluetooth_a2dp_codec_sample_rate_summaries:1 (4482862757811638365) -->
+ <!-- no translation found for bluetooth_a2dp_codec_sample_rate_summaries:2 (354495328188724404) -->
+ <!-- no translation found for bluetooth_a2dp_codec_sample_rate_summaries:3 (7329816882213695083) -->
+ <!-- no translation found for bluetooth_a2dp_codec_sample_rate_summaries:4 (6967397666254430476) -->
+ <!-- no translation found for bluetooth_a2dp_codec_bits_per_sample_titles:0 (6694044160540313386) -->
+ <!-- no translation found for bluetooth_a2dp_codec_bits_per_sample_titles:1 (5618929009984956469) -->
+ <!-- no translation found for bluetooth_a2dp_codec_bits_per_sample_titles:2 (3412640499234627248) -->
+ <!-- no translation found for bluetooth_a2dp_codec_bits_per_sample_titles:3 (121583001492929387) -->
+ <!-- no translation found for bluetooth_a2dp_codec_bits_per_sample_summaries:0 (5091076677792306320) -->
+ <!-- no translation found for bluetooth_a2dp_codec_bits_per_sample_summaries:1 (4726688794884191540) -->
+ <!-- no translation found for bluetooth_a2dp_codec_bits_per_sample_summaries:2 (305344756485516870) -->
+ <!-- no translation found for bluetooth_a2dp_codec_bits_per_sample_summaries:3 (244568657919675099) -->
+ <!-- no translation found for bluetooth_a2dp_codec_channel_mode_titles:0 (13423709606339855) -->
+ <!-- no translation found for bluetooth_a2dp_codec_channel_mode_titles:1 (4106832974775067314) -->
+ <!-- no translation found for bluetooth_a2dp_codec_channel_mode_titles:2 (5571632958424639155) -->
+ <!-- no translation found for bluetooth_a2dp_codec_channel_mode_summaries:0 (8128478683963250130) -->
+ <!-- no translation found for bluetooth_a2dp_codec_channel_mode_summaries:1 (8900559293912978337) -->
+ <!-- no translation found for bluetooth_a2dp_codec_channel_mode_summaries:2 (8883739882299884241) -->
+ <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_titles:0 (2944889121850394020) -->
+ <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_titles:1 (138837449700903545) -->
+ <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_titles:2 (4777177307869441982) -->
+ <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_summaries:0 (172302906231378902) -->
+ <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_summaries:1 (9091111147684472529) -->
+ <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_summaries:2 (3367904477834831032) -->
<string-array name="select_logd_size_titles">
<item msgid="8665206199209698501">"關閉"</item>
<item msgid="1593289376502312923">"64K"</item>
diff --git a/packages/SettingsLib/res/values-zh-rHK/strings.xml b/packages/SettingsLib/res/values-zh-rHK/strings.xml
index 62c7715..4dc9b1c 100644
--- a/packages/SettingsLib/res/values-zh-rHK/strings.xml
+++ b/packages/SettingsLib/res/values-zh-rHK/strings.xml
@@ -170,6 +170,26 @@
<string name="wifi_allow_scan_with_traffic" msgid="3601853081178265786">"永遠允許 Wi-Fi 漫遊掃瞄"</string>
<string name="mobile_data_always_on" msgid="7745605759775320362">"經常啟用流動數據"</string>
<string name="bluetooth_disable_absolute_volume" msgid="2660673801947898809">"停用絕對音量功能"</string>
+ <!-- no translation found for bluetooth_select_a2dp_codec_type (90597356942154882) -->
+ <skip />
+ <!-- no translation found for bluetooth_select_a2dp_codec_type_dialog_title (6470824182074383881) -->
+ <skip />
+ <!-- no translation found for bluetooth_select_a2dp_codec_sample_rate (4788245703824623062) -->
+ <skip />
+ <!-- no translation found for bluetooth_select_a2dp_codec_sample_rate_dialog_title (4263851572248033749) -->
+ <skip />
+ <!-- no translation found for bluetooth_select_a2dp_codec_bits_per_sample (2099645202720164141) -->
+ <skip />
+ <!-- no translation found for bluetooth_select_a2dp_codec_bits_per_sample_dialog_title (2096170505745650345) -->
+ <skip />
+ <!-- no translation found for bluetooth_select_a2dp_codec_channel_mode (884855779449390540) -->
+ <skip />
+ <!-- no translation found for bluetooth_select_a2dp_codec_channel_mode_dialog_title (4073812880900816325) -->
+ <skip />
+ <!-- no translation found for bluetooth_select_a2dp_codec_ldac_playback_quality (4846872213548295632) -->
+ <skip />
+ <!-- no translation found for bluetooth_select_a2dp_codec_ldac_playback_quality_dialog_title (3940973633342423717) -->
+ <skip />
<string name="wifi_display_certification_summary" msgid="1155182309166746973">"顯示無線螢幕分享認證的選項"</string>
<string name="wifi_verbose_logging_summary" msgid="6615071616111731958">"讓 Wi‑Fi 記錄功能升級,在 Wi‑Fi 選擇器中依每個 SSID RSSI 顯示 Wi‑Fi 詳細紀錄"</string>
<string name="wifi_aggressive_handover_summary" msgid="6328455667642570371">"啟用時,Wi-Fi 連線會在訊號不穩的情況下更積極轉換成流動數據連線"</string>
diff --git a/packages/SettingsLib/res/values-zh-rTW/arrays.xml b/packages/SettingsLib/res/values-zh-rTW/arrays.xml
index 766bc95..eafaf3f 100644
--- a/packages/SettingsLib/res/values-zh-rTW/arrays.xml
+++ b/packages/SettingsLib/res/values-zh-rTW/arrays.xml
@@ -58,6 +58,46 @@
<item msgid="3878793616631049349">"僅使用 HDCP 檢查 DRM 內容"</item>
<item msgid="45075631231212732">"一律使用 HDCP 檢查"</item>
</string-array>
+ <!-- no translation found for bluetooth_a2dp_codec_titles:0 (1852387125374225729) -->
+ <!-- no translation found for bluetooth_a2dp_codec_titles:1 (7539690996561263909) -->
+ <!-- no translation found for bluetooth_a2dp_codec_titles:2 (4260844283202960798) -->
+ <!-- no translation found for bluetooth_a2dp_codec_titles:3 (7279983368484312990) -->
+ <!-- no translation found for bluetooth_a2dp_codec_titles:4 (2301339338870319651) -->
+ <!-- no translation found for bluetooth_a2dp_codec_summaries:0 (9072025520360316957) -->
+ <!-- no translation found for bluetooth_a2dp_codec_summaries:1 (6898329690939802290) -->
+ <!-- no translation found for bluetooth_a2dp_codec_summaries:2 (1190434429082395888) -->
+ <!-- no translation found for bluetooth_a2dp_codec_summaries:3 (649699003004233053) -->
+ <!-- no translation found for bluetooth_a2dp_codec_summaries:4 (508106435710925399) -->
+ <!-- no translation found for bluetooth_a2dp_codec_sample_rate_titles:0 (7102940318360468759) -->
+ <!-- no translation found for bluetooth_a2dp_codec_sample_rate_titles:1 (8895532488906185219) -->
+ <!-- no translation found for bluetooth_a2dp_codec_sample_rate_titles:2 (2909915718994807056) -->
+ <!-- no translation found for bluetooth_a2dp_codec_sample_rate_titles:3 (3347287377354164611) -->
+ <!-- no translation found for bluetooth_a2dp_codec_sample_rate_titles:4 (1234212100239985373) -->
+ <!-- no translation found for bluetooth_a2dp_codec_sample_rate_summaries:0 (7224433008148687313) -->
+ <!-- no translation found for bluetooth_a2dp_codec_sample_rate_summaries:1 (4482862757811638365) -->
+ <!-- no translation found for bluetooth_a2dp_codec_sample_rate_summaries:2 (354495328188724404) -->
+ <!-- no translation found for bluetooth_a2dp_codec_sample_rate_summaries:3 (7329816882213695083) -->
+ <!-- no translation found for bluetooth_a2dp_codec_sample_rate_summaries:4 (6967397666254430476) -->
+ <!-- no translation found for bluetooth_a2dp_codec_bits_per_sample_titles:0 (6694044160540313386) -->
+ <!-- no translation found for bluetooth_a2dp_codec_bits_per_sample_titles:1 (5618929009984956469) -->
+ <!-- no translation found for bluetooth_a2dp_codec_bits_per_sample_titles:2 (3412640499234627248) -->
+ <!-- no translation found for bluetooth_a2dp_codec_bits_per_sample_titles:3 (121583001492929387) -->
+ <!-- no translation found for bluetooth_a2dp_codec_bits_per_sample_summaries:0 (5091076677792306320) -->
+ <!-- no translation found for bluetooth_a2dp_codec_bits_per_sample_summaries:1 (4726688794884191540) -->
+ <!-- no translation found for bluetooth_a2dp_codec_bits_per_sample_summaries:2 (305344756485516870) -->
+ <!-- no translation found for bluetooth_a2dp_codec_bits_per_sample_summaries:3 (244568657919675099) -->
+ <!-- no translation found for bluetooth_a2dp_codec_channel_mode_titles:0 (13423709606339855) -->
+ <!-- no translation found for bluetooth_a2dp_codec_channel_mode_titles:1 (4106832974775067314) -->
+ <!-- no translation found for bluetooth_a2dp_codec_channel_mode_titles:2 (5571632958424639155) -->
+ <!-- no translation found for bluetooth_a2dp_codec_channel_mode_summaries:0 (8128478683963250130) -->
+ <!-- no translation found for bluetooth_a2dp_codec_channel_mode_summaries:1 (8900559293912978337) -->
+ <!-- no translation found for bluetooth_a2dp_codec_channel_mode_summaries:2 (8883739882299884241) -->
+ <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_titles:0 (2944889121850394020) -->
+ <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_titles:1 (138837449700903545) -->
+ <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_titles:2 (4777177307869441982) -->
+ <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_summaries:0 (172302906231378902) -->
+ <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_summaries:1 (9091111147684472529) -->
+ <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_summaries:2 (3367904477834831032) -->
<string-array name="select_logd_size_titles">
<item msgid="8665206199209698501">"關閉"</item>
<item msgid="1593289376502312923">"64K"</item>
diff --git a/packages/SettingsLib/res/values-zh-rTW/strings.xml b/packages/SettingsLib/res/values-zh-rTW/strings.xml
index 17a62e1..cf7b011 100644
--- a/packages/SettingsLib/res/values-zh-rTW/strings.xml
+++ b/packages/SettingsLib/res/values-zh-rTW/strings.xml
@@ -170,6 +170,26 @@
<string name="wifi_allow_scan_with_traffic" msgid="3601853081178265786">"一律允許 Wi-Fi 漫遊掃描"</string>
<string name="mobile_data_always_on" msgid="7745605759775320362">"行動數據連線一律保持啟用狀態"</string>
<string name="bluetooth_disable_absolute_volume" msgid="2660673801947898809">"停用絕對音量功能"</string>
+ <!-- no translation found for bluetooth_select_a2dp_codec_type (90597356942154882) -->
+ <skip />
+ <!-- no translation found for bluetooth_select_a2dp_codec_type_dialog_title (6470824182074383881) -->
+ <skip />
+ <!-- no translation found for bluetooth_select_a2dp_codec_sample_rate (4788245703824623062) -->
+ <skip />
+ <!-- no translation found for bluetooth_select_a2dp_codec_sample_rate_dialog_title (4263851572248033749) -->
+ <skip />
+ <!-- no translation found for bluetooth_select_a2dp_codec_bits_per_sample (2099645202720164141) -->
+ <skip />
+ <!-- no translation found for bluetooth_select_a2dp_codec_bits_per_sample_dialog_title (2096170505745650345) -->
+ <skip />
+ <!-- no translation found for bluetooth_select_a2dp_codec_channel_mode (884855779449390540) -->
+ <skip />
+ <!-- no translation found for bluetooth_select_a2dp_codec_channel_mode_dialog_title (4073812880900816325) -->
+ <skip />
+ <!-- no translation found for bluetooth_select_a2dp_codec_ldac_playback_quality (4846872213548295632) -->
+ <skip />
+ <!-- no translation found for bluetooth_select_a2dp_codec_ldac_playback_quality_dialog_title (3940973633342423717) -->
+ <skip />
<string name="wifi_display_certification_summary" msgid="1155182309166746973">"顯示無線螢幕分享認證的選項"</string>
<string name="wifi_verbose_logging_summary" msgid="6615071616111731958">"讓 Wi‑Fi 記錄功能升級,在 Wi‑Fi 選擇器中依每個 SSID RSSI 顯示 Wi‑Fi 詳細紀錄"</string>
<string name="wifi_aggressive_handover_summary" msgid="6328455667642570371">"啟用時,Wi-Fi 連線在訊號不穩的情況下會更積極轉換成行動數據連線"</string>
diff --git a/packages/SettingsLib/res/values-zu/arrays.xml b/packages/SettingsLib/res/values-zu/arrays.xml
index a2b176c..deb801f 100644
--- a/packages/SettingsLib/res/values-zu/arrays.xml
+++ b/packages/SettingsLib/res/values-zu/arrays.xml
@@ -58,6 +58,46 @@
<item msgid="3878793616631049349">"Sebenzisa ukuhlola kwe-HDCP kokuqukethwe i-DRM kuphela"</item>
<item msgid="45075631231212732">"Sebenzisa njalo ukuhlola kwe-HDPC"</item>
</string-array>
+ <!-- no translation found for bluetooth_a2dp_codec_titles:0 (1852387125374225729) -->
+ <!-- no translation found for bluetooth_a2dp_codec_titles:1 (7539690996561263909) -->
+ <!-- no translation found for bluetooth_a2dp_codec_titles:2 (4260844283202960798) -->
+ <!-- no translation found for bluetooth_a2dp_codec_titles:3 (7279983368484312990) -->
+ <!-- no translation found for bluetooth_a2dp_codec_titles:4 (2301339338870319651) -->
+ <!-- no translation found for bluetooth_a2dp_codec_summaries:0 (9072025520360316957) -->
+ <!-- no translation found for bluetooth_a2dp_codec_summaries:1 (6898329690939802290) -->
+ <!-- no translation found for bluetooth_a2dp_codec_summaries:2 (1190434429082395888) -->
+ <!-- no translation found for bluetooth_a2dp_codec_summaries:3 (649699003004233053) -->
+ <!-- no translation found for bluetooth_a2dp_codec_summaries:4 (508106435710925399) -->
+ <!-- no translation found for bluetooth_a2dp_codec_sample_rate_titles:0 (7102940318360468759) -->
+ <!-- no translation found for bluetooth_a2dp_codec_sample_rate_titles:1 (8895532488906185219) -->
+ <!-- no translation found for bluetooth_a2dp_codec_sample_rate_titles:2 (2909915718994807056) -->
+ <!-- no translation found for bluetooth_a2dp_codec_sample_rate_titles:3 (3347287377354164611) -->
+ <!-- no translation found for bluetooth_a2dp_codec_sample_rate_titles:4 (1234212100239985373) -->
+ <!-- no translation found for bluetooth_a2dp_codec_sample_rate_summaries:0 (7224433008148687313) -->
+ <!-- no translation found for bluetooth_a2dp_codec_sample_rate_summaries:1 (4482862757811638365) -->
+ <!-- no translation found for bluetooth_a2dp_codec_sample_rate_summaries:2 (354495328188724404) -->
+ <!-- no translation found for bluetooth_a2dp_codec_sample_rate_summaries:3 (7329816882213695083) -->
+ <!-- no translation found for bluetooth_a2dp_codec_sample_rate_summaries:4 (6967397666254430476) -->
+ <!-- no translation found for bluetooth_a2dp_codec_bits_per_sample_titles:0 (6694044160540313386) -->
+ <!-- no translation found for bluetooth_a2dp_codec_bits_per_sample_titles:1 (5618929009984956469) -->
+ <!-- no translation found for bluetooth_a2dp_codec_bits_per_sample_titles:2 (3412640499234627248) -->
+ <!-- no translation found for bluetooth_a2dp_codec_bits_per_sample_titles:3 (121583001492929387) -->
+ <!-- no translation found for bluetooth_a2dp_codec_bits_per_sample_summaries:0 (5091076677792306320) -->
+ <!-- no translation found for bluetooth_a2dp_codec_bits_per_sample_summaries:1 (4726688794884191540) -->
+ <!-- no translation found for bluetooth_a2dp_codec_bits_per_sample_summaries:2 (305344756485516870) -->
+ <!-- no translation found for bluetooth_a2dp_codec_bits_per_sample_summaries:3 (244568657919675099) -->
+ <!-- no translation found for bluetooth_a2dp_codec_channel_mode_titles:0 (13423709606339855) -->
+ <!-- no translation found for bluetooth_a2dp_codec_channel_mode_titles:1 (4106832974775067314) -->
+ <!-- no translation found for bluetooth_a2dp_codec_channel_mode_titles:2 (5571632958424639155) -->
+ <!-- no translation found for bluetooth_a2dp_codec_channel_mode_summaries:0 (8128478683963250130) -->
+ <!-- no translation found for bluetooth_a2dp_codec_channel_mode_summaries:1 (8900559293912978337) -->
+ <!-- no translation found for bluetooth_a2dp_codec_channel_mode_summaries:2 (8883739882299884241) -->
+ <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_titles:0 (2944889121850394020) -->
+ <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_titles:1 (138837449700903545) -->
+ <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_titles:2 (4777177307869441982) -->
+ <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_summaries:0 (172302906231378902) -->
+ <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_summaries:1 (9091111147684472529) -->
+ <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_summaries:2 (3367904477834831032) -->
<string-array name="select_logd_size_titles">
<item msgid="8665206199209698501">"Valiwe"</item>
<item msgid="1593289376502312923">"64K"</item>
diff --git a/packages/SettingsLib/res/values-zu/strings.xml b/packages/SettingsLib/res/values-zu/strings.xml
index 7e982ee..30fab23 100644
--- a/packages/SettingsLib/res/values-zu/strings.xml
+++ b/packages/SettingsLib/res/values-zu/strings.xml
@@ -170,6 +170,26 @@
<string name="wifi_allow_scan_with_traffic" msgid="3601853081178265786">"Vumela njalo ukuskena kokuzula kwe-Wi-Fi"</string>
<string name="mobile_data_always_on" msgid="7745605759775320362">"Idatha yeselula ihlala isebenza"</string>
<string name="bluetooth_disable_absolute_volume" msgid="2660673801947898809">"Khubaza ivolumu ngokuphelele"</string>
+ <!-- no translation found for bluetooth_select_a2dp_codec_type (90597356942154882) -->
+ <skip />
+ <!-- no translation found for bluetooth_select_a2dp_codec_type_dialog_title (6470824182074383881) -->
+ <skip />
+ <!-- no translation found for bluetooth_select_a2dp_codec_sample_rate (4788245703824623062) -->
+ <skip />
+ <!-- no translation found for bluetooth_select_a2dp_codec_sample_rate_dialog_title (4263851572248033749) -->
+ <skip />
+ <!-- no translation found for bluetooth_select_a2dp_codec_bits_per_sample (2099645202720164141) -->
+ <skip />
+ <!-- no translation found for bluetooth_select_a2dp_codec_bits_per_sample_dialog_title (2096170505745650345) -->
+ <skip />
+ <!-- no translation found for bluetooth_select_a2dp_codec_channel_mode (884855779449390540) -->
+ <skip />
+ <!-- no translation found for bluetooth_select_a2dp_codec_channel_mode_dialog_title (4073812880900816325) -->
+ <skip />
+ <!-- no translation found for bluetooth_select_a2dp_codec_ldac_playback_quality (4846872213548295632) -->
+ <skip />
+ <!-- no translation found for bluetooth_select_a2dp_codec_ldac_playback_quality_dialog_title (3940973633342423717) -->
+ <skip />
<string name="wifi_display_certification_summary" msgid="1155182309166746973">"Bonisa izinketho zokunikeza isitifiketi ukubukeka okungenantambo"</string>
<string name="wifi_verbose_logging_summary" msgid="6615071616111731958">"khuphula izinga lokungena le-Wi-Fi, bonisa nge-SSID RSSI engayodwana kusikhethi se-Wi-Fi"</string>
<string name="wifi_aggressive_handover_summary" msgid="6328455667642570371">"Uma inikwe amandla, i-Wi-Fi izoba namandla kakhulu ekunikezeleni ukuxhumeka kwedatha kuselula, uma isiginali ye-Wi-Fi iphansi"</string>
diff --git a/packages/SettingsLib/res/values/arrays.xml b/packages/SettingsLib/res/values/arrays.xml
index 362cf44..5c00985 100644
--- a/packages/SettingsLib/res/values/arrays.xml
+++ b/packages/SettingsLib/res/values/arrays.xml
@@ -100,6 +100,129 @@
<item>Always use HDCP checking</item>
</string-array>
+
+ <!-- Bluetooth settings -->
+
+ <!-- Titles for Bluetooth Audio Codec selection preference. [CHAR LIMIT=40] -->
+ <string-array name="bluetooth_a2dp_codec_titles">
+ <item>Default</item>
+ <item>SBC</item>
+ <item>aptX</item>
+ <item>aptX-HD</item>
+ <item>LDAC</item>
+ </string-array>
+
+ <!-- Values for Bluetooth Audio Codec selection preference. -->
+ <string-array name="bluetooth_a2dp_codec_values" translatable="false" >
+ <item>1000000</item>
+ <item>0</item>
+ <item>1</item>
+ <item>2</item>
+ <item>3</item>
+ </string-array>
+
+ <!-- Summaries for Bluetooth Audio Codec selection preference. [CHAR LIMIT=40]-->
+ <string-array name="bluetooth_a2dp_codec_summaries" >
+ <item>Default</item>
+ <item>SBC</item>
+ <item>aptX</item>
+ <item>aptX-HD</item>
+ <item>LDAC</item>
+ </string-array>
+
+ <!-- Titles for Bluetooth Audio Codec Sample Rate selection preference. [CHAR LIMIT=40] -->
+ <string-array name="bluetooth_a2dp_codec_sample_rate_titles">
+ <item>Default</item>
+ <item>44.1 kHz</item>
+ <item>48.0 kHz</item>
+ <item>88.2 kHz</item>
+ <item>96.0 kHz</item>
+ </string-array>
+
+ <!-- Values for Bluetooth Audio Codec Sample Rate selection preference. -->
+ <string-array name="bluetooth_a2dp_codec_sample_rate_values" translatable="false" >
+ <item>0</item>
+ <item>1</item>
+ <item>2</item>
+ <item>4</item>
+ <item>8</item>
+ </string-array>
+
+ <!-- Summaries for Bluetooth Audio Codec Sample Rate selection preference. [CHAR LIMIT=40]-->
+ <string-array name="bluetooth_a2dp_codec_sample_rate_summaries" >
+ <item>Default</item>
+ <item>44.1 kHz</item>
+ <item>48.0 kHz</item>
+ <item>88.2 kHz</item>
+ <item>96.0 kHz</item>
+ </string-array>
+
+ <!-- Titles for Bluetooth Audio Codec Bits Per Sample selection preference. [CHAR LIMIT=40] -->
+ <string-array name="bluetooth_a2dp_codec_bits_per_sample_titles">
+ <item>Default</item>
+ <item>16 bits/sample</item>
+ <item>24 bits/sample</item>
+ <item>32 bits/sample</item>
+ </string-array>
+
+ <!-- Values for Bluetooth Audio Codec Bits Per Sample selection preference. -->
+ <string-array name="bluetooth_a2dp_codec_bits_per_sample_values" translatable="false" >
+ <item>0</item>
+ <item>1</item>
+ <item>2</item>
+ <item>4</item>
+ </string-array>
+
+ <!-- Summaries for Bluetooth Audio Codec Bits Per Sample selection preference. [CHAR LIMIT=40]-->
+ <string-array name="bluetooth_a2dp_codec_bits_per_sample_summaries" >
+ <item>Default</item>
+ <item>16 bits/sample</item>
+ <item>24 bits/sample</item>
+ <item>32 bits/sample</item>
+ </string-array>
+
+ <!-- Titles for Bluetooth Audio Codec Channel Mode selection preference. [CHAR LIMIT=40] -->
+ <string-array name="bluetooth_a2dp_codec_channel_mode_titles">
+ <item>Default</item>
+ <item>Mono</item>
+ <item>Stereo</item>
+ </string-array>
+
+ <!-- Values for Bluetooth Audio Codec Channel Mode selection preference. -->
+ <string-array name="bluetooth_a2dp_codec_channel_mode_values" translatable="false" >
+ <item>0</item>
+ <item>1</item>
+ <item>2</item>
+ </string-array>
+
+ <!-- Summaries for Bluetooth Audio Codec Channel Mode selection preference. [CHAR LIMIT=40]-->
+ <string-array name="bluetooth_a2dp_codec_channel_mode_summaries" >
+ <item>Default</item>
+ <item>Mono</item>
+ <item>Stereo</item>
+ </string-array>
+
+ <!-- Titles for Bluetooth Audio Codec LDAC Playback Quality selection preference. [CHAR LIMIT=40] -->
+ <string-array name="bluetooth_a2dp_codec_ldac_playback_quality_titles">
+ <item>Sound quality preferred (990kbps/909kbps)</item>
+ <item>Standard (660kbps/606kbps)</item>
+ <item>Connection preferred (330kbps/303kbps)</item>
+ </string-array>
+
+ <!-- Values for Bluetooth Audio Codec LDAC Playback Quaility selection preference. -->
+ <string-array name="bluetooth_a2dp_codec_ldac_playback_quality_values" translatable="false" >
+ <item>1000</item>
+ <item>1001</item>
+ <item>1002</item>
+ </string-array>
+
+ <!-- Summaries for Bluetooth Audio Codec LDAC Playback Quality selection preference. [CHAR LIMIT=40]-->
+ <string-array name="bluetooth_a2dp_codec_ldac_playback_quality_summaries" >
+ <item>Sound quality preferred (990kbps/909kbps)</item>
+ <item>Standard (660kbps/606kbps)</item>
+ <item>Connection preferred (330kbps/303kbps)</item>
+ </string-array>
+
<!-- Titles for logd limit size selection preference. [CHAR LIMIT=14] -->
<string-array name="select_logd_size_titles">
<item>Off</item>
diff --git a/packages/SettingsLib/res/values/config.xml b/packages/SettingsLib/res/values/config.xml
index 64f21b5..ee69b56 100755
--- a/packages/SettingsLib/res/values/config.xml
+++ b/packages/SettingsLib/res/values/config.xml
@@ -26,6 +26,9 @@
<!-- Whether to send a custom package name with the PSD.-->
<bool name="config_sendPackageName">false</bool>
+ <!-- Whether to enable the left nav drawer in all Settings UI.-->
+ <bool name="config_enable_nav_drawer">false</bool>
+
<!-- Name for the set of keys associating package names -->
<string name="config_helpPackageNameKey" translatable="false"></string>
diff --git a/packages/SettingsLib/res/values/dimens.xml b/packages/SettingsLib/res/values/dimens.xml
index c3b3cfc..2e8b30f 100644
--- a/packages/SettingsLib/res/values/dimens.xml
+++ b/packages/SettingsLib/res/values/dimens.xml
@@ -51,5 +51,10 @@
<dimen name="usage_graph_dot_size">.75dp</dimen>
<dimen name="usage_graph_dot_interval">7dp</dimen>
-
+ <dimen name="drawer_icon_size">24dp</dimen>
+ <dimen name="normal_icon_size">24dp</dimen>
+ <dimen name="drawer_icon_margin">24dp</dimen>
+ <dimen name="drawer_width">300dp</dimen>
+ <dimen name="drawer_item_top_bottom_margin">4dp</dimen>
+ <dimen name="drawer_spacer_height">32dp</dimen>
</resources>
diff --git a/packages/SettingsLib/res/values/strings.xml b/packages/SettingsLib/res/values/strings.xml
index f176aac..93bd5dc 100644
--- a/packages/SettingsLib/res/values/strings.xml
+++ b/packages/SettingsLib/res/values/strings.xml
@@ -428,6 +428,31 @@
<!-- Setting Checkbox title for disabling Bluetooth absolute volume -->
<string name="bluetooth_disable_absolute_volume">Disable absolute volume</string>
+ <!-- UI debug setting: Select Bluetooth Audio Codec -->
+ <string name="bluetooth_select_a2dp_codec_type">Bluetooth Audio Codec</string>
+ <!-- UI debug setting: Select Preferred Bluetooth A2DP Codec -->
+ <string name="bluetooth_select_a2dp_codec_type_dialog_title">Select Preferred Bluetooth A2DP Codec</string>
+
+ <!-- UI debug setting: Select Bluetooth Audio Sample Rate -->
+ <string name="bluetooth_select_a2dp_codec_sample_rate">Bluetooth Audio Sample Rate</string>
+ <!-- UI debug setting: Select Preferred Bluetooth A2DP Codec Sample Rate -->
+ <string name="bluetooth_select_a2dp_codec_sample_rate_dialog_title">Select Preferred Bluetooth A2DP Codec Sample Rate</string>
+
+ <!-- UI debug setting: Select Bluetooth Audio Bits Per Sample -->
+ <string name="bluetooth_select_a2dp_codec_bits_per_sample">Bluetooth Audio Bits Per Sample</string>
+ <!-- UI debug setting: Select Preferred Bluetooth A2DP Codec Bits Per Sample -->
+ <string name="bluetooth_select_a2dp_codec_bits_per_sample_dialog_title">Select Preferred Bluetooth A2DP Codec Bits Per Sample</string>
+
+ <!-- UI debug setting: Select Bluetooth Audio Channel Mode -->
+ <string name="bluetooth_select_a2dp_codec_channel_mode">Bluetooth Audio Channel Mode</string>
+ <!-- UI debug setting: Select Preferred Bluetooth A2DP Codec Channel Mode -->
+ <string name="bluetooth_select_a2dp_codec_channel_mode_dialog_title">Select Preferred Bluetooth A2DP Codec Channel Mode</string>
+
+ <!-- UI debug setting: Select Bluetooth Audio LDAC Playback Quality -->
+ <string name="bluetooth_select_a2dp_codec_ldac_playback_quality">Bluetooth Audio LDAC Playback Quality</string>
+ <!-- UI debug setting: Select Preferred Bluetooth A2DP Codec LDAC Playback Quality -->
+ <string name="bluetooth_select_a2dp_codec_ldac_playback_quality_dialog_title">Select Preferred Bluetooth A2DP Codec LDAC Playback Quality</string>
+
<!-- setting Checkbox summary whether to show options for wireless display certification -->
<string name="wifi_display_certification_summary">Show options for wireless display certification</string>
<!-- Setting Checkbox summary whether to enable Wifi verbose Logging [CHAR LIMIT=80] -->
diff --git a/packages/SettingsLib/res/values/styles.xml b/packages/SettingsLib/res/values/styles.xml
new file mode 100644
index 0000000..3f312f4
--- /dev/null
+++ b/packages/SettingsLib/res/values/styles.xml
@@ -0,0 +1,24 @@
+<!--
+ ~ Copyright (C) 2016 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>
+ <style name="TextAppearanceSmall">
+ <item name="android:textAppearance">?android:attr/textAppearanceSmall</item>
+ </style>
+ <style name="TextAppearanceMedium">
+ <item name="android:textAppearance">?android:attr/textAppearanceMedium</item>
+ </style>
+</resources>
diff --git a/packages/SettingsLib/src/com/android/settingslib/Utils.java b/packages/SettingsLib/src/com/android/settingslib/Utils.java
index e049079..6179244 100644
--- a/packages/SettingsLib/src/com/android/settingslib/Utils.java
+++ b/packages/SettingsLib/src/com/android/settingslib/Utils.java
@@ -8,6 +8,7 @@
import android.content.pm.PackageManager.NameNotFoundException;
import android.content.pm.UserInfo;
import android.content.pm.Signature;
+import android.content.res.ColorStateList;
import android.content.res.Resources;
import android.content.res.TypedArray;
import android.graphics.Bitmap;
@@ -165,6 +166,22 @@
return colorAccent;
}
+ @ColorInt
+ public static int getColorError(Context context) {
+ TypedArray ta = context.obtainStyledAttributes(new int[]{android.R.attr.textColorError});
+ @ColorInt int colorError = ta.getColor(0, 0);
+ ta.recycle();
+ return colorError;
+ }
+
+ @ColorInt
+ public static int getDefaultColor(Context context, int resId) {
+ final ColorStateList list =
+ context.getResources().getColorStateList(resId, context.getTheme());
+
+ return list.getDefaultColor();
+ }
+
/**
* Determine whether a package is a "system package", in which case certain things (like
* disabling notifications or disabling the package altogether) should be disallowed.
diff --git a/packages/SettingsLib/src/com/android/settingslib/drawer/CategoryManager.java b/packages/SettingsLib/src/com/android/settingslib/drawer/CategoryManager.java
index 6ccba92..fa5ba73 100644
--- a/packages/SettingsLib/src/com/android/settingslib/drawer/CategoryManager.java
+++ b/packages/SettingsLib/src/com/android/settingslib/drawer/CategoryManager.java
@@ -72,21 +72,30 @@
}
public synchronized DashboardCategory getTilesByCategory(Context context, String categoryKey) {
- tryInitCategories(context);
+ return getTilesByCategory(context, categoryKey, TileUtils.SETTING_PKG);
+ }
+
+ public synchronized DashboardCategory getTilesByCategory(Context context, String categoryKey,
+ String settingPkg) {
+ tryInitCategories(context, settingPkg);
return mCategoryByKeyMap.get(categoryKey);
}
public synchronized List<DashboardCategory> getCategories(Context context) {
- tryInitCategories(context);
+ return getCategories(context, TileUtils.SETTING_PKG);
+ }
+
+ public synchronized List<DashboardCategory> getCategories(Context context, String settingPkg) {
+ tryInitCategories(context, settingPkg);
return mCategories;
}
- public synchronized void reloadAllCategories(Context context) {
+ public synchronized void reloadAllCategories(Context context, String settingPkg) {
final boolean forceClearCache = mInterestingConfigChanges.applyNewConfig(
context.getResources());
mCategories = null;
- tryInitCategories(context, forceClearCache);
+ tryInitCategories(context, forceClearCache, settingPkg);
}
public synchronized void updateCategoryFromBlacklist(Set<ComponentName> tileBlacklist) {
@@ -104,20 +113,21 @@
}
}
- private synchronized void tryInitCategories(Context context) {
+ private synchronized void tryInitCategories(Context context, String settingPkg) {
// Keep cached tiles by default. The cache is only invalidated when InterestingConfigChange
// happens.
- tryInitCategories(context, false /* forceClearCache */);
+ tryInitCategories(context, false /* forceClearCache */, settingPkg);
}
- private synchronized void tryInitCategories(Context context, boolean forceClearCache) {
+ private synchronized void tryInitCategories(Context context, boolean forceClearCache,
+ String settingPkg) {
if (mCategories == null) {
if (forceClearCache) {
mTileByComponentCache.clear();
}
mCategoryByKeyMap.clear();
mCategories = TileUtils.getCategories(context, mTileByComponentCache,
- false /* categoryDefinedInManifest */, mExtraAction);
+ false /* categoryDefinedInManifest */, mExtraAction, settingPkg);
for (DashboardCategory category : mCategories) {
mCategoryByKeyMap.put(category.key, category);
}
diff --git a/packages/SettingsLib/src/com/android/settingslib/drawer/SettingsDrawerActivity.java b/packages/SettingsLib/src/com/android/settingslib/drawer/SettingsDrawerActivity.java
index 86514dc..6010621 100644
--- a/packages/SettingsLib/src/com/android/settingslib/drawer/SettingsDrawerActivity.java
+++ b/packages/SettingsLib/src/com/android/settingslib/drawer/SettingsDrawerActivity.java
@@ -28,7 +28,6 @@
import android.content.res.TypedArray;
import android.os.AsyncTask;
import android.os.Bundle;
-import android.os.UserManager;
import android.provider.Settings;
import android.support.v4.widget.DrawerLayout;
import android.util.ArraySet;
@@ -72,7 +71,6 @@
private FrameLayout mContentHeaderContainer;
private DrawerLayout mDrawerLayout;
private boolean mShowingMenu;
- private UserManager mUserManager;
// Remove below after new IA
@Deprecated
@@ -92,7 +90,6 @@
TypedArray theme = getTheme().obtainStyledAttributes(android.R.styleable.Theme);
if (!theme.getBoolean(android.R.styleable.Theme_windowNoTitle, false)) {
getWindow().addFlags(LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS);
- getWindow().addFlags(LayoutParams.FLAG_TRANSLUCENT_STATUS);
requestWindowFeature(Window.FEATURE_NO_TITLE);
}
super.setContentView(R.layout.settings_with_drawer);
@@ -108,6 +105,9 @@
mDrawerLayout = null;
return;
}
+ if (!isNavDrawerEnabled()) {
+ setIsDrawerPresent(false);
+ }
if (!isDashboardFeatureEnabled()) {
getDashboardCategories();
}
@@ -122,7 +122,6 @@
}
});
- mUserManager = UserManager.get(this);
if (DEBUG_TIMING) Log.d(TAG, "onCreate took " + (System.currentTimeMillis() - startTime)
+ " ms");
}
@@ -138,6 +137,15 @@
}
@Override
+ public boolean onNavigateUp() {
+ if (!isNavDrawerEnabled()) {
+ finish();
+ return true;
+ }
+ return super.onNavigateUp();
+ }
+
+ @Override
protected void onResume() {
super.onResume();
@@ -162,7 +170,7 @@
// Intent explicitly set to show menu.
showMenuIcon();
}
- } else if (isTopLevelTile(intent)) {
+ } else if (isNavDrawerEnabled() && isTopLevelTile(intent)) {
showMenuIcon();
}
}
@@ -184,8 +192,9 @@
}
if (isDashboardFeatureEnabled()) {
final DashboardCategory homepageCategories = CategoryManager.get(this)
- .getTilesByCategory(this, CategoryKey.CATEGORY_HOMEPAGE);
- return homepageCategories.containsComponent(componentName);
+ .getTilesByCategory(this, CategoryKey.CATEGORY_HOMEPAGE, getSettingPkg());
+ return homepageCategories ==
+ null ? false : homepageCategories.containsComponent(componentName);
} else {
// Look for a tile that has the same component as incoming intent
final List<DashboardCategory> categories = getDashboardCategories();
@@ -201,6 +210,14 @@
}
}
+ /**
+ * Gets the name of the intent action of the default setting app. Used to launch setting app
+ * when Settings Home is clicked.
+ */
+ public String getSettingAction() {
+ return Settings.ACTION_SETTINGS;
+ }
+
public void addCategoryListener(CategoryListener listener) {
mCategoryListeners.add(listener);
}
@@ -265,7 +282,7 @@
}
// TODO: Do this in the background with some loading.
if (isDashboardFeatureEnabled()) {
- mDrawerAdapter.updateHomepageCategories();
+ mDrawerAdapter.updateHomepageCategories(getSettingPkg());
} else {
mDrawerAdapter.updateCategories();
}
@@ -277,10 +294,13 @@
}
public void showMenuIcon() {
- mShowingMenu = true;
- getActionBar().setHomeAsUpIndicator(R.drawable.ic_menu);
- getActionBar().setHomeActionContentDescription(R.string.content_description_menu_button);
getActionBar().setDisplayHomeAsUpEnabled(true);
+ if (isNavDrawerEnabled()) {
+ mShowingMenu = true;
+ getActionBar().setHomeAsUpIndicator(R.drawable.ic_menu);
+ getActionBar().setHomeActionContentDescription(
+ R.string.content_description_menu_button);
+ }
}
public List<DashboardCategory> getDashboardCategories() {
@@ -305,8 +325,9 @@
public boolean openTile(Tile tile) {
closeDrawer();
if (tile == null) {
- startActivity(new Intent(Settings.ACTION_SETTINGS).addFlags(
- Intent.FLAG_ACTIVITY_CLEAR_TASK));
+ Intent intent = new Intent(getSettingAction()).addFlags(
+ Intent.FLAG_ACTIVITY_CLEAR_TASK);
+ startActivity(intent);
return true;
}
try {
@@ -356,14 +377,24 @@
? PackageManager.COMPONENT_ENABLED_STATE_ENABLED
: PackageManager.COMPONENT_ENABLED_STATE_DISABLED,
PackageManager.DONT_KILL_APP);
- if (isDashboardFeatureEnabled()) {
- new CategoriesUpdateTask().execute();
- } else {
- new CategoriesUpdater().execute();
- }
}
}
+ /**
+ * Updates dashboard categories. Only necessary to call this after setTileEnabled
+ */
+ public void updateCategories() {
+ if (isDashboardFeatureEnabled()) {
+ new CategoriesUpdateTask().execute();
+ } else {
+ new CategoriesUpdater().execute();
+ }
+ }
+
+ public String getSettingPkg() {
+ return TileUtils.SETTING_PKG;
+ }
+
public interface CategoryListener {
void onCategoriesChanged();
}
@@ -414,7 +445,7 @@
@Override
protected Void doInBackground(Void... params) {
- mCategoryManager.reloadAllCategories(SettingsDrawerActivity.this);
+ mCategoryManager.reloadAllCategories(SettingsDrawerActivity.this, getSettingPkg());
return null;
}
@@ -425,10 +456,18 @@
}
}
+ /**
+ * @return {@code true} if IA (Information Architecture) is enabled.
+ */
protected boolean isDashboardFeatureEnabled() {
return false;
}
+ boolean isNavDrawerEnabled() {
+ return !isDashboardFeatureEnabled()
+ || getResources().getBoolean(R.bool.config_enable_nav_drawer);
+ }
+
private class PackageReceiver extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
diff --git a/packages/SettingsLib/src/com/android/settingslib/drawer/SettingsDrawerAdapter.java b/packages/SettingsLib/src/com/android/settingslib/drawer/SettingsDrawerAdapter.java
index 602d135..75942f9 100644
--- a/packages/SettingsLib/src/com/android/settingslib/drawer/SettingsDrawerAdapter.java
+++ b/packages/SettingsLib/src/com/android/settingslib/drawer/SettingsDrawerAdapter.java
@@ -68,9 +68,9 @@
notifyDataSetChanged();
}
- public void updateHomepageCategories() {
+ public void updateHomepageCategories(String settingPkg) {
final DashboardCategory category = CategoryManager.get(mActivity)
- .getTilesByCategory(mActivity, CategoryKey.CATEGORY_HOMEPAGE);
+ .getTilesByCategory(mActivity, CategoryKey.CATEGORY_HOMEPAGE, settingPkg);
mItems.clear();
// Spacer.
mItems.add(null);
diff --git a/packages/SettingsLib/src/com/android/settingslib/drawer/TileUtils.java b/packages/SettingsLib/src/com/android/settingslib/drawer/TileUtils.java
index a0109e2..b327be0 100644
--- a/packages/SettingsLib/src/com/android/settingslib/drawer/TileUtils.java
+++ b/packages/SettingsLib/src/com/android/settingslib/drawer/TileUtils.java
@@ -147,7 +147,7 @@
public static final String META_DATA_PREFERENCE_SUMMARY_URI =
"com.android.settings.summary_uri";
- private static final String SETTING_PKG = "com.android.settings";
+ public static final String SETTING_PKG = "com.android.settings";
/**
* Build a list of DashboardCategory. Each category must be defined in manifest.
@@ -167,39 +167,45 @@
*/
public static List<DashboardCategory> getCategories(Context context,
Map<Pair<String, String>, Tile> cache, boolean categoryDefinedInManifest) {
- return getCategories(context, cache, categoryDefinedInManifest, null);
+ return getCategories(context, cache, categoryDefinedInManifest, null, SETTING_PKG);
}
/**
* Build a list of DashboardCategory.
* @param categoryDefinedInManifest If true, an dummy activity must exists in manifest to
* represent this category (eg: .Settings$DeviceSettings)
- * @param extraAction additional intent filter action to be used to build the dashboard
+ * @param extraAction additional intent filter action to be usetileutild to build the dashboard
* categories
*/
public static List<DashboardCategory> getCategories(Context context,
Map<Pair<String, String>, Tile> cache, boolean categoryDefinedInManifest,
- String extraAction) {
+ String extraAction, String settingPkg) {
final long startTime = System.currentTimeMillis();
boolean setup = Global.getInt(context.getContentResolver(), Global.DEVICE_PROVISIONED, 0)
!= 0;
ArrayList<Tile> tiles = new ArrayList<>();
- UserManager userManager = UserManager.get(context);
+ UserManager userManager = (UserManager) context.getSystemService(Context.USER_SERVICE);
for (UserHandle user : userManager.getUserProfiles()) {
// TODO: Needs much optimization, too many PM queries going on here.
if (user.getIdentifier() == ActivityManager.getCurrentUser()) {
// Only add Settings for this user.
- getTilesForAction(context, user, SETTINGS_ACTION, cache, null, tiles, true);
+ getTilesForAction(context, user, SETTINGS_ACTION, cache, null, tiles, true,
+ settingPkg);
getTilesForAction(context, user, OPERATOR_SETTINGS, cache,
- OPERATOR_DEFAULT_CATEGORY, tiles, false, true);
+ OPERATOR_DEFAULT_CATEGORY, tiles, false, true, settingPkg);
getTilesForAction(context, user, MANUFACTURER_SETTINGS, cache,
- MANUFACTURER_DEFAULT_CATEGORY, tiles, false, true);
+ MANUFACTURER_DEFAULT_CATEGORY, tiles, false, true, settingPkg);
}
if (setup) {
- getTilesForAction(context, user, EXTRA_SETTINGS_ACTION, cache, null, tiles, false);
- getTilesForAction(context, user, IA_SETTINGS_ACTION, cache, null, tiles, false);
- if (extraAction != null) {
- getTilesForAction(context, user, extraAction, cache, null, tiles, false);
+ getTilesForAction(context, user, EXTRA_SETTINGS_ACTION, cache, null, tiles, false,
+ settingPkg);
+ if (!categoryDefinedInManifest) {
+ getTilesForAction(context, user, IA_SETTINGS_ACTION, cache, null, tiles, false,
+ settingPkg);
+ if (extraAction != null) {
+ getTilesForAction(context, user, extraAction, cache, null, tiles, false,
+ settingPkg);
+ }
}
}
}
@@ -263,18 +269,19 @@
private static void getTilesForAction(Context context,
UserHandle user, String action, Map<Pair<String, String>, Tile> addedCache,
- String defaultCategory, ArrayList<Tile> outTiles, boolean requireSettings) {
+ String defaultCategory, ArrayList<Tile> outTiles, boolean requireSettings,
+ String settingPkg) {
getTilesForAction(context, user, action, addedCache, defaultCategory, outTiles,
- requireSettings, requireSettings);
+ requireSettings, requireSettings, settingPkg);
}
private static void getTilesForAction(Context context,
UserHandle user, String action, Map<Pair<String, String>, Tile> addedCache,
String defaultCategory, ArrayList<Tile> outTiles, boolean requireSettings,
- boolean usePriority) {
+ boolean usePriority, String settingPkg) {
Intent intent = new Intent(action);
if (requireSettings) {
- intent.setPackage(SETTING_PKG);
+ intent.setPackage(settingPkg);
}
getTilesForIntent(context, user, intent, addedCache, defaultCategory, outTiles,
usePriority, true);
diff --git a/packages/SettingsLib/tests/integ/src/com/android/settingslib/drawer/SettingsDrawerActivityTest.java b/packages/SettingsLib/tests/integ/src/com/android/settingslib/drawer/SettingsDrawerActivityTest.java
index 1e87ea0f..2fd5ec0 100644
--- a/packages/SettingsLib/tests/integ/src/com/android/settingslib/drawer/SettingsDrawerActivityTest.java
+++ b/packages/SettingsLib/tests/integ/src/com/android/settingslib/drawer/SettingsDrawerActivityTest.java
@@ -52,34 +52,34 @@
}
@Test
- public void startActivityWithNoExtra_showNoHamburgerMenu() {
+ public void startActivityWithNoExtra_showNoNavUp() {
Instrumentation instrumentation = InstrumentationRegistry.getInstrumentation();
instrumentation.startActivitySync(new Intent(instrumentation.getTargetContext(),
TestActivity.class));
- onView(withContentDescription(R.string.content_description_menu_button))
+ onView(withContentDescription(com.android.internal.R.string.action_bar_up_description))
.check(doesNotExist());
}
@Test
- public void startActivityWithExtraToHideMenu_showNoHamburgerMenu() {
+ public void startActivityWithExtraToHideMenu_showNavUp() {
Instrumentation instrumentation = InstrumentationRegistry.getInstrumentation();
Intent intent = new Intent(instrumentation.getTargetContext(), TestActivity.class)
.putExtra(TestActivity.EXTRA_SHOW_MENU, false);
instrumentation.startActivitySync(intent);
- onView(withContentDescription(R.string.content_description_menu_button))
+ onView(withContentDescription(com.android.internal.R.string.action_bar_up_description))
.check(doesNotExist());
}
@Test
- public void startActivityWithExtraToShowMenu_showHamburgerMenu() {
+ public void startActivityWithExtraToShowMenu_showNavUp() {
Instrumentation instrumentation = InstrumentationRegistry.getInstrumentation();
Intent intent = new Intent(instrumentation.getTargetContext(), TestActivity.class)
.putExtra(TestActivity.EXTRA_SHOW_MENU, true);
instrumentation.startActivitySync(intent);
- onView(withContentDescription(R.string.content_description_menu_button))
+ onView(withContentDescription(com.android.internal.R.string.action_bar_up_description))
.check(matches(isDisplayed()));
}
diff --git a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/drawer/TileUtilsTest.java b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/drawer/TileUtilsTest.java
index eb99cac9..d8082c4 100644
--- a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/drawer/TileUtilsTest.java
+++ b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/drawer/TileUtilsTest.java
@@ -16,6 +16,8 @@
package com.android.settingslib.drawer;
+import android.app.ActivityManager;
+import static org.mockito.Mockito.verify;
import android.content.IContentProvider;
import android.content.ContentResolver;
import android.content.Context;
@@ -36,6 +38,7 @@
import android.util.Pair;
import com.android.settingslib.TestConfig;
+import static org.mockito.Mockito.atLeastOnce;
import org.junit.Before;
import org.junit.Test;
@@ -43,6 +46,7 @@
import org.mockito.ArgumentMatcher;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
+import org.robolectric.shadows.ShadowApplication;
import org.robolectric.RobolectricTestRunner;
import org.robolectric.RuntimeEnvironment;
import org.robolectric.annotation.Config;
@@ -59,6 +63,8 @@
import static org.mockito.Matchers.eq;
import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.when;
+import org.mockito.ArgumentCaptor;
+
@RunWith(RobolectricTestRunner.class)
@Config(manifest = TestConfig.MANIFEST_PATH, sdk = TestConfig.SDK_VERSION)
@@ -97,7 +103,7 @@
List<Tile> outTiles = new ArrayList<>();
List<ResolveInfo> info = new ArrayList<>();
info.add(newInfo(true, testCategory));
-
+ Map<Pair<String, String>, Tile> cache = new ArrayMap<>();
when(mPackageManager.queryIntentActivitiesAsUser(eq(intent), anyInt(), anyInt()))
.thenReturn(info);
@@ -169,12 +175,33 @@
}), anyInt(), anyInt())).thenReturn(info);
List<DashboardCategory> categoryList = TileUtils.getCategories(
- mContext, cache, false /* categoryDefinedInManifest */, testAction);
-
+ mContext, cache, false /* categoryDefinedInManifest */, testAction,
+ TileUtils.SETTING_PKG);
assertThat(categoryList.get(0).tiles.get(0).category).isEqualTo(testCategory);
}
@Test
+ public void getCategories_withPackageName() throws Exception {
+ ArgumentCaptor<Intent> intentCaptor = ArgumentCaptor.forClass(Intent.class);
+ Map<Pair<String, String>, Tile> cache = new ArrayMap<>();
+ Global.putInt(mContext.getContentResolver(), Global.DEVICE_PROVISIONED, 1);
+ when(mContext.getSystemService(Context.USER_SERVICE)).thenReturn(mUserManager);
+ List<UserHandle> userHandleList = new ArrayList<>();
+
+ userHandleList.add(new UserHandle(ActivityManager.getCurrentUser()));
+ when(mUserManager.getUserProfiles()).thenReturn(userHandleList);
+
+ TileUtils.getCategories(
+ mContext, cache, false /* categoryDefinedInManifest */, null /* action */,
+ TileUtils.SETTING_PKG);
+ verify(mPackageManager, atLeastOnce()).queryIntentActivitiesAsUser(
+ intentCaptor.capture(), anyInt(), anyInt());
+
+ assertThat(intentCaptor.getAllValues().get(0).getPackage())
+ .isEqualTo(TileUtils.SETTING_PKG);
+ }
+
+ @Test
public void getTilesForIntent_shouldNotProcessInvalidUriContentSystemApp()
throws RemoteException {
Intent intent = new Intent();
diff --git a/packages/SettingsProvider/src/com/android/providers/settings/SettingsService.java b/packages/SettingsProvider/src/com/android/providers/settings/SettingsService.java
index 6b01d66..fecc938 100644
--- a/packages/SettingsProvider/src/com/android/providers/settings/SettingsService.java
+++ b/packages/SettingsProvider/src/com/android/providers/settings/SettingsService.java
@@ -355,9 +355,11 @@
final String callPutCommand;
if ("system".equals(table)) {
callPutCommand = Settings.CALL_METHOD_PUT_SYSTEM;
- makeDefault = false;
- getOutPrintWriter().println("Ignored makeDefault - "
- + "doesn't apply to system settings");
+ if (makeDefault) {
+ getOutPrintWriter().print("Ignored makeDefault - "
+ + "doesn't apply to system settings");
+ makeDefault = false;
+ }
} else if ("secure".equals(table)) callPutCommand = Settings.CALL_METHOD_PUT_SECURE;
else if ("global".equals(table)) callPutCommand = Settings.CALL_METHOD_PUT_GLOBAL;
else {
diff --git a/packages/Shell/res/values-da/strings.xml b/packages/Shell/res/values-da/strings.xml
index 154193e..265828e 100644
--- a/packages/Shell/res/values-da/strings.xml
+++ b/packages/Shell/res/values-da/strings.xml
@@ -23,8 +23,8 @@
<string name="bugreport_updating_wait" msgid="3322151947853929470">"Vent et øjeblik…"</string>
<string name="bugreport_finished_text" product="watch" msgid="1223616207145252689">"Fejlrapporten vises på telefonen om et øjeblik"</string>
<string name="bugreport_finished_text" product="default" msgid="8353769438382138847">"Tryk for at dele din fejlrapport"</string>
- <string name="bugreport_finished_pending_screenshot_text" product="watch" msgid="1474435374470177193">"Tryk for at dele din fejlrapport uden et skærmbillede, eller vent på, at skærmbilledet fuldføres"</string>
- <string name="bugreport_finished_pending_screenshot_text" product="default" msgid="1474435374470177193">"Tryk for at dele din fejlrapport uden et skærmbillede, eller vent på, at skærmbilledet fuldføres"</string>
+ <string name="bugreport_finished_pending_screenshot_text" product="watch" msgid="1474435374470177193">"Tryk for at dele din fejlrapport uden et screenshot, eller vent på, at screenshott fuldføres"</string>
+ <string name="bugreport_finished_pending_screenshot_text" product="default" msgid="1474435374470177193">"Tryk for at dele din fejlrapport uden et screenshot, eller vent på, at screenshott fuldføres"</string>
<string name="bugreport_confirm" msgid="5917407234515812495">"Fejlrapporter indeholder data fra systemets forskellige logfiler, som kan være data, du mener er følsomme, f.eks. appforbrug og placeringsdata. Del kun fejlrapporter med personer og apps, du har tillid til."</string>
<string name="bugreport_confirm_dont_repeat" msgid="6179945398364357318">"Vis ikke igen"</string>
<string name="bugreport_storage_title" msgid="5332488144740527109">"Fejlrapporter"</string>
@@ -33,8 +33,8 @@
<string name="bugreport_unnamed" msgid="2800582406842092709">"ikke navngivet"</string>
<string name="bugreport_info_action" msgid="2158204228510576227">"Oplysninger"</string>
<string name="bugreport_screenshot_action" msgid="8677781721940614995">"Skærmbillede"</string>
- <string name="bugreport_screenshot_taken" msgid="5684211273096253120">"Der blev taget et skærmbillede."</string>
- <string name="bugreport_screenshot_failed" msgid="5853049140806834601">"Der kunne ikke tages et skærmbillede."</string>
+ <string name="bugreport_screenshot_taken" msgid="5684211273096253120">"Der blev taget et screenshot."</string>
+ <string name="bugreport_screenshot_failed" msgid="5853049140806834601">"Der kunne ikke tages et screenshot."</string>
<string name="bugreport_info_dialog_title" msgid="1355948594292983332">"Oplysninger om fejlrapporten <xliff:g id="ID">#%d</xliff:g>"</string>
<string name="bugreport_info_name" msgid="4414036021935139527">"Filnavn"</string>
<string name="bugreport_info_title" msgid="2306030793918239804">"Fejlrapportens titel"</string>
diff --git a/packages/Shell/src/com/android/shell/BugreportProgressService.java b/packages/Shell/src/com/android/shell/BugreportProgressService.java
index 47abd4f..26568cc 100644
--- a/packages/Shell/src/com/android/shell/BugreportProgressService.java
+++ b/packages/Shell/src/com/android/shell/BugreportProgressService.java
@@ -82,11 +82,14 @@
import android.os.RemoteException;
import android.os.ServiceManager;
import android.os.SystemProperties;
+import android.os.UserHandle;
+import android.os.UserManager;
import android.os.Vibrator;
import android.support.v4.content.FileProvider;
import android.text.TextUtils;
import android.text.format.DateUtils;
import android.util.Log;
+import android.util.Pair;
import android.util.Patterns;
import android.util.SparseArray;
import android.view.View;
@@ -861,9 +864,16 @@
intent.setClipData(clipData);
intent.putParcelableArrayListExtra(Intent.EXTRA_STREAM, attachments);
- final Account sendToAccount = findSendToAccount(context);
+ final Pair<UserHandle, Account> sendToAccount = findSendToAccount(context,
+ SystemProperties.get("sendbug.preferred.domain"));
if (sendToAccount != null) {
- intent.putExtra(Intent.EXTRA_EMAIL, new String[] { sendToAccount.name });
+ intent.putExtra(Intent.EXTRA_EMAIL, new String[] { sendToAccount.second.name });
+
+ // TODO Open the chooser activity on work profile by default.
+ // If we just use startActivityAsUser(), then the launched app couldn't read
+ // attachments.
+ // We probably need to change ChooserActivity to take an extra argument for the
+ // default profile.
}
return intent;
@@ -1109,44 +1119,52 @@
}
/**
- * Find the best matching {@link Account} based on build properties.
+ * Find the best matching {@link Account} based on build properties. If none found, returns
+ * the first account that looks like an email address.
*/
- private static Account findSendToAccount(Context context) {
- final AccountManager am = (AccountManager) context.getSystemService(
- Context.ACCOUNT_SERVICE);
+ @VisibleForTesting
+ static Pair<UserHandle, Account> findSendToAccount(Context context, String preferredDomain) {
+ final UserManager um = context.getSystemService(UserManager.class);
+ final AccountManager am = context.getSystemService(AccountManager.class);
- String preferredDomain = SystemProperties.get("sendbug.preferred.domain");
- if (!preferredDomain.startsWith("@")) {
+ if (preferredDomain != null && !preferredDomain.startsWith("@")) {
preferredDomain = "@" + preferredDomain;
}
- final Account[] accounts;
- try {
- accounts = am.getAccounts();
- } catch (RuntimeException e) {
- Log.e(TAG, "Could not get accounts for preferred domain " + preferredDomain, e);
- return null;
- }
- if (DEBUG) Log.d(TAG, "Number of accounts: " + accounts.length);
- Account foundAccount = null;
- for (Account account : accounts) {
- if (Patterns.EMAIL_ADDRESS.matcher(account.name).matches()) {
- if (!preferredDomain.isEmpty()) {
- // if we have a preferred domain and it matches, return; otherwise keep
- // looking
- if (account.name.endsWith(preferredDomain)) {
- return account;
+ Pair<UserHandle, Account> first = null;
+
+ for (UserHandle user : um.getUserProfiles()) {
+ final Account[] accounts;
+ try {
+ accounts = am.getAccountsAsUser(user.getIdentifier());
+ } catch (RuntimeException e) {
+ Log.e(TAG, "Could not get accounts for preferred domain " + preferredDomain
+ + " for user " + user, e);
+ continue;
+ }
+ if (DEBUG) Log.d(TAG, "User: " + user + " Number of accounts: " + accounts.length);
+ for (Account account : accounts) {
+ if (Patterns.EMAIL_ADDRESS.matcher(account.name).matches()) {
+ final Pair<UserHandle, Account> candidate = Pair.create(user, account);
+
+ if (!TextUtils.isEmpty(preferredDomain)) {
+ // if we have a preferred domain and it matches, return; otherwise keep
+ // looking
+ if (account.name.endsWith(preferredDomain)) {
+ return candidate;
+ }
+ // if we don't have a preferred domain, just return since it looks like
+ // an email address
} else {
- foundAccount = account;
+ return candidate;
}
- // if we don't have a preferred domain, just return since it looks like
- // an email address
- } else {
- return account;
+ if (first == null) {
+ first = candidate;
+ }
}
}
}
- return foundAccount;
+ return first;
}
static Uri getUri(Context context, File file) {
diff --git a/packages/Shell/tests/Android.mk b/packages/Shell/tests/Android.mk
index 872eb7a..0424eb0 100644
--- a/packages/Shell/tests/Android.mk
+++ b/packages/Shell/tests/Android.mk
@@ -10,6 +10,7 @@
LOCAL_STATIC_JAVA_LIBRARIES := \
android-support-test \
+ mockito-target-minus-junit4 \
ub-uiautomator \
LOCAL_PACKAGE_NAME := ShellTests
diff --git a/packages/Shell/tests/src/com/android/shell/BugreportProgressServiceTest.java b/packages/Shell/tests/src/com/android/shell/BugreportProgressServiceTest.java
new file mode 100644
index 0000000..cef74ae
--- /dev/null
+++ b/packages/Shell/tests/src/com/android/shell/BugreportProgressServiceTest.java
@@ -0,0 +1,351 @@
+/*
+ * Copyright (C) 2016 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.shell;
+
+import static com.android.shell.BugreportProgressService.findSendToAccount;
+
+import static junit.framework.Assert.assertEquals;
+import static junit.framework.Assert.assertNull;
+
+import static org.mockito.Matchers.anyInt;
+import static org.mockito.Matchers.eq;
+import static org.mockito.Mockito.when;
+
+import android.accounts.Account;
+import android.accounts.AccountManager;
+import android.content.Context;
+import android.os.UserHandle;
+import android.os.UserManager;
+import android.support.test.filters.SmallTest;
+import android.support.test.runner.AndroidJUnit4;
+import android.test.mock.MockContext;
+import android.util.Pair;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+
+import java.util.Arrays;
+import java.util.List;
+
+/**
+ * Test for {@link BugreportProgressServiceTest}.
+ *
+ * Usage:
+ adb shell am instrument -w \
+ -e class com.android.shell.BugreportProgressServiceTest \
+ com.android.shell.tests
+ */
+@SmallTest
+@RunWith(AndroidJUnit4.class)
+public class BugreportProgressServiceTest {
+ private static class MyContext extends MockContext {
+ @Mock
+ public UserManager userManager;
+
+ @Mock
+ public AccountManager accountManager;
+
+ public MyContext() {
+ MockitoAnnotations.initMocks(this);
+ }
+
+ @Override
+ public Object getSystemService(String name) {
+ switch (name) {
+ case Context.USER_SERVICE:
+ return userManager;
+ case Context.ACCOUNT_SERVICE:
+ return accountManager;
+ default:
+ return super.getSystemService(name);
+ }
+ }
+
+ @Override
+ public String getSystemServiceName(Class<?> serviceClass) {
+ if (UserManager.class.equals(serviceClass)) {
+ return Context.USER_SERVICE;
+ }
+ if (AccountManager.class.equals(serviceClass)) {
+ return Context.ACCOUNT_SERVICE;
+ }
+ return super.getSystemServiceName(serviceClass);
+ }
+ }
+
+ private final MyContext mTestContext = new MyContext();
+
+ private static <T> List<T> list(T... array) {
+ return Arrays.asList(array);
+ }
+
+ private static <T> T[] array(T... array) {
+ return array;
+ }
+
+ private Account account(String email) {
+ return new Account(email, "test.com");
+ }
+
+ private void checkFindSendToAccount(
+ int expectedUserId, String expectedEmail, String preferredDomain) {
+ final Pair<UserHandle, Account> actual = findSendToAccount(mTestContext, preferredDomain);
+ assertEquals(UserHandle.of(expectedUserId), actual.first);
+ assertEquals(account(expectedEmail), actual.second);
+ }
+
+ @Test
+ public void findSendToAccount_noWorkProfile() {
+ when(mTestContext.userManager.getUserProfiles()).thenReturn(
+ list(UserHandle.of(UserHandle.USER_SYSTEM)));
+
+ // No accounts.
+ when(mTestContext.accountManager.getAccountsAsUser(eq(UserHandle.USER_SYSTEM))).thenReturn(
+ array());
+
+ assertNull(findSendToAccount(mTestContext, null));
+ assertNull(findSendToAccount(mTestContext, ""));
+ assertNull(findSendToAccount(mTestContext, "android.com"));
+ assertNull(findSendToAccount(mTestContext, "@android.com"));
+
+ // 1 account
+ when(mTestContext.accountManager.getAccountsAsUser(eq(UserHandle.USER_SYSTEM))).thenReturn(
+ array(account("abc@gmail.com")));
+
+ checkFindSendToAccount(0, "abc@gmail.com", null);
+ checkFindSendToAccount(0, "abc@gmail.com", "");
+ checkFindSendToAccount(0, "abc@gmail.com", "android.com");
+ checkFindSendToAccount(0, "abc@gmail.com", "@android.com");
+ checkFindSendToAccount(0, "abc@gmail.com", "gmail.com");
+ checkFindSendToAccount(0, "abc@gmail.com", "@gmail.com");
+
+ // 2 accounts, same domain
+ when(mTestContext.accountManager.getAccountsAsUser(eq(UserHandle.USER_SYSTEM))).thenReturn(
+ array(account("abc@gmail.com"), account("def@gmail.com")));
+
+ checkFindSendToAccount(0, "abc@gmail.com", null);
+ checkFindSendToAccount(0, "abc@gmail.com", "");
+ checkFindSendToAccount(0, "abc@gmail.com", "android.com");
+ checkFindSendToAccount(0, "abc@gmail.com", "@android.com");
+ checkFindSendToAccount(0, "abc@gmail.com", "gmail.com");
+ checkFindSendToAccount(0, "abc@gmail.com", "@gmail.com");
+
+ // 2 accounts, different domains
+ when(mTestContext.accountManager.getAccountsAsUser(eq(UserHandle.USER_SYSTEM))).thenReturn(
+ array(account("abc@gmail.com"), account("def@android.com")));
+
+ checkFindSendToAccount(0, "abc@gmail.com", null);
+ checkFindSendToAccount(0, "abc@gmail.com", "");
+ checkFindSendToAccount(0, "def@android.com", "android.com");
+ checkFindSendToAccount(0, "def@android.com", "@android.com");
+ checkFindSendToAccount(0, "abc@gmail.com", "gmail.com");
+ checkFindSendToAccount(0, "abc@gmail.com", "@gmail.com");
+
+ // Plut an account that doesn't look like an email address.
+ when(mTestContext.accountManager.getAccountsAsUser(eq(UserHandle.USER_SYSTEM))).thenReturn(
+ array(account("notemail"), account("abc@gmail.com"), account("def@android.com")));
+
+ checkFindSendToAccount(0, "abc@gmail.com", null);
+ checkFindSendToAccount(0, "abc@gmail.com", "");
+ checkFindSendToAccount(0, "def@android.com", "android.com");
+ checkFindSendToAccount(0, "def@android.com", "@android.com");
+ checkFindSendToAccount(0, "abc@gmail.com", "gmail.com");
+ checkFindSendToAccount(0, "abc@gmail.com", "@gmail.com");
+ }
+
+ /**
+ * Same as {@link #findSendToAccount_noWorkProfile()}, but with work profile, which has no
+ * accounts. The expected results are the same as the original.
+ */
+ @Test
+ public void findSendToAccount_withWorkProfile_noAccounts() {
+ when(mTestContext.userManager.getUserProfiles()).thenReturn(
+ list(UserHandle.of(UserHandle.USER_SYSTEM), UserHandle.of(10)));
+
+ // Work profile has no accounts
+ when(mTestContext.accountManager.getAccountsAsUser(eq(10))).thenReturn(
+ array());
+
+ // No accounts.
+ when(mTestContext.accountManager.getAccountsAsUser(eq(UserHandle.USER_SYSTEM))).thenReturn(
+ array());
+
+ assertNull(findSendToAccount(mTestContext, null));
+ assertNull(findSendToAccount(mTestContext, ""));
+ assertNull(findSendToAccount(mTestContext, "android.com"));
+ assertNull(findSendToAccount(mTestContext, "@android.com"));
+
+ // 1 account
+ when(mTestContext.accountManager.getAccountsAsUser(eq(UserHandle.USER_SYSTEM))).thenReturn(
+ array(account("abc@gmail.com")));
+
+ checkFindSendToAccount(0, "abc@gmail.com", null);
+ checkFindSendToAccount(0, "abc@gmail.com", "");
+ checkFindSendToAccount(0, "abc@gmail.com", "android.com");
+ checkFindSendToAccount(0, "abc@gmail.com", "@android.com");
+ checkFindSendToAccount(0, "abc@gmail.com", "gmail.com");
+ checkFindSendToAccount(0, "abc@gmail.com", "@gmail.com");
+
+ // 2 accounts, same domain
+ when(mTestContext.accountManager.getAccountsAsUser(eq(UserHandle.USER_SYSTEM))).thenReturn(
+ array(account("abc@gmail.com"), account("def@gmail.com")));
+
+ checkFindSendToAccount(0, "abc@gmail.com", null);
+ checkFindSendToAccount(0, "abc@gmail.com", "");
+ checkFindSendToAccount(0, "abc@gmail.com", "android.com");
+ checkFindSendToAccount(0, "abc@gmail.com", "@android.com");
+ checkFindSendToAccount(0, "abc@gmail.com", "gmail.com");
+ checkFindSendToAccount(0, "abc@gmail.com", "@gmail.com");
+
+ // 2 accounts, different domains
+ when(mTestContext.accountManager.getAccountsAsUser(eq(UserHandle.USER_SYSTEM))).thenReturn(
+ array(account("abc@gmail.com"), account("def@android.com")));
+
+ checkFindSendToAccount(0, "abc@gmail.com", null);
+ checkFindSendToAccount(0, "abc@gmail.com", "");
+ checkFindSendToAccount(0, "def@android.com", "android.com");
+ checkFindSendToAccount(0, "def@android.com", "@android.com");
+ checkFindSendToAccount(0, "abc@gmail.com", "gmail.com");
+ checkFindSendToAccount(0, "abc@gmail.com", "@gmail.com");
+
+ // Plut an account that doesn't look like an email address.
+ when(mTestContext.accountManager.getAccountsAsUser(eq(UserHandle.USER_SYSTEM))).thenReturn(
+ array(account("notemail"), account("abc@gmail.com"), account("def@android.com")));
+
+ checkFindSendToAccount(0, "abc@gmail.com", null);
+ checkFindSendToAccount(0, "abc@gmail.com", "");
+ checkFindSendToAccount(0, "def@android.com", "android.com");
+ checkFindSendToAccount(0, "def@android.com", "@android.com");
+ checkFindSendToAccount(0, "abc@gmail.com", "gmail.com");
+ checkFindSendToAccount(0, "abc@gmail.com", "@gmail.com");
+ }
+
+ /**
+ * Same as {@link #findSendToAccount_noWorkProfile()}, but with work profile, which has
+ * 1 account. The expected results are the same as the original, expect for the "no accounts
+ * on the primary profile" case.
+ */
+ @Test
+ public void findSendToAccount_withWorkProfile_1account() {
+ when(mTestContext.userManager.getUserProfiles()).thenReturn(
+ list(UserHandle.of(UserHandle.USER_SYSTEM), UserHandle.of(10)));
+
+ // Work profile has no accounts
+ when(mTestContext.accountManager.getAccountsAsUser(eq(10))).thenReturn(
+ array(account("xyz@gmail.com")));
+
+ // No accounts.
+ when(mTestContext.accountManager.getAccountsAsUser(eq(UserHandle.USER_SYSTEM))).thenReturn(
+ array());
+
+ checkFindSendToAccount(10, "xyz@gmail.com", null);
+ checkFindSendToAccount(10, "xyz@gmail.com", "");
+ checkFindSendToAccount(10, "xyz@gmail.com", "android.com");
+ checkFindSendToAccount(10, "xyz@gmail.com", "@android.com");
+
+ // 1 account
+ when(mTestContext.accountManager.getAccountsAsUser(eq(UserHandle.USER_SYSTEM))).thenReturn(
+ array(account("abc@gmail.com")));
+
+ checkFindSendToAccount(0, "abc@gmail.com", null);
+ checkFindSendToAccount(0, "abc@gmail.com", "");
+ checkFindSendToAccount(0, "abc@gmail.com", "android.com");
+ checkFindSendToAccount(0, "abc@gmail.com", "@android.com");
+ checkFindSendToAccount(0, "abc@gmail.com", "gmail.com");
+ checkFindSendToAccount(0, "abc@gmail.com", "@gmail.com");
+
+ // 2 accounts, same domain
+ when(mTestContext.accountManager.getAccountsAsUser(eq(UserHandle.USER_SYSTEM))).thenReturn(
+ array(account("abc@gmail.com"), account("def@gmail.com")));
+
+ checkFindSendToAccount(0, "abc@gmail.com", null);
+ checkFindSendToAccount(0, "abc@gmail.com", "");
+ checkFindSendToAccount(0, "abc@gmail.com", "android.com");
+ checkFindSendToAccount(0, "abc@gmail.com", "@android.com");
+ checkFindSendToAccount(0, "abc@gmail.com", "gmail.com");
+ checkFindSendToAccount(0, "abc@gmail.com", "@gmail.com");
+
+ // 2 accounts, different domains
+ when(mTestContext.accountManager.getAccountsAsUser(eq(UserHandle.USER_SYSTEM))).thenReturn(
+ array(account("abc@gmail.com"), account("def@android.com")));
+
+ checkFindSendToAccount(0, "abc@gmail.com", null);
+ checkFindSendToAccount(0, "abc@gmail.com", "");
+ checkFindSendToAccount(0, "def@android.com", "android.com");
+ checkFindSendToAccount(0, "def@android.com", "@android.com");
+ checkFindSendToAccount(0, "abc@gmail.com", "gmail.com");
+ checkFindSendToAccount(0, "abc@gmail.com", "@gmail.com");
+
+ // Plut an account that doesn't look like an email address.
+ when(mTestContext.accountManager.getAccountsAsUser(eq(UserHandle.USER_SYSTEM))).thenReturn(
+ array(account("notemail"), account("abc@gmail.com"), account("def@android.com")));
+
+ checkFindSendToAccount(0, "abc@gmail.com", null);
+ checkFindSendToAccount(0, "abc@gmail.com", "");
+ checkFindSendToAccount(0, "def@android.com", "android.com");
+ checkFindSendToAccount(0, "def@android.com", "@android.com");
+ checkFindSendToAccount(0, "abc@gmail.com", "gmail.com");
+ checkFindSendToAccount(0, "abc@gmail.com", "@gmail.com");
+ }
+
+ /**
+ * Same as {@link #findSendToAccount_noWorkProfile()}, but with work profile, with mixed
+ * domains.
+ */
+ @Test
+ public void findSendToAccount_withWorkProfile_mixedDomains() {
+ when(mTestContext.userManager.getUserProfiles()).thenReturn(
+ list(UserHandle.of(UserHandle.USER_SYSTEM), UserHandle.of(10)));
+
+ // Work profile has no accounts
+ when(mTestContext.accountManager.getAccountsAsUser(eq(10))).thenReturn(
+ array(account("xyz@android.com")));
+
+ // No accounts.
+ when(mTestContext.accountManager.getAccountsAsUser(eq(UserHandle.USER_SYSTEM))).thenReturn(
+ array());
+
+ checkFindSendToAccount(10, "xyz@android.com", null);
+ checkFindSendToAccount(10, "xyz@android.com", "");
+ checkFindSendToAccount(10, "xyz@android.com", "android.com");
+ checkFindSendToAccount(10, "xyz@android.com", "@android.com");
+
+ // 1 account
+ when(mTestContext.accountManager.getAccountsAsUser(eq(UserHandle.USER_SYSTEM))).thenReturn(
+ array(account("abc@gmail.com")));
+
+ checkFindSendToAccount(0, "abc@gmail.com", null);
+ checkFindSendToAccount(0, "abc@gmail.com", "");
+ checkFindSendToAccount(10, "xyz@android.com", "android.com");
+ checkFindSendToAccount(10, "xyz@android.com", "@android.com");
+ checkFindSendToAccount(0, "abc@gmail.com", "gmail.com");
+ checkFindSendToAccount(0, "abc@gmail.com", "@gmail.com");
+
+ // more accounts.
+ when(mTestContext.accountManager.getAccountsAsUser(eq(UserHandle.USER_SYSTEM))).thenReturn(
+ array(account("abc@gmail.com"), account("def@gmail.com")));
+
+ checkFindSendToAccount(0, "abc@gmail.com", null);
+ checkFindSendToAccount(0, "abc@gmail.com", "");
+ checkFindSendToAccount(10, "xyz@android.com", "android.com");
+ checkFindSendToAccount(10, "xyz@android.com", "@android.com");
+ checkFindSendToAccount(0, "abc@gmail.com", "gmail.com");
+ checkFindSendToAccount(0, "abc@gmail.com", "@gmail.com");
+ }
+}
diff --git a/packages/SystemUI/AndroidManifest.xml b/packages/SystemUI/AndroidManifest.xml
index 5c2787b..5574753 100644
--- a/packages/SystemUI/AndroidManifest.xml
+++ b/packages/SystemUI/AndroidManifest.xml
@@ -427,6 +427,7 @@
android:supportsPictureInPicture="true"
android:stateNotNeeded="true"
android:taskAffinity=""
+ android:launchMode="singleTop"
androidprv:alwaysFocusable="true" />
<!-- platform logo easter egg activity -->
diff --git a/packages/SystemUI/plugin/src/com/android/systemui/plugins/PluginInstanceManager.java b/packages/SystemUI/plugin/src/com/android/systemui/plugins/PluginInstanceManager.java
index 62d3ce4..388c71d 100644
--- a/packages/SystemUI/plugin/src/com/android/systemui/plugins/PluginInstanceManager.java
+++ b/packages/SystemUI/plugin/src/com/android/systemui/plugins/PluginInstanceManager.java
@@ -14,22 +14,32 @@
package com.android.systemui.plugins;
+import android.app.Notification;
+import android.app.Notification.Action;
+import android.app.NotificationManager;
+import android.app.PendingIntent;
+import android.content.BroadcastReceiver;
import android.content.ComponentName;
import android.content.Context;
import android.content.ContextWrapper;
import android.content.Intent;
+import android.content.IntentFilter;
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageManager;
+import android.content.pm.PackageManager.NameNotFoundException;
import android.content.pm.ResolveInfo;
+import android.content.res.Resources;
import android.net.Uri;
import android.os.Build;
import android.os.Handler;
import android.os.Looper;
import android.os.Message;
+import android.os.UserHandle;
import android.util.Log;
import android.view.LayoutInflater;
import com.android.internal.annotations.VisibleForTesting;
+import com.android.internal.messages.nano.SystemMessageProto.SystemMessage;
import java.util.ArrayList;
import java.util.List;
@@ -260,10 +270,9 @@
String pkg = component.getPackageName();
String cls = component.getClassName();
try {
- PackageManager pm = mPm;
- ApplicationInfo info = pm.getApplicationInfo(pkg, 0);
+ ApplicationInfo info = mPm.getApplicationInfo(pkg, 0);
// TODO: This probably isn't needed given that we don't have IGNORE_SECURITY on
- if (pm.checkPermission(PLUGIN_PERMISSION, pkg)
+ if (mPm.checkPermission(PLUGIN_PERMISSION, pkg)
!= PackageManager.PERMISSION_GRANTED) {
Log.d(TAG, "Plugin doesn't have permission: " + pkg);
return null;
@@ -275,6 +284,43 @@
Class<?> pluginClass = Class.forName(cls, true, classLoader);
T plugin = (T) pluginClass.newInstance();
if (plugin.getVersion() != mVersion) {
+ final int icon = mContext.getResources().getIdentifier("tuner", "drawable",
+ mContext.getPackageName());
+ final int color = Resources.getSystem().getIdentifier(
+ "system_notification_accent_color", "color", "android");
+ final Notification.Builder nb = new Notification.Builder(mContext)
+ .setStyle(new Notification.BigTextStyle())
+ .setSmallIcon(icon)
+ .setWhen(0)
+ .setShowWhen(false)
+ .setPriority(Notification.PRIORITY_MAX)
+ .setVisibility(Notification.VISIBILITY_PUBLIC)
+ .setColor(mContext.getColor(color));
+ String label = cls;
+ try {
+ label = mPm.getServiceInfo(component, 0).loadLabel(mPm).toString();
+ } catch (NameNotFoundException e) {
+ }
+ if (plugin.getVersion() < mVersion) {
+ // Localization not required as this will never ever appear in a user build.
+ nb.setContentTitle("Plugin \"" + label + "\" is too old")
+ .setContentText("Contact plugin developer to get an updated"
+ + " version.\nPlugin version: " + plugin.getVersion()
+ + "\nSystem version: " + mVersion);
+ } else {
+ // Localization not required as this will never ever appear in a user build.
+ nb.setContentTitle("Plugin \"" + label + "\" is too new")
+ .setContentText("Check to see if an OTA is available.\n"
+ + "Plugin version: " + plugin.getVersion()
+ + "\nSystem version: " + mVersion);
+ }
+ Intent i = new Intent(PluginManager.DISABLE_PLUGIN).setData(
+ Uri.parse("package://" + component.flattenToString()));
+ PendingIntent pi = PendingIntent.getBroadcast(mContext, 0, i, 0);
+ nb.addAction(new Action.Builder(null, "Disable plugin", pi).build());
+ mContext.getSystemService(NotificationManager.class)
+ .notifyAsUser(cls, SystemMessage.NOTE_PLUGIN, nb.build(),
+ UserHandle.ALL);
// TODO: Warn user.
Log.w(TAG, "Plugin has invalid interface version " + plugin.getVersion()
+ ", expected " + mVersion);
diff --git a/packages/SystemUI/plugin/src/com/android/systemui/plugins/PluginManager.java b/packages/SystemUI/plugin/src/com/android/systemui/plugins/PluginManager.java
index 60cf312..6096eaf 100644
--- a/packages/SystemUI/plugin/src/com/android/systemui/plugins/PluginManager.java
+++ b/packages/SystemUI/plugin/src/com/android/systemui/plugins/PluginManager.java
@@ -14,11 +14,14 @@
package com.android.systemui.plugins;
+import android.app.NotificationManager;
import android.content.BroadcastReceiver;
+import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.pm.ApplicationInfo;
+import android.content.pm.PackageManager;
import android.content.pm.PackageManager.NameNotFoundException;
import android.net.Uri;
import android.os.Build;
@@ -28,6 +31,7 @@
import android.util.ArrayMap;
import com.android.internal.annotations.VisibleForTesting;
+import com.android.internal.messages.nano.SystemMessageProto.SystemMessage;
import com.android.systemui.plugins.PluginInstanceManager.PluginContextWrapper;
import dalvik.system.PathClassLoader;
@@ -42,6 +46,8 @@
public static final String PLUGIN_CHANGED = "com.android.systemui.action.PLUGIN_CHANGED";
+ static final String DISABLE_PLUGIN = "com.android.systemui.action.DISABLE_PLUGIN";
+
private static PluginManager sInstance;
private final HandlerThread mBackgroundThread;
@@ -112,6 +118,7 @@
filter.addAction(Intent.ACTION_PACKAGE_CHANGED);
filter.addAction(Intent.ACTION_PACKAGE_REMOVED);
filter.addAction(PLUGIN_CHANGED);
+ filter.addAction(DISABLE_PLUGIN);
filter.addDataScheme("package");
mContext.registerReceiver(this, filter);
filter = new IntentFilter(Intent.ACTION_USER_UNLOCKED);
@@ -128,6 +135,15 @@
for (PluginInstanceManager manager : mPluginMap.values()) {
manager.loadAll();
}
+ } else if (DISABLE_PLUGIN.equals(intent.getAction())) {
+ Uri uri = intent.getData();
+ ComponentName component = ComponentName.unflattenFromString(
+ uri.toString().substring(10));
+ mContext.getPackageManager().setComponentEnabledSetting(component,
+ PackageManager.COMPONENT_ENABLED_STATE_DISABLED,
+ PackageManager.DONT_KILL_APP);
+ mContext.getSystemService(NotificationManager.class).cancel(component.getClassName(),
+ SystemMessage.NOTE_PLUGIN);
} else {
Uri data = intent.getData();
String pkg = data.getEncodedSchemeSpecificPart();
diff --git a/packages/SystemUI/res/color/data_usage_graph_track.xml b/packages/SystemUI/res/color/data_usage_graph_track.xml
new file mode 100644
index 0000000..55c4d2f
--- /dev/null
+++ b/packages/SystemUI/res/color/data_usage_graph_track.xml
@@ -0,0 +1,18 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- 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.
+-->
+<selector xmlns:android="http://schemas.android.com/apk/res/android">
+ <item android:alpha="0.2" android:color="?android:attr/colorForeground" />
+</selector>
\ No newline at end of file
diff --git a/packages/SystemUI/res/color/data_usage_graph_warning.xml b/packages/SystemUI/res/color/data_usage_graph_warning.xml
new file mode 100644
index 0000000..15944c3
--- /dev/null
+++ b/packages/SystemUI/res/color/data_usage_graph_warning.xml
@@ -0,0 +1,18 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- 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.
+-->
+<selector xmlns:android="http://schemas.android.com/apk/res/android">
+ <item android:color="?android:attr/colorForeground" />
+</selector>
\ No newline at end of file
diff --git a/packages/SystemUI/res/color/tint_color_selector.xml b/packages/SystemUI/res/color/tint_color_selector.xml
new file mode 100644
index 0000000..cb24425
--- /dev/null
+++ b/packages/SystemUI/res/color/tint_color_selector.xml
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2016 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.
+-->
+<selector xmlns:android="http://schemas.android.com/apk/res/android">
+ <item android:state_enabled="false"
+ android:alpha="0.25"
+ android:color="?android:attr/colorForeground"/>
+ <item android:state_activated="false"
+ android:alpha="0.3"
+ android:color="?android:attr/colorForeground"/>
+ <item android:color="?android:attr/colorForeground"/>
+</selector>
\ No newline at end of file
diff --git a/packages/SystemUI/res/drawable-nodpi/tuner.xml b/packages/SystemUI/res/drawable-nodpi/tuner.xml
index 0596aa4..c0e51a4 100644
--- a/packages/SystemUI/res/drawable-nodpi/tuner.xml
+++ b/packages/SystemUI/res/drawable-nodpi/tuner.xml
@@ -17,7 +17,8 @@
android:width="24.0dp"
android:height="24.0dp"
android:viewportWidth="24.0"
- android:viewportHeight="24.0">
+ android:viewportHeight="24.0"
+ android:tint="?android:attr/colorControlNormal">
<path
android:fillColor="#FFFFFFFF"
android:pathData="M22.7,19.0l-9.1,-9.1c0.9,-2.0 0.4,-5.0 -1.5,-6.9 -2.0,-2.0 -5.0,-2.4 -7.4,-1.3L9.0,6.0 6.0,9.0 1.6,4.7C0.4,7.0 0.9,10.1 2.9,12.1c1.9,1.9 4.6,2.4 6.9,1.5l9.1,9.1c0.4,0.4 1.0,0.4 1.4,0.0l2.3,-2.3c0.5,-0.4 0.5,-1.0 0.1,-1.4z"/>
diff --git a/packages/SystemUI/res/drawable/ic_device_thermostat_24.xml b/packages/SystemUI/res/drawable/ic_device_thermostat_24.xml
new file mode 100644
index 0000000..1972f6e
--- /dev/null
+++ b/packages/SystemUI/res/drawable/ic_device_thermostat_24.xml
@@ -0,0 +1,25 @@
+<!--
+Copyright (C) 2016 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.
+-->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:width="24dp"
+ android:height="24dp"
+ android:viewportWidth="24.0"
+ android:viewportHeight="24.0"
+ android:tint="?attr/colorControlNormal">
+ <path
+ android:fillColor="#FFFFFFFF"
+ android:pathData="M15,13L15,5c0,-1.66 -1.34,-3 -3,-3S9,3.34 9,5v8c-1.21,0.91 -2,2.37 -2,4 0,2.76 2.24,5 5,5s5,-2.24 5,-5c0,-1.63 -0.79,-3.09 -2,-4zM11,5c0,-0.55 0.45,-1 1,-1s1,0.45 1,1h-1v1h1v2h-1v1h1v2h-2L11,5z"/>
+</vector>
diff --git a/packages/SystemUI/res/drawable/ic_hotspot_unavailable.xml b/packages/SystemUI/res/drawable/ic_hotspot_unavailable.xml
index 736cfd8..83f46e5 100644
--- a/packages/SystemUI/res/drawable/ic_hotspot_unavailable.xml
+++ b/packages/SystemUI/res/drawable/ic_hotspot_unavailable.xml
@@ -20,7 +20,8 @@
android:width="48dp"
android:viewportHeight="48"
android:viewportWidth="48"
- android:tint="@color/qs_tile_tint_unavailable" >
+ android:alpha="0.25"
+ android:tint="?android:attr/colorControlNormal" >
<group
android:name="ic_hotspot"
android:translateX="23.97354"
diff --git a/packages/SystemUI/res/layout-sw410dp/status_bar_alarm_group.xml b/packages/SystemUI/res/layout-sw410dp/status_bar_alarm_group.xml
index efdfae7..e85b76d 100644
--- a/packages/SystemUI/res/layout-sw410dp/status_bar_alarm_group.xml
+++ b/packages/SystemUI/res/layout-sw410dp/status_bar_alarm_group.xml
@@ -67,7 +67,6 @@
android:paddingTop="3dp"
android:drawablePadding="8dp"
android:drawableStart="@drawable/ic_access_alarms_small"
- android:textColor="?android:attr/textColorSecondary"
android:textAppearance="@style/TextAppearance.StatusBar.Expanded.Date"
android:gravity="top"
android:background="?android:attr/selectableItemBackground"
diff --git a/packages/SystemUI/res/layout/pip_menu_action.xml b/packages/SystemUI/res/layout/pip_menu_action.xml
index db6ae19a..9b954f7 100644
--- a/packages/SystemUI/res/layout/pip_menu_action.xml
+++ b/packages/SystemUI/res/layout/pip_menu_action.xml
@@ -13,32 +13,9 @@
See the License for the specific language governing permissions and
limitations under the License.
-->
-<FrameLayout
+<ImageView
xmlns:android="http://schemas.android.com/apk/res/android"
- android:layout_width="0dp"
- android:layout_height="match_parent"
- android:layout_weight="1"
- android:background="?android:selectableItemBackground">
- <LinearLayout
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:layout_gravity="center_vertical"
- android:orientation="vertical">
- <ImageView
- android:id="@+id/icon"
- android:layout_width="@dimen/pip_menu_action_icon_size"
- android:layout_height="@dimen/pip_menu_action_icon_size"
- android:layout_gravity="center_horizontal"
- android:layout_marginBottom="4dp" />
- <TextView
- android:id="@+id/title"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:includeFontPadding="false"
- android:gravity="center"
- android:textSize="12sp"
- android:textColor="#ffffffff"
- android:textAllCaps="true"
- android:fontFamily="sans-serif" />
- </LinearLayout>
-</FrameLayout>
\ No newline at end of file
+ android:layout_width="48dp"
+ android:layout_height="48dp"
+ android:padding="10dp"
+ android:background="?android:selectableItemBackgroundBorderless" />
\ No newline at end of file
diff --git a/packages/SystemUI/res/layout/pip_menu_activity.xml b/packages/SystemUI/res/layout/pip_menu_activity.xml
index 054bfab..cf65f4a 100644
--- a/packages/SystemUI/res/layout/pip_menu_activity.xml
+++ b/packages/SystemUI/res/layout/pip_menu_activity.xml
@@ -13,47 +13,38 @@
See the License for the specific language governing permissions and
limitations under the License.
-->
-
<FrameLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/menu"
android:layout_width="match_parent"
android:layout_height="match_parent"
- android:background="#33000000">
+ android:background="#00000000">
+ <!-- The above background is only for the dismiss button ripple to show. -->
- <LinearLayout
- android:id="@+id/actions"
- android:layout_width="match_parent"
- android:layout_height="match_parent"
- android:layout_marginBottom="48dp">
- </LinearLayout>
+ <ImageView
+ android:id="@+id/dismiss"
+ android:layout_width="48dp"
+ android:layout_height="48dp"
+ android:layout_gravity="top|end"
+ android:padding="10dp"
+ android:contentDescription="@string/pip_phone_dismiss"
+ android:src="@drawable/ic_close_white"
+ android:background="?android:selectableItemBackgroundBorderless" />
- <LinearLayout
+ <FrameLayout
+ android:id="@+id/actions_container"
android:layout_width="match_parent"
android:layout_height="48dp"
android:layout_gravity="bottom"
- android:orientation="horizontal">
- <TextView
- android:id="@+id/dismiss"
- android:layout_width="0dp"
+ android:paddingStart="24dp"
+ android:paddingEnd="24dp"
+ android:background="#66000000"
+ android:visibility="invisible">
+ <LinearLayout
+ android:id="@+id/actions"
+ android:layout_width="wrap_content"
android:layout_height="match_parent"
- android:layout_weight="1"
- android:gravity="center"
- android:textSize="12sp"
- android:textColor="#ffffffff"
- android:fontFamily="sans-serif"
- android:text="@string/pip_phone_dismiss"
- android:background="?android:selectableItemBackground" />
- <TextView
- android:id="@+id/minimize"
- android:layout_width="0dp"
- android:layout_height="match_parent"
- android:layout_weight="1"
- android:gravity="center"
- android:textSize="12sp"
- android:textColor="#ffffffff"
- android:fontFamily="sans-serif"
- android:text="@string/pip_phone_minimize"
- android:background="?android:selectableItemBackground" />
- </LinearLayout>
+ android:layout_gravity="center_horizontal"
+ android:orientation="horizontal" />
+ </FrameLayout>
</FrameLayout>
diff --git a/packages/SystemUI/res/layout/quick_status_bar_expanded_header.xml b/packages/SystemUI/res/layout/quick_status_bar_expanded_header.xml
index 6673d6e..53acb9f 100644
--- a/packages/SystemUI/res/layout/quick_status_bar_expanded_header.xml
+++ b/packages/SystemUI/res/layout/quick_status_bar_expanded_header.xml
@@ -72,19 +72,20 @@
android:clipChildren="false"
android:clipToPadding="false">
- <com.android.systemui.statusbar.phone.SettingsButton android:id="@+id/settings_button"
+ <com.android.systemui.statusbar.phone.SettingsButton
+ android:id="@+id/settings_button"
style="@android:style/Widget.Material.Button.Borderless"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@drawable/ripple_drawable"
android:src="@drawable/ic_settings_20dp"
android:contentDescription="@string/accessibility_quick_settings_settings" />
- <com.android.systemui.statusbar.AlphaOptimizedImageView android:id="@+id/tuner_icon"
+ <com.android.systemui.statusbar.AlphaOptimizedImageView
+ android:id="@+id/tuner_icon"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:paddingStart="36dp"
- android:tint="#4DFFFFFF"
- android:tintMode="src_in"
+ android:alpha="0.3"
android:visibility="invisible"
android:src="@drawable/tuner" />
diff --git a/packages/SystemUI/res/layout/status_bar_alarm_group.xml b/packages/SystemUI/res/layout/status_bar_alarm_group.xml
index 03585b8..a02e9af 100644
--- a/packages/SystemUI/res/layout/status_bar_alarm_group.xml
+++ b/packages/SystemUI/res/layout/status_bar_alarm_group.xml
@@ -65,7 +65,6 @@
android:paddingTop="3dp"
android:drawablePadding="8dp"
android:drawableStart="@drawable/ic_access_alarms_small"
- android:textColor="?android:attr/textColorSecondary"
android:textAppearance="@style/TextAppearance.StatusBar.Expanded.Date"
android:gravity="top"
android:background="?android:attr/selectableItemBackground"
diff --git a/packages/SystemUI/res/values/colors.xml b/packages/SystemUI/res/values/colors.xml
index c7149df..b18b6ac 100644
--- a/packages/SystemUI/res/values/colors.xml
+++ b/packages/SystemUI/res/values/colors.xml
@@ -31,15 +31,11 @@
<color name="batterymeter_bolt_color">#FFFFFFFF</color>
<color name="qs_batterymeter_frame_color">#FF404040</color>
<color name="system_warning_color">@*android:color/system_error</color>
- <color name="qs_text">#FFFFFFFF</color>
<color name="qs_tile_divider">#29ffffff</color><!-- 16% white -->
<color name="qs_subhead">#99FFFFFF</color><!-- 60% white -->
<color name="qs_detail_button">@*android:color/quaternary_device_default_settings</color>
<color name="qs_detail_button_white">#B3FFFFFF</color><!-- 70% white -->
<color name="qs_detail_transition">#66FFFFFF</color>
- <color name="data_usage_secondary">#99FFFFFF</color><!-- 60% white -->
- <color name="data_usage_graph_track">#33FFFFFF</color><!-- 20% white -->
- <color name="data_usage_graph_warning">#FFFFFFFF</color>
<color name="status_bar_clock_color">#FFFFFFFF</color>
<color name="qs_user_detail_icon_muted">#FFFFFFFF</color> <!-- not so muted after all -->
<color name="qs_tile_disabled_color">#9E9E9E</color> <!-- 38% black -->
@@ -144,10 +140,6 @@
<color name="remote_input_accent">#eeeeee</color>
- <color name="qs_tile_tint_unavailable">#40ffffff</color>
- <color name="qs_tile_tint_inactive">#4dffffff</color>
- <color name="qs_tile_tint_active">#ffffffff</color>
-
<!-- Keyboard shortcuts colors -->
<color name="ksh_application_group_color">#fff44336</color>
<color name="ksh_keyword_color">#d9000000</color>
diff --git a/packages/SystemUI/res/values/config.xml b/packages/SystemUI/res/values/config.xml
index 0f5d37e..50ef392 100644
--- a/packages/SystemUI/res/values/config.xml
+++ b/packages/SystemUI/res/values/config.xml
@@ -290,4 +290,11 @@
<bool name="quick_settings_show_full_alarm">false</bool>
+ <!-- Whether to show a warning notification when the device reaches a certain temperature. -->
+ <bool name="config_showTemperatureWarning">false</bool>
+
+ <!-- Temp at which to show a warning notification if config_showTemperatureWarning is true.
+ If < 0, uses the value from HardwarePropertiesManager#getDeviceTemperatures. -->
+ <integer name="config_warningTemperature">-1</integer>
+
</resources>
diff --git a/packages/SystemUI/res/values/dimens.xml b/packages/SystemUI/res/values/dimens.xml
index ca4214b..78d211f 100644
--- a/packages/SystemUI/res/values/dimens.xml
+++ b/packages/SystemUI/res/values/dimens.xml
@@ -724,10 +724,7 @@
<!-- The alpha to apply to the recents row when it doesn't have focus -->
<item name="recents_recents_row_dim_alpha" format="float" type="dimen">0.5</item>
- <!-- The size of the PIP dismiss target. -->
+ <!-- The size of the PIP drag-to-dismiss target. -->
<dimen name="pip_dismiss_target_size">48dp</dimen>
- <!-- The size of a PIP menu action icon. -->
- <dimen name="pip_menu_action_icon_size">32dp</dimen>
-
</resources>
diff --git a/packages/SystemUI/res/values/ids.xml b/packages/SystemUI/res/values/ids.xml
index 2a895f9..4a19dde 100644
--- a/packages/SystemUI/res/values/ids.xml
+++ b/packages/SystemUI/res/values/ids.xml
@@ -52,7 +52,8 @@
<item type="id" name="notification_power"/>
<item type="id" name="notification_screenshot"/>
<item type="id" name="notification_hidden"/>
- <item type="id" name="notification_volumeui"/>
+ <item type="id" name="notification_temperature"/>
+ <item type="id" name="notification_plugin"/>
<item type="id" name="transformation_start_x_tag"/>
<item type="id" name="transformation_start_y_tag"/>
<item type="id" name="transformation_start_scale_x_tag"/>
diff --git a/packages/SystemUI/res/values/strings.xml b/packages/SystemUI/res/values/strings.xml
index 194653b..34a0397 100644
--- a/packages/SystemUI/res/values/strings.xml
+++ b/packages/SystemUI/res/values/strings.xml
@@ -1125,21 +1125,6 @@
<!-- Hide quick settings tile confirmation button -->
<string name="quick_settings_reset_confirmation_button">Hide</string>
- <!-- VolumeUI activation dialog: warning message -->
- <string name="volumeui_prompt_message"><xliff:g id="app_name" example="Volume Prototype 1">%1$s</xliff:g> wants to be the volume dialog.</string>
-
- <!-- VolumeUI activation dialog: allow button label -->
- <string name="volumeui_prompt_allow">Allow</string>
-
- <!-- VolumeUI activation dialog: deny button label -->
- <string name="volumeui_prompt_deny">Deny</string>
-
- <!-- VolumeUI restoration notification: title -->
- <string name="volumeui_notification_title"><xliff:g id="app_name" example="Volume Prototype 1">%1$s</xliff:g> is the volume dialog</string>
-
- <!-- VolumeUI restoration notification: text -->
- <string name="volumeui_notification_text">Tap to restore the original.</string>
-
<!-- Toast shown when user unlocks screen and managed profile activity is in the foreground -->
<string name="managed_profile_foreground_toast">You\'re using your work profile</string>
@@ -1719,14 +1704,6 @@
not appear on production builds ever. -->
<string name="picture_in_picture" translatable="false">Picture-in-Picture</string>
- <!-- PIP swipe to dismiss title. Non-translatable since it should
- not appear on production builds ever. -->
- <string name="pip_swipe_to_dismiss_title" translatable="false">Swipe to dismiss</string>
-
- <!-- PIP swipe to dismiss description. Non-translatable since it should
- not appear on production builds ever. -->
- <string name="pip_swipe_to_dismiss_summary" translatable="false">Swipe left or right off screen to close the PIP</string>
-
<!-- PIP drag to dismiss title. Non-translatable since it should
not appear on production builds ever. -->
<string name="pip_drag_to_dismiss_title" translatable="false">Drag to dismiss</string>
@@ -1735,22 +1712,6 @@
not appear on production builds ever. -->
<string name="pip_drag_to_dismiss_summary" translatable="false">Drag to the dismiss target at the bottom of the screen to close the PIP</string>
- <!-- PIP tap once to break through to the activity title. Non-translatable since it should
- not appear on production builds ever. -->
- <string name="pip_tap_through_title" translatable="false">Tap to interact</string>
-
- <!-- PIP tap once to break through to the activity description. Non-translatable since it should
- not appear on production builds ever. -->
- <string name="pip_tap_through_summary" translatable="false">Tap once to interact with the activity</string>
-
- <!-- PIP snap to closest edge title. Non-translatable since it should
- not appear on production builds ever. -->
- <string name="pip_snap_mode_edge_title" translatable="false">Snap to closest edge</string>
-
- <!-- PIP snap to closest edge description. Non-translatable since it should
- not appear on production builds ever. -->
- <string name="pip_snap_mode_edge_summary" translatable="false">Snap to the closest edge</string>
-
<!-- PIP allow minimize title. Non-translatable since it should
not appear on production builds ever. -->
<string name="pip_allow_minimize_title" translatable="false">Allow PIP to minimize</string>
@@ -1766,4 +1727,12 @@
<!-- Tuner string -->
<string name="default_theme" translatable="false">Default</string>
+ <!-- Title for notification (and dialog) that user's phone has reached a certain temperature and may start to slow down in order to cool down. [CHAR LIMIT=30] -->
+ <string name="high_temp_title">Phone is getting warm</string>
+ <!-- Message body for notification that user's phone has reached a certain temperature and may start to slow down in order to cool down. [CHAR LIMIT=100] -->
+ <string name="high_temp_notif_message">Some features limited while phone cools down</string>
+ <!-- Text body for dialog alerting user that their phone has reached a certain temperature and may start to slow down in order to cool down. [CHAR LIMIT=300] -->
+ <string name="high_temp_dialog_message">Your phone will automatically try to cool down. You can still use your phone, but it may run slower.\n\nOnce your phone has cooled down, it will run normally.</string>
+
+
</resources>
diff --git a/packages/SystemUI/res/values/styles.xml b/packages/SystemUI/res/values/styles.xml
index fc1d816..a9c858c 100644
--- a/packages/SystemUI/res/values/styles.xml
+++ b/packages/SystemUI/res/values/styles.xml
@@ -68,7 +68,7 @@
<item name="android:windowIsTranslucent">true</item>
<item name="android:windowNoTitle">true</item>
<item name="android:windowContentOverlay">@null</item>
- <item name="android:windowBackground">@drawable/forced_resizable_background</item>
+ <item name="android:windowBackground">@null</item>
<item name="android:colorBackgroundCacheHint">@null</item>
<item name="android:statusBarColor">@color/transparent</item>
<item name="android:windowAnimationStyle">@style/Animation.PipPhoneOverlayControl</item>
@@ -117,13 +117,13 @@
<style name="TextAppearance.StatusBar.Expanded.Date">
<item name="android:textSize">@dimen/qs_date_collapsed_size</item>
<item name="android:textStyle">normal</item>
- <item name="android:textColor">#b2ffffff</item>
+ <item name="android:textColor">?android:attr/textColorSecondary</item>
</style>
<style name="TextAppearance.StatusBar.Expanded.AboveDateTime">
<item name="android:textSize">@dimen/qs_emergency_calls_only_text_size</item>
<item name="android:textStyle">normal</item>
- <item name="android:textColor">#66ffffff</item>
+ <item name="android:textColor">?android:attr/textColorSecondary</item>
</style>
<style name="TextAppearance.StatusBar.Expanded.EmergencyCallsOnly"
@@ -207,7 +207,7 @@
</style>
<style name="TextAppearance.QS.DataUsage.Secondary">
- <item name="android:textColor">@color/data_usage_secondary</item>
+ <item name="android:textColor">?android:attr/textColorSecondary</item>
</style>
<style name="TextAppearance.QS.TileLabel">
diff --git a/packages/SystemUI/res/xml/tuner_prefs.xml b/packages/SystemUI/res/xml/tuner_prefs.xml
index 74d5d6c..59a10da 100644
--- a/packages/SystemUI/res/xml/tuner_prefs.xml
+++ b/packages/SystemUI/res/xml/tuner_prefs.xml
@@ -126,34 +126,16 @@
android:title="@string/picture_in_picture">
<com.android.systemui.tuner.TunerSwitch
- android:key="pip_swipe_to_dismiss"
- android:title="@string/pip_swipe_to_dismiss_title"
- android:summary="@string/pip_swipe_to_dismiss_summary"
- sysui:defValue="true" />
-
- <com.android.systemui.tuner.TunerSwitch
android:key="pip_drag_to_dismiss"
android:title="@string/pip_drag_to_dismiss_title"
android:summary="@string/pip_drag_to_dismiss_summary"
- sysui:defValue="true" />
-
- <com.android.systemui.tuner.TunerSwitch
- android:key="pip_tap_through"
- android:title="@string/pip_tap_through_title"
- android:summary="@string/pip_tap_through_summary"
- sysui:defValue="false" />
-
- <com.android.systemui.tuner.TunerSwitch
- android:key="pip_snap_mode_edge"
- android:title="@string/pip_snap_mode_edge_title"
- android:summary="@string/pip_snap_mode_edge_summary"
- sysui:defValue="false" />
+ sysui:defValue="false" />
<com.android.systemui.tuner.TunerSwitch
android:key="pip_allow_minimize"
android:title="@string/pip_allow_minimize_title"
android:summary="@string/pip_allow_minimize_summary"
- sysui:defValue="false" />
+ sysui:defValue="true" />
</PreferenceScreen>
diff --git a/packages/SystemUI/src/com/android/systemui/BatteryMeterDrawable.java b/packages/SystemUI/src/com/android/systemui/BatteryMeterDrawable.java
index c4698c3..07ef5e0 100755
--- a/packages/SystemUI/src/com/android/systemui/BatteryMeterDrawable.java
+++ b/packages/SystemUI/src/com/android/systemui/BatteryMeterDrawable.java
@@ -491,6 +491,12 @@
@Override
public void setColorFilter(@Nullable ColorFilter colorFilter) {
+ mFramePaint.setColorFilter(colorFilter);
+ mBatteryPaint.setColorFilter(colorFilter);
+ mWarningTextPaint.setColorFilter(colorFilter);
+ mTextPaint.setColorFilter(colorFilter);
+ mBoltPaint.setColorFilter(colorFilter);
+ mPlusPaint.setColorFilter(colorFilter);
}
@Override
diff --git a/packages/SystemUI/src/com/android/systemui/SystemUIApplication.java b/packages/SystemUI/src/com/android/systemui/SystemUIApplication.java
index b207984..d109ae1 100644
--- a/packages/SystemUI/src/com/android/systemui/SystemUIApplication.java
+++ b/packages/SystemUI/src/com/android/systemui/SystemUIApplication.java
@@ -42,6 +42,7 @@
import com.android.systemui.recents.Recents;
import com.android.systemui.shortcut.ShortcutKeyDispatcher;
import com.android.systemui.stackdivider.Divider;
+import com.android.systemui.statusbar.CommandQueue;
import com.android.systemui.statusbar.SystemBars;
import com.android.systemui.statusbar.phone.PhoneStatusBar;
import com.android.systemui.tuner.TunerService;
@@ -65,6 +66,7 @@
private final Class<?>[] SERVICES = new Class[] {
FragmentService.class,
TunerService.class,
+ CommandQueue.CommandQueueStart.class,
KeyguardViewMediator.class,
Recents.class,
VolumeUI.class,
diff --git a/packages/SystemUI/src/com/android/systemui/pip/phone/PipMenuActivity.java b/packages/SystemUI/src/com/android/systemui/pip/phone/PipMenuActivity.java
index fe8ee6f..1798730 100644
--- a/packages/SystemUI/src/com/android/systemui/pip/phone/PipMenuActivity.java
+++ b/packages/SystemUI/src/com/android/systemui/pip/phone/PipMenuActivity.java
@@ -16,13 +16,16 @@
package com.android.systemui.pip.phone;
+import android.animation.Animator;
+import android.animation.AnimatorListenerAdapter;
+import android.animation.ObjectAnimator;
import android.annotation.Nullable;
import android.app.Activity;
import android.app.ActivityManager;
-import android.app.PendingIntent.CanceledException;
import android.app.RemoteAction;
import android.content.Intent;
import android.content.pm.ParceledListSlice;
+import android.graphics.PointF;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
@@ -30,11 +33,15 @@
import android.os.RemoteException;
import android.util.Log;
import android.view.LayoutInflater;
+import android.view.MotionEvent;
import android.view.View;
+import android.view.ViewConfiguration;
import android.view.ViewGroup;
+import android.view.WindowManager.LayoutParams;
import android.widget.ImageView;
import android.widget.TextView;
+import com.android.systemui.Interpolators;
import com.android.systemui.R;
import java.util.ArrayList;
@@ -47,28 +54,39 @@
private static final String TAG = "PipMenuActivity";
- public static final int MESSAGE_FINISH_SELF = 1;
- public static final int MESSAGE_UPDATE_ACTIONS = 2;
+ public static final int MESSAGE_SHOW_MENU = 1;
+ public static final int MESSAGE_HIDE_MENU = 2;
+ public static final int MESSAGE_UPDATE_ACTIONS = 3;
private static final long INITIAL_DISMISS_DELAY = 2000;
private static final long POST_INTERACTION_DISMISS_DELAY = 1500;
+ private static final long MENU_FADE_DURATION = 125;
- private List<RemoteAction> mActions = new ArrayList<>();
+ private boolean mMenuVisible;
+ private final List<RemoteAction> mActions = new ArrayList<>();
+ private View mMenuContainer;
private View mDismissButton;
- private View mMinimizeButton;
+ private ObjectAnimator mMenuContainerAnimator;
+
+ private PointF mDownPosition = new PointF();
+ private PointF mDownDelta = new PointF();
+ private ViewConfiguration mViewConfig;
private Handler mHandler = new Handler();
private Messenger mToControllerMessenger;
private Messenger mMessenger = new Messenger(new Handler() {
@Override
public void handleMessage(Message msg) {
switch (msg.what) {
+ case MESSAGE_SHOW_MENU:
+ showMenu();
+ break;
+ case MESSAGE_HIDE_MENU:
+ hideMenu();
+ break;
case MESSAGE_UPDATE_ACTIONS:
setActions(((ParceledListSlice) msg.obj).getList());
break;
- case MESSAGE_FINISH_SELF:
- finish();
- break;
}
}
});
@@ -76,12 +94,17 @@
private final Runnable mFinishRunnable = new Runnable() {
@Override
public void run() {
- finish();
+ hideMenu();
}
};
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
+ // Set the flags to allow us to watch for outside touches and also hide the menu and start
+ // manipulating the PIP in the same touch gesture
+ mViewConfig = ViewConfiguration.get(this);
+ getWindow().addFlags(LayoutParams.FLAG_WATCH_OUTSIDE_TOUCH | LayoutParams.FLAG_SLIPPERY);
+
super.onCreate(savedInstanceState);
setContentView(R.layout.pip_menu_activity);
@@ -94,44 +117,70 @@
setActions(actions.getList());
}
- findViewById(R.id.menu).setOnClickListener((v) -> {
+ mMenuContainer = findViewById(R.id.menu);
+ mMenuContainer.setOnClickListener((v) -> {
expandPip();
});
mDismissButton = findViewById(R.id.dismiss);
mDismissButton.setOnClickListener((v) -> {
dismissPip();
});
- mMinimizeButton = findViewById(R.id.minimize);
- mMinimizeButton.setOnClickListener((v) -> {
- minimizePip();
- });
+
+ notifyActivityCallback(mMessenger);
+ showMenu();
+ }
+
+ @Override
+ protected void onNewIntent(Intent intent) {
+ super.onNewIntent(intent);
+ showMenu();
}
@Override
protected void onStart() {
super.onStart();
- notifyActivityVisibility(true);
+ notifyMenuVisibility(true);
repostDelayedFinish(INITIAL_DISMISS_DELAY);
}
@Override
+ public void onPictureInPictureModeChanged(boolean isInPictureInPictureMode) {
+ if (!isInPictureInPictureMode) {
+ finish();
+ }
+ }
+
+ @Override
public void onUserInteraction() {
repostDelayedFinish(POST_INTERACTION_DISMISS_DELAY);
}
@Override
- protected void onStop() {
- super.onStop();
- finish();
+ public boolean dispatchTouchEvent(MotionEvent ev) {
+ // On the first action outside the window, hide the menu
+ switch (ev.getAction()) {
+ case MotionEvent.ACTION_OUTSIDE:
+ hideMenu();
+ break;
+ case MotionEvent.ACTION_DOWN:
+ mDownPosition.set(ev.getX(), ev.getY());
+ break;
+ case MotionEvent.ACTION_MOVE:
+ mDownDelta.set(ev.getX() - mDownPosition.x, ev.getY() - mDownPosition.y);
+ if (mDownDelta.length() > mViewConfig.getScaledTouchSlop() && mMenuVisible) {
+ hideMenu();
+ mMenuVisible = false;
+ }
+ }
+ return super.dispatchTouchEvent(ev);
}
@Override
public void finish() {
- View v = getWindow().getDecorView();
- v.removeCallbacks(mFinishRunnable);
- notifyActivityVisibility(false);
+ notifyActivityCallback(null);
super.finish();
- overridePendingTransition(0, R.anim.forced_resizable_exit);
+ // Hide without an animation (the menu should already be invisible at this point)
+ overridePendingTransition(0, 0);
}
@Override
@@ -139,6 +188,51 @@
// Do nothing
}
+ private void showMenu() {
+ if (!mMenuVisible) {
+ if (mMenuContainerAnimator != null) {
+ mMenuContainerAnimator.cancel();
+ }
+
+ notifyMenuVisibility(true);
+ mMenuContainerAnimator = ObjectAnimator.ofFloat(mMenuContainer, View.ALPHA,
+ mMenuContainer.getAlpha(), 1f);
+ mMenuContainerAnimator.setInterpolator(Interpolators.ALPHA_IN);
+ mMenuContainerAnimator.setDuration(MENU_FADE_DURATION);
+ mMenuContainerAnimator.addListener(new AnimatorListenerAdapter() {
+ @Override
+ public void onAnimationEnd(Animator animation) {
+ repostDelayedFinish(INITIAL_DISMISS_DELAY);
+ }
+ });
+ mMenuContainerAnimator.start();
+ }
+ }
+
+ private void hideMenu() {
+ hideMenu(null /* animationFinishedRunnable */);
+ }
+
+ private void hideMenu(final Runnable animationFinishedRunnable) {
+ if (mMenuVisible) {
+ cancelDelayedFinish();
+ notifyMenuVisibility(false);
+ mMenuContainerAnimator = ObjectAnimator.ofFloat(mMenuContainer, View.ALPHA,
+ mMenuContainer.getAlpha(), 0f);
+ mMenuContainerAnimator.setInterpolator(Interpolators.ALPHA_OUT);
+ mMenuContainerAnimator.setDuration(MENU_FADE_DURATION);
+ mMenuContainerAnimator.addListener(new AnimatorListenerAdapter() {
+ @Override
+ public void onAnimationEnd(Animator animation) {
+ if (animationFinishedRunnable != null) {
+ animationFinishedRunnable.run();
+ }
+ }
+ });
+ mMenuContainerAnimator.start();
+ }
+ }
+
private void setActions(List<RemoteAction> actions) {
mActions.clear();
mActions.addAll(actions);
@@ -146,44 +240,52 @@
}
private void updateActionViews() {
- ViewGroup actionsContainer = (ViewGroup) findViewById(R.id.actions);
- if (actionsContainer != null) {
- actionsContainer.removeAllViews();
+ ViewGroup actionsContainer = (ViewGroup) findViewById(R.id.actions_container);
+ actionsContainer.setOnTouchListener((v, ev) -> {
+ // Do nothing, prevent click through to parent
+ return true;
+ });
- // Recreate the layout
- final LayoutInflater inflater = LayoutInflater.from(this);
- for (int i = 0; i < mActions.size(); i++) {
- final RemoteAction action = mActions.get(i);
- final ViewGroup actionContainer = (ViewGroup) inflater.inflate(
- R.layout.pip_menu_action, actionsContainer, false);
- actionContainer.setOnClickListener((v) -> {
- action.sendActionInvoked();
- });
+ if (mActions.isEmpty()) {
+ actionsContainer.setVisibility(View.INVISIBLE);
+ } else {
+ actionsContainer.setVisibility(View.VISIBLE);
+ ViewGroup actionsGroup = (ViewGroup) findViewById(R.id.actions);
+ if (actionsGroup != null) {
+ actionsGroup.removeAllViews();
- final TextView title = (TextView) actionContainer.findViewById(R.id.title);
- title.setText(action.getTitle());
- title.setContentDescription(action.getContentDescription());
-
- final ImageView icon = (ImageView) actionContainer.findViewById(R.id.icon);
- action.getIcon().loadDrawableAsync(this, (d) -> {
- icon.setImageDrawable(d);
- }, mHandler);
- actionsContainer.addView(actionContainer);
+ // Recreate the layout
+ final LayoutInflater inflater = LayoutInflater.from(this);
+ for (int i = 0; i < mActions.size(); i++) {
+ final RemoteAction action = mActions.get(i);
+ final ImageView actionView = (ImageView) inflater.inflate(
+ R.layout.pip_menu_action, actionsGroup, false);
+ action.getIcon().loadDrawableAsync(this, d -> {
+ actionView.setImageDrawable(d);
+ }, mHandler);
+ actionView.setContentDescription(action.getContentDescription());
+ actionView.setOnClickListener(v -> {
+ action.sendActionInvoked();
+ });
+ actionsGroup.addView(actionView);
+ }
}
}
}
- private void notifyActivityVisibility(boolean visible) {
+ private void notifyMenuVisibility(boolean visible) {
+ mMenuVisible = visible;
Message m = Message.obtain();
- m.what = PipMenuActivityController.MESSAGE_ACTIVITY_VISIBILITY_CHANGED;
+ m.what = PipMenuActivityController.MESSAGE_MENU_VISIBILITY_CHANGED;
m.arg1 = visible ? 1 : 0;
- m.replyTo = visible ? mMessenger : null;
sendMessage(m, "Could not notify controller of PIP menu visibility");
}
private void expandPip() {
- sendEmptyMessage(PipMenuActivityController.MESSAGE_EXPAND_PIP,
- "Could not notify controller to expand PIP");
+ hideMenu(() -> {
+ sendEmptyMessage(PipMenuActivityController.MESSAGE_EXPAND_PIP,
+ "Could not notify controller to expand PIP");
+ });
}
private void minimizePip() {
@@ -192,8 +294,17 @@
}
private void dismissPip() {
- sendEmptyMessage(PipMenuActivityController.MESSAGE_DISMISS_PIP,
- "Could not notify controller to dismiss PIP");
+ hideMenu(() -> {
+ sendEmptyMessage(PipMenuActivityController.MESSAGE_DISMISS_PIP,
+ "Could not notify controller to dismiss PIP");
+ });
+ }
+
+ private void notifyActivityCallback(Messenger callback) {
+ Message m = Message.obtain();
+ m.what = PipMenuActivityController.MESSAGE_UPDATE_ACTIVITY_CALLBACK;
+ m.replyTo = callback;
+ sendMessage(m, "Could not notify controller of activity finished");
}
private void sendEmptyMessage(int what, String errorMsg) {
@@ -210,6 +321,11 @@
}
}
+ private void cancelDelayedFinish() {
+ View v = getWindow().getDecorView();
+ v.removeCallbacks(mFinishRunnable);
+ }
+
private void repostDelayedFinish(long delay) {
View v = getWindow().getDecorView();
v.removeCallbacks(mFinishRunnable);
diff --git a/packages/SystemUI/src/com/android/systemui/pip/phone/PipMenuActivityController.java b/packages/SystemUI/src/com/android/systemui/pip/phone/PipMenuActivityController.java
index 64e2d1a..0350cc6 100644
--- a/packages/SystemUI/src/com/android/systemui/pip/phone/PipMenuActivityController.java
+++ b/packages/SystemUI/src/com/android/systemui/pip/phone/PipMenuActivityController.java
@@ -25,10 +25,11 @@
public static final String EXTRA_CONTROLLER_MESSENGER = "messenger";
public static final String EXTRA_ACTIONS = "actions";
- public static final int MESSAGE_ACTIVITY_VISIBILITY_CHANGED = 100;
+ public static final int MESSAGE_MENU_VISIBILITY_CHANGED = 100;
public static final int MESSAGE_EXPAND_PIP = 101;
public static final int MESSAGE_MINIMIZE_PIP = 102;
public static final int MESSAGE_DISMISS_PIP = 103;
+ public static final int MESSAGE_UPDATE_ACTIVITY_CALLBACK = 104;
/**
* A listener interface to receive notification on changes in PIP.
@@ -67,34 +68,25 @@
@Override
public void handleMessage(Message msg) {
switch (msg.what) {
- case MESSAGE_ACTIVITY_VISIBILITY_CHANGED: {
+ case MESSAGE_MENU_VISIBILITY_CHANGED: {
boolean visible = msg.arg1 > 0;
- int listenerCount = mListeners.size();
- for (int i = 0; i < listenerCount; i++) {
- mListeners.get(i).onPipMenuVisibilityChanged(visible);
- }
- mToActivityMessenger = msg.replyTo;
+ mListeners.forEach(l -> l.onPipMenuVisibilityChanged(visible));
break;
}
case MESSAGE_EXPAND_PIP: {
- int listenerCount = mListeners.size();
- for (int i = 0; i < listenerCount; i++) {
- mListeners.get(i).onPipExpand();
- }
+ mListeners.forEach(l -> l.onPipExpand());
break;
}
case MESSAGE_MINIMIZE_PIP: {
- int listenerCount = mListeners.size();
- for (int i = 0; i < listenerCount; i++) {
- mListeners.get(i).onPipMinimize();
- }
+ mListeners.forEach(l -> l.onPipMinimize());
break;
}
case MESSAGE_DISMISS_PIP: {
- int listenerCount = mListeners.size();
- for (int i = 0; i < listenerCount; i++) {
- mListeners.get(i).onPipDismiss();
- }
+ mListeners.forEach(l -> l.onPipDismiss());
+ break;
+ }
+ case MESSAGE_UPDATE_ACTIVITY_CALLBACK: {
+ mToActivityMessenger = msg.replyTo;
break;
}
}
@@ -121,24 +113,34 @@
* Shows the menu activity.
*/
public void showMenu() {
- // Start the menu activity on the top task of the pinned stack
- try {
- StackInfo pinnedStackInfo = mActivityManager.getStackInfo(PINNED_STACK_ID);
- if (pinnedStackInfo != null && pinnedStackInfo.taskIds != null &&
- pinnedStackInfo.taskIds.length > 0) {
- Intent intent = new Intent(mContext, PipMenuActivity.class);
- intent.putExtra(EXTRA_CONTROLLER_MESSENGER, mMessenger);
- intent.putExtra(EXTRA_ACTIONS, mActions);
- ActivityOptions options = ActivityOptions.makeBasic();
- options.setLaunchTaskId(
- pinnedStackInfo.taskIds[pinnedStackInfo.taskIds.length - 1]);
- options.setTaskOverlay(true);
- mContext.startActivityAsUser(intent, options.toBundle(), UserHandle.CURRENT);
- } else {
- Log.e(TAG, "No PIP tasks found");
+ if (mToActivityMessenger != null) {
+ Message m = Message.obtain();
+ m.what = PipMenuActivity.MESSAGE_SHOW_MENU;
+ try {
+ mToActivityMessenger.send(m);
+ } catch (RemoteException e) {
+ Log.e(TAG, "Could not notify menu to show", e);
}
- } catch (RemoteException e) {
- Log.e(TAG, "Error showing PIP menu activity", e);
+ } else {
+ // Start the menu activity on the top task of the pinned stack
+ try {
+ StackInfo pinnedStackInfo = mActivityManager.getStackInfo(PINNED_STACK_ID);
+ if (pinnedStackInfo != null && pinnedStackInfo.taskIds != null &&
+ pinnedStackInfo.taskIds.length > 0) {
+ Intent intent = new Intent(mContext, PipMenuActivity.class);
+ intent.putExtra(EXTRA_CONTROLLER_MESSENGER, mMessenger);
+ intent.putExtra(EXTRA_ACTIONS, mActions);
+ ActivityOptions options = ActivityOptions.makeCustomAnimation(mContext, 0, 0);
+ options.setLaunchTaskId(
+ pinnedStackInfo.taskIds[pinnedStackInfo.taskIds.length - 1]);
+ options.setTaskOverlay(true);
+ mContext.startActivityAsUser(intent, options.toBundle(), UserHandle.CURRENT);
+ } else {
+ Log.e(TAG, "No PIP tasks found");
+ }
+ } catch (RemoteException e) {
+ Log.e(TAG, "Error showing PIP menu activity", e);
+ }
}
}
@@ -148,13 +150,12 @@
public void hideMenu() {
if (mToActivityMessenger != null) {
Message m = Message.obtain();
- m.what = PipMenuActivity.MESSAGE_FINISH_SELF;
+ m.what = PipMenuActivity.MESSAGE_HIDE_MENU;
try {
mToActivityMessenger.send(m);
} catch (RemoteException e) {
- Log.e(TAG, "Could not notify menu activity to finish", e);
+ Log.e(TAG, "Could not notify menu to hide", e);
}
- mToActivityMessenger = null;
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/pip/phone/PipTouchHandler.java b/packages/SystemUI/src/com/android/systemui/pip/phone/PipTouchHandler.java
index ff3cc79..d5ae3ad 100644
--- a/packages/SystemUI/src/com/android/systemui/pip/phone/PipTouchHandler.java
+++ b/packages/SystemUI/src/com/android/systemui/pip/phone/PipTouchHandler.java
@@ -58,10 +58,7 @@
private static final String TAG = "PipTouchHandler";
private static final boolean DEBUG_ALLOW_OUT_OF_BOUNDS_STACK = false;
- private static final String TUNER_KEY_SWIPE_TO_DISMISS = "pip_swipe_to_dismiss";
private static final String TUNER_KEY_DRAG_TO_DISMISS = "pip_drag_to_dismiss";
- private static final String TUNER_KEY_TAP_THROUGH = "pip_tap_through";
- private static final String TUNER_KEY_SNAP_MODE_EDGE = "pip_snap_mode_edge";
private static final String TUNER_KEY_ALLOW_MINIMIZE = "pip_allow_minimize";
private static final int SNAP_STACK_DURATION = 225;
@@ -71,8 +68,6 @@
// The fraction of the stack width that the user has to drag offscreen to minimize the PIP
private static final float MINIMIZE_OFFSCREEN_FRACTION = 0.15f;
- // The fraction of the stack width that the user has to move when flinging to dismiss the PIP
- private static final float DISMISS_FLING_DISTANCE_FRACTION = 0.3f;
private final Context mContext;
private final IActivityManager mActivityManager;
@@ -87,16 +82,10 @@
private final PipSnapAlgorithm mSnapAlgorithm;
private PipMotionHelper mMotionHelper;
- // Allow swiping offscreen to dismiss the PIP
- private boolean mEnableSwipeToDismiss = true;
// Allow dragging the PIP to a location to close it
- private boolean mEnableDragToDismiss = true;
- // Allow tapping on the PIP to show additional controls
- private boolean mEnableTapThrough = false;
- // Allow snapping the PIP to the closest edge and not the corners of the screen
- private boolean mEnableSnapToEdge = false;
+ private boolean mEnableDragToDismiss = false;
// Allow the PIP to be "docked" slightly offscreen
- private boolean mEnableMinimizing = false;
+ private boolean mEnableMinimizing = true;
private final Rect mPinnedStackBounds = new Rect();
private final Rect mBoundedPinnedStackBounds = new Rect();
@@ -174,7 +163,7 @@
@Override
public void onPipDismiss() {
- animateDismissPinnedStack(mPinnedStackBounds);
+ BackgroundThread.getHandler().post(PipTouchHandler.this::dismissPinnedStack);
}
}
@@ -192,16 +181,15 @@
mSnapAlgorithm = new PipSnapAlgorithm(mContext);
mTouchState = new PipTouchState(mViewConfig);
mFlingAnimationUtils = new FlingAnimationUtils(context, 2f);
- mGestures = new PipTouchGesture[]{
- mDragToDismissGesture, mSwipeToDismissGesture, mTapThroughGesture, mMinimizeGesture,
- mDefaultMovementGesture
+ mGestures = new PipTouchGesture[] {
+ mDragToDismissGesture, mTapThroughGesture, mMinimizeGesture, mDefaultMovementGesture
};
mMotionHelper = new PipMotionHelper(BackgroundThread.getHandler());
registerInputConsumer();
+ setSnapToEdge(true);
// Register any tuner settings changes
- TunerService.get(context).addTunable(this, TUNER_KEY_SWIPE_TO_DISMISS,
- TUNER_KEY_DRAG_TO_DISMISS, TUNER_KEY_TAP_THROUGH, TUNER_KEY_SNAP_MODE_EDGE,
+ TunerService.get(context).addTunable(this, TUNER_KEY_DRAG_TO_DISMISS,
TUNER_KEY_ALLOW_MINIMIZE);
}
@@ -209,34 +197,18 @@
public void onTuningChanged(String key, String newValue) {
if (newValue == null) {
// Reset back to default
- mEnableSwipeToDismiss = true;
- mEnableDragToDismiss = true;
- mEnableMinimizing = false;
+ mEnableDragToDismiss = false;
+ mEnableMinimizing = true;
setMinimizedState(false);
- mEnableTapThrough = false;
- mIsTappingThrough = false;
- mEnableSnapToEdge = false;
- setSnapToEdge(false);
return;
}
switch (key) {
- case TUNER_KEY_SWIPE_TO_DISMISS:
- mEnableSwipeToDismiss = Integer.parseInt(newValue) != 0;
- break;
case TUNER_KEY_DRAG_TO_DISMISS:
mEnableDragToDismiss = Integer.parseInt(newValue) != 0;
break;
case TUNER_KEY_ALLOW_MINIMIZE:
mEnableMinimizing = Integer.parseInt(newValue) != 0;
break;
- case TUNER_KEY_TAP_THROUGH:
- mEnableTapThrough = Integer.parseInt(newValue) != 0;
- mIsTappingThrough = false;
- break;
- case TUNER_KEY_SNAP_MODE_EDGE:
- mEnableSnapToEdge = Integer.parseInt(newValue) != 0;
- setSnapToEdge(mEnableSnapToEdge);
- break;
}
}
@@ -328,26 +300,31 @@
* Registers the input consumer.
*/
private void registerInputConsumer() {
- final InputChannel inputChannel = new InputChannel();
- try {
- mWindowManager.destroyInputConsumer(INPUT_CONSUMER_PIP);
- mWindowManager.createInputConsumer(INPUT_CONSUMER_PIP, inputChannel);
- } catch (RemoteException e) {
- Log.e(TAG, "Failed to create PIP input consumer", e);
+ if (mInputEventReceiver == null) {
+ final InputChannel inputChannel = new InputChannel();
+ try {
+ mWindowManager.destroyInputConsumer(INPUT_CONSUMER_PIP);
+ mWindowManager.createInputConsumer(INPUT_CONSUMER_PIP, inputChannel);
+ } catch (RemoteException e) {
+ Log.e(TAG, "Failed to create PIP input consumer", e);
+ }
+ mInputEventReceiver = new PipInputEventReceiver(inputChannel, Looper.myLooper());
}
- mInputEventReceiver = new PipInputEventReceiver(inputChannel, Looper.myLooper());
}
/**
* Unregisters the input consumer.
*/
private void unregisterInputConsumer() {
- try {
- mWindowManager.destroyInputConsumer(INPUT_CONSUMER_PIP);
- } catch (RemoteException e) {
- Log.e(TAG, "Failed to destroy PIP input consumer", e);
+ if (mInputEventReceiver != null) {
+ try {
+ mWindowManager.destroyInputConsumer(INPUT_CONSUMER_PIP);
+ } catch (RemoteException e) {
+ Log.e(TAG, "Failed to destroy PIP input consumer", e);
+ }
+ mInputEventReceiver.dispose();
+ mInputEventReceiver = null;
}
- mInputEventReceiver.dispose();
}
/**
@@ -476,45 +453,6 @@
}
/**
- * @return whether the velocity is coincident with the current pinned stack bounds to be
- * considered a fling to dismiss.
- */
- private boolean isFlingToDismiss(float velocityX) {
- Point displaySize = new Point();
- mContext.getDisplay().getRealSize(displaySize);
- return (mPinnedStackBounds.right > displaySize.x && velocityX > 0) ||
- (mPinnedStackBounds.left < 0 && velocityX < 0);
- }
-
- /**
- * Flings the PIP to dismiss it offscreen.
- */
- private void flingToDismiss(float velocityX) {
- Point displaySize = new Point();
- mContext.getDisplay().getRealSize(displaySize);
- float offsetX = velocityX > 0
- ? displaySize.x + mPinnedStackBounds.width()
- : -mPinnedStackBounds.width();
-
- Rect toBounds = new Rect(mPinnedStackBounds);
- toBounds.offsetTo((int) offsetX, toBounds.top);
- if (!mPinnedStackBounds.equals(toBounds)) {
- mPinnedStackBoundsAnimator = mMotionHelper.createAnimationToBounds(mPinnedStackBounds,
- toBounds, 0, FAST_OUT_SLOW_IN, mUpdatePinnedStackBoundsListener);
- mFlingAnimationUtils.apply(mPinnedStackBoundsAnimator, 0,
- distanceBetweenRectOffsets(mPinnedStackBounds, toBounds),
- velocityX);
- mPinnedStackBoundsAnimator.addListener(new AnimatorListenerAdapter() {
- @Override
- public void onAnimationEnd(Animator animation) {
- BackgroundThread.getHandler().post(PipTouchHandler.this::dismissPinnedStack);
- }
- });
- mPinnedStackBoundsAnimator.start();
- }
- }
-
- /**
* Animates the dismissal of the PIP over the dismiss target bounds.
*/
private void animateDismissPinnedStack(Rect dismissBounds) {
@@ -638,57 +576,6 @@
/**** Gestures ****/
/**
- * Gesture controlling swiping offscreen to dismiss the PIP.
- */
- private PipTouchGesture mSwipeToDismissGesture = new PipTouchGesture() {
- @Override
- boolean onMove(PipTouchState touchState) {
- if (mEnableSwipeToDismiss) {
- boolean isDraggingOffscreen = isDraggingOffscreen(touchState);
-
- if (touchState.startedDragging() && isDraggingOffscreen) {
- // Reset the minimized state once we drag horizontally
- setMinimizedState(false);
- }
-
- if (touchState.allowDraggingOffscreen() && isDraggingOffscreen) {
- // Move the pinned stack, but ignore the vertical movement
- float left = mPinnedStackBounds.left + touchState.getLastTouchDelta().x;
- mTmpBounds.set(mPinnedStackBounds);
- mTmpBounds.offsetTo((int) left, mPinnedStackBounds.top);
- if (!mTmpBounds.equals(mPinnedStackBounds)) {
- mPinnedStackBounds.set(mTmpBounds);
- mMotionHelper.resizeToBounds(mPinnedStackBounds);
- }
- return true;
- }
- }
- return false;
- }
-
- @Override
- public boolean onUp(PipTouchState touchState) {
- if (mEnableSwipeToDismiss && touchState.isDragging()) {
- PointF vel = touchState.getVelocity();
- PointF downDelta = touchState.getDownTouchDelta();
- float minFlingVel = mFlingAnimationUtils.getMinVelocityPxPerSecond();
- float flingVelScale = mEnableMinimizing ? 3f : 2f;
- if (Math.abs(vel.x) > (flingVelScale * minFlingVel)) {
- // Determine if this gesture is actually a fling to dismiss
- if (isFlingToDismiss(vel.x) && Math.abs(downDelta.x) >=
- (DISMISS_FLING_DISTANCE_FRACTION * mPinnedStackBounds.width())) {
- flingToDismiss(vel.x);
- } else {
- flingToSnapTarget(vel.length(), vel.x, vel.y);
- }
- return true;
- }
- }
- return false;
- }
- };
-
- /**
* Gesture controlling dragging the PIP slightly offscreen to minimize it.
*/
private PipTouchGesture mMinimizeGesture = new PipTouchGesture() {
@@ -761,17 +648,12 @@
private PipTouchGesture mTapThroughGesture = new PipTouchGesture() {
@Override
boolean onMove(PipTouchState touchState) {
- if (mEnableTapThrough && touchState.startedDragging()) {
- mIsTappingThrough = false;
- mMenuController.hideMenu();
- }
return false;
}
@Override
public boolean onUp(PipTouchState touchState) {
- if (mEnableTapThrough && !touchState.isDragging() && !mIsMinimized &&
- !mIsTappingThrough) {
+ if (!touchState.isDragging() && !mIsMinimized && !mIsTappingThrough) {
mMenuController.showMenu();
mIsTappingThrough = true;
return true;
diff --git a/packages/SystemUI/src/com/android/systemui/power/PowerNotificationWarnings.java b/packages/SystemUI/src/com/android/systemui/power/PowerNotificationWarnings.java
index 8a500c3..71dda2d 100644
--- a/packages/SystemUI/src/com/android/systemui/power/PowerNotificationWarnings.java
+++ b/packages/SystemUI/src/com/android/systemui/power/PowerNotificationWarnings.java
@@ -38,6 +38,7 @@
import android.provider.Settings;
import android.util.Slog;
+import com.android.internal.messages.nano.SystemMessageProto.SystemMessage;
import com.android.systemui.R;
import com.android.systemui.SystemUI;
import com.android.systemui.statusbar.phone.PhoneStatusBar;
@@ -50,7 +51,8 @@
private static final String TAG = PowerUI.TAG + ".Notification";
private static final boolean DEBUG = PowerUI.DEBUG;
- private static final String TAG_NOTIFICATION = "low_battery";
+ private static final String TAG_BATTERY = "low_battery";
+ private static final String TAG_TEMPERATURE = "high_temp";
private static final int SHOWING_NOTHING = 0;
private static final int SHOWING_WARNING = 1;
@@ -65,6 +67,8 @@
private static final String ACTION_SHOW_BATTERY_SETTINGS = "PNW.batterySettings";
private static final String ACTION_START_SAVER = "PNW.startSaver";
private static final String ACTION_DISMISSED_WARNING = "PNW.dismissedWarning";
+ private static final String ACTION_CLICKED_TEMP_WARNING = "PNW.clickedTempWarning";
+ private static final String ACTION_DISMISSED_TEMP_WARNING = "PNW.dismissedTempWarning";
private static final AudioAttributes AUDIO_ATTRIBUTES = new AudioAttributes.Builder()
.setContentType(AudioAttributes.CONTENT_TYPE_SONIFICATION)
@@ -89,6 +93,8 @@
private boolean mPlaySound;
private boolean mInvalidCharger;
private SystemUIDialog mSaverConfirmation;
+ private boolean mTempWarning;
+ private SystemUIDialog mHighTempDialog;
public PowerNotificationWarnings(Context context, NotificationManager notificationManager,
PhoneStatusBar phoneStatusBar) {
@@ -105,6 +111,8 @@
pw.print("mInvalidCharger="); pw.println(mInvalidCharger);
pw.print("mShowing="); pw.println(SHOWING_STRINGS[mShowing]);
pw.print("mSaverConfirmation="); pw.println(mSaverConfirmation != null ? "not null" : null);
+ pw.print("mTempWarning="); pw.println(mTempWarning);
+ pw.print("mHighTempDialog="); pw.println(mHighTempDialog != null ? "not null" : null);
}
@Override
@@ -129,7 +137,8 @@
showWarningNotification();
mShowing = SHOWING_WARNING;
} else {
- mNoMan.cancelAsUser(TAG_NOTIFICATION, R.id.notification_power, UserHandle.ALL);
+ mNoMan.cancelAsUser(TAG_BATTERY, SystemMessage.NOTE_BAD_CHARGER, UserHandle.ALL);
+ mNoMan.cancelAsUser(TAG_BATTERY, SystemMessage.NOTE_POWER_LOW, UserHandle.ALL);
mShowing = SHOWING_NOTHING;
}
}
@@ -148,7 +157,8 @@
com.android.internal.R.color.system_notification_accent_color));
SystemUI.overrideNotificationAppName(mContext, nb);
final Notification n = nb.build();
- mNoMan.notifyAsUser(TAG_NOTIFICATION, R.id.notification_power, n, UserHandle.ALL);
+ mNoMan.cancelAsUser(TAG_BATTERY, SystemMessage.NOTE_POWER_LOW, UserHandle.ALL);
+ mNoMan.notifyAsUser(TAG_BATTERY, SystemMessage.NOTE_BAD_CHARGER, n, UserHandle.ALL);
}
private void showWarningNotification() {
@@ -178,12 +188,9 @@
mPlaySound = false;
}
SystemUI.overrideNotificationAppName(mContext, nb);
- mNoMan.notifyAsUser(TAG_NOTIFICATION, R.id.notification_power, nb.build(), UserHandle.ALL);
- }
-
- private PendingIntent pendingActivity(Intent intent) {
- return PendingIntent.getActivityAsUser(mContext,
- 0, intent, 0, null, UserHandle.CURRENT);
+ final Notification n = nb.build();
+ mNoMan.cancelAsUser(TAG_BATTERY, SystemMessage.NOTE_BAD_CHARGER, UserHandle.ALL);
+ mNoMan.notifyAsUser(TAG_BATTERY, SystemMessage.NOTE_POWER_LOW, n, UserHandle.ALL);
}
private PendingIntent pendingBroadcast(String action) {
@@ -205,6 +212,53 @@
}
@Override
+ public void dismissTemperatureWarning() {
+ if (!mTempWarning) {
+ return;
+ }
+ mTempWarning = false;
+ mNoMan.cancelAsUser(TAG_TEMPERATURE, SystemMessage.NOTE_HIGH_TEMP,
+ UserHandle.ALL);
+ }
+
+ @Override
+ public void showTemperatureWarning() {
+ if (mTempWarning) {
+ return;
+ }
+ mTempWarning = true;
+ final Notification.Builder nb = new Notification.Builder(mContext)
+ .setSmallIcon(R.drawable.ic_device_thermostat_24)
+ .setWhen(0)
+ .setShowWhen(false)
+ .setContentTitle(mContext.getString(R.string.high_temp_title))
+ .setContentText(mContext.getString(R.string.high_temp_notif_message))
+ .setPriority(Notification.PRIORITY_HIGH)
+ .setVisibility(Notification.VISIBILITY_PUBLIC)
+ .setContentIntent(pendingBroadcast(ACTION_CLICKED_TEMP_WARNING))
+ .setDeleteIntent(pendingBroadcast(ACTION_DISMISSED_TEMP_WARNING))
+ .setColor(mContext.getColor(
+ com.android.internal.R.color.battery_saver_mode_color));
+ SystemUI.overrideNotificationAppName(mContext, nb);
+ final Notification n = nb.build();
+ mNoMan.notifyAsUser(TAG_TEMPERATURE, SystemMessage.NOTE_HIGH_TEMP, n, UserHandle.ALL);
+
+ }
+
+ private void showTemperatureDialog() {
+ if (mHighTempDialog != null) return;
+ final SystemUIDialog d = new SystemUIDialog(mContext);
+ d.setIconAttribute(android.R.attr.alertDialogIcon);
+ d.setTitle(R.string.high_temp_title);
+ d.setMessage(R.string.high_temp_dialog_message);
+ d.setPositiveButton(com.android.internal.R.string.ok, null);
+ d.setShowForAllUsers(true);
+ d.setOnDismissListener(dialog -> mHighTempDialog = null);
+ d.show();
+ mHighTempDialog = d;
+ }
+
+ @Override
public void updateLowBatteryWarning() {
updateNotification();
}
@@ -317,6 +371,8 @@
filter.addAction(ACTION_SHOW_BATTERY_SETTINGS);
filter.addAction(ACTION_START_SAVER);
filter.addAction(ACTION_DISMISSED_WARNING);
+ filter.addAction(ACTION_CLICKED_TEMP_WARNING);
+ filter.addAction(ACTION_DISMISSED_TEMP_WARNING);
mContext.registerReceiverAsUser(this, UserHandle.ALL, filter,
android.Manifest.permission.STATUS_BAR_SERVICE, mHandler);
}
@@ -333,6 +389,11 @@
showStartSaverConfirmation();
} else if (action.equals(ACTION_DISMISSED_WARNING)) {
dismissLowBatteryWarning();
+ } else if (ACTION_CLICKED_TEMP_WARNING.equals(action)) {
+ dismissTemperatureWarning();
+ showTemperatureDialog();
+ } else if (ACTION_DISMISSED_TEMP_WARNING.equals(action)) {
+ dismissTemperatureWarning();
}
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/power/PowerUI.java b/packages/SystemUI/src/com/android/systemui/power/PowerUI.java
index b651f2d9..8988801 100644
--- a/packages/SystemUI/src/com/android/systemui/power/PowerUI.java
+++ b/packages/SystemUI/src/com/android/systemui/power/PowerUI.java
@@ -25,12 +25,15 @@
import android.database.ContentObserver;
import android.os.BatteryManager;
import android.os.Handler;
+import android.os.HardwarePropertiesManager;
import android.os.PowerManager;
import android.os.SystemClock;
import android.os.UserHandle;
import android.provider.Settings;
+import android.text.format.DateUtils;
import android.util.Log;
import android.util.Slog;
+import com.android.systemui.R;
import com.android.systemui.SystemUI;
import com.android.systemui.statusbar.phone.PhoneStatusBar;
import java.io.FileDescriptor;
@@ -40,11 +43,13 @@
public class PowerUI extends SystemUI {
static final String TAG = "PowerUI";
static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG);
+ private static final long TEMPERATURE_INTERVAL = 30 * DateUtils.SECOND_IN_MILLIS;
private final Handler mHandler = new Handler();
private final Receiver mReceiver = new Receiver();
private PowerManager mPowerManager;
+ private HardwarePropertiesManager mHardwarePropertiesManager;
private WarningsUI mWarnings;
private int mBatteryLevel = 100;
private int mBatteryStatus = BatteryManager.BATTERY_STATUS_UNKNOWN;
@@ -56,8 +61,12 @@
private long mScreenOffTime = -1;
+ private float mThrottlingTemp;
+
public void start() {
mPowerManager = (PowerManager) mContext.getSystemService(Context.POWER_SERVICE);
+ mHardwarePropertiesManager = (HardwarePropertiesManager)
+ mContext.getSystemService(Context.HARDWARE_PROPERTIES_SERVICE);
mScreenOffTime = mPowerManager.isScreenOn() ? -1 : SystemClock.elapsedRealtime();
mWarnings = new PowerNotificationWarnings(
mContext,
@@ -76,6 +85,8 @@
false, obs, UserHandle.USER_ALL);
updateBatteryWarningLevels();
mReceiver.init();
+
+ initTemperatureWarning();
}
void updateBatteryWarningLevels() {
@@ -136,8 +147,6 @@
filter.addAction(Intent.ACTION_SCREEN_OFF);
filter.addAction(Intent.ACTION_SCREEN_ON);
filter.addAction(Intent.ACTION_USER_SWITCHED);
- filter.addAction(PowerManager.ACTION_POWER_SAVE_MODE_CHANGING);
- filter.addAction(PowerManager.ACTION_POWER_SAVE_MODE_CHANGED);
mContext.registerReceiver(this, filter, null, mHandler);
}
@@ -211,6 +220,57 @@
}
};
+ private void initTemperatureWarning() {
+ if (!mContext.getResources().getBoolean(R.bool.config_showTemperatureWarning)) {
+ return;
+ }
+
+ mThrottlingTemp = mContext.getResources().getInteger(R.integer.config_warningTemperature);
+
+ if (mThrottlingTemp < 0f) {
+ // Get the throttling temperature. No need to check if we're not throttling.
+ float[] throttlingTemps = mHardwarePropertiesManager.getDeviceTemperatures(
+ HardwarePropertiesManager.DEVICE_TEMPERATURE_SKIN,
+ HardwarePropertiesManager.TEMPERATURE_THROTTLING);
+ if (throttlingTemps == null
+ || throttlingTemps.length == 0
+ || throttlingTemps[0] == HardwarePropertiesManager.UNDEFINED_TEMPERATURE) {
+ return;
+ }
+ mThrottlingTemp = throttlingTemps[0];
+ }
+
+ // We have passed all of the checks, start checking the temp
+ updateTemperatureWarning();
+ }
+
+ private void updateTemperatureWarning() {
+ PhoneStatusBar phoneStatusBar = getComponent(PhoneStatusBar.class);
+ if (phoneStatusBar != null && phoneStatusBar.isDeviceInVrMode()) {
+ // ensure the warning isn't showing, since VR shows its own warning
+ mWarnings.dismissTemperatureWarning();
+ } else {
+ float[] temps = mHardwarePropertiesManager.getDeviceTemperatures(
+ HardwarePropertiesManager.DEVICE_TEMPERATURE_SKIN,
+ HardwarePropertiesManager.TEMPERATURE_CURRENT);
+ boolean shouldShowTempWarning = false;
+ for (float temp : temps) {
+ if (temp >= mThrottlingTemp) {
+ shouldShowTempWarning = true;
+ break;
+ }
+ }
+ if (shouldShowTempWarning) {
+ mWarnings.showTemperatureWarning();
+ } else {
+ mWarnings.dismissTemperatureWarning();
+ }
+ }
+
+ // TODO: skip this when in VR mode since we already get a callback
+ mHandler.postDelayed(this::updateTemperatureWarning, TEMPERATURE_INTERVAL);
+ }
+
public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
pw.print("mLowBatteryAlertCloseLevel=");
pw.println(mLowBatteryAlertCloseLevel);
@@ -237,6 +297,8 @@
Settings.Global.LOW_BATTERY_SOUND_TIMEOUT, 0));
pw.print("bucket: ");
pw.println(Integer.toString(findBatteryLevelBucket(mBatteryLevel)));
+ pw.print("mThrottlingTemp=");
+ pw.println(Float.toString(mThrottlingTemp));
mWarnings.dump(pw);
}
@@ -248,6 +310,8 @@
void showInvalidChargerWarning();
void updateLowBatteryWarning();
boolean isInvalidChargerWarningShowing();
+ void dismissTemperatureWarning();
+ void showTemperatureWarning();
void dump(PrintWriter pw);
void userSwitched();
}
diff --git a/packages/SystemUI/src/com/android/systemui/qs/DataUsageGraph.java b/packages/SystemUI/src/com/android/systemui/qs/DataUsageGraph.java
index 5f23a40..047e0d1 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/DataUsageGraph.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/DataUsageGraph.java
@@ -45,10 +45,10 @@
public DataUsageGraph(Context context, AttributeSet attrs) {
super(context, attrs);
final Resources res = context.getResources();
- mTrackColor = context.getColor(R.color.data_usage_graph_track);
+ mTrackColor = Utils.getDefaultColor(context, R.color.data_usage_graph_track);
+ mWarningColor = Utils.getDefaultColor(context, R.color.data_usage_graph_warning);
mUsageColor = Utils.getColorAccent(context);
- mOverlimitColor = context.getColor(R.color.system_warning_color);
- mWarningColor = context.getColor(R.color.data_usage_graph_warning);
+ mOverlimitColor = Utils.getColorError(context);
mMarkerWidth = res.getDimensionPixelSize(R.dimen.data_usage_graph_marker_width);
}
diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSFooter.java b/packages/SystemUI/src/com/android/systemui/qs/QSFooter.java
index 03cd959..b91800a6 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/QSFooter.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/QSFooter.java
@@ -196,6 +196,9 @@
profileVpn, deviceOwnerOrganization, hasProfileOwner, isBranded);
if (deviceOwnerPackage == null) {
mDialog.setMessage(msg);
+ if (mSecurityController.isVpnEnabled() && !mSecurityController.isVpnRestricted()) {
+ mDialog.setButton(DialogInterface.BUTTON_NEGATIVE, getSettingsButton(), this);
+ }
} else {
View dialogView = LayoutInflater.from(mContext)
.inflate(R.layout.quick_settings_footer_dialog, null, false);
@@ -213,10 +216,12 @@
final SpannableStringBuilder message = new SpannableStringBuilder();
message.append(mContext.getString(R.string.monitoring_description_do_body_vpn,
primaryVpn));
- message.append(mContext.getString(
- R.string.monitoring_description_vpn_settings_separator));
- message.append(mContext.getString(R.string.monitoring_description_vpn_settings),
- new VpnSpan(), 0);
+ if (!mSecurityController.isVpnRestricted()) {
+ message.append(mContext.getString(
+ R.string.monitoring_description_vpn_settings_separator));
+ message.append(mContext.getString(R.string.monitoring_description_vpn_settings),
+ new VpnSpan(), 0);
+ }
TextView vpnWarning = (TextView) dialogView.findViewById(R.id.vpn_warning);
vpnWarning.setText(message);
diff --git a/packages/SystemUI/src/com/android/systemui/qs/external/CustomTile.java b/packages/SystemUI/src/com/android/systemui/qs/external/CustomTile.java
index 1fcb45b..9e3889b 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/external/CustomTile.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/external/CustomTile.java
@@ -15,6 +15,9 @@
*/
package com.android.systemui.qs.external;
+import static android.view.Display.DEFAULT_DISPLAY;
+import static android.view.WindowManager.LayoutParams.TYPE_QS_DIALOG;
+
import android.app.ActivityManager;
import android.content.ComponentName;
import android.content.Context;
@@ -24,7 +27,6 @@
import android.content.pm.ResolveInfo;
import android.content.pm.ServiceInfo;
import android.graphics.drawable.Drawable;
-import android.graphics.drawable.Icon;
import android.net.Uri;
import android.os.Binder;
import android.os.IBinder;
@@ -37,19 +39,14 @@
import android.text.style.ForegroundColorSpan;
import android.util.Log;
import android.view.IWindowManager;
-import android.view.WindowManager;
import android.view.WindowManagerGlobal;
import com.android.internal.logging.MetricsLogger;
import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
-import com.android.systemui.R;
import com.android.systemui.qs.QSTile;
import com.android.systemui.qs.external.TileLifecycleManager.TileChangeListener;
import com.android.systemui.statusbar.phone.QSTileHost;
import libcore.util.Objects;
-import static android.view.Display.DEFAULT_DISPLAY;
-import static android.view.WindowManager.LayoutParams.TYPE_QS_DIALOG;
-
public class CustomTile extends QSTile<QSTile.State> implements TileChangeListener {
public static final String PREFIX = "custom(";
@@ -301,7 +298,7 @@
tileState = Tile.STATE_UNAVAILABLE;
drawable = mDefaultIcon.loadDrawable(mAppContext);
}
- int color = mContext.getColor(getColor(tileState));
+ final int color = TileColorPicker.getInstance(mContext).getColor(tileState);
drawable.setTint(color);
state.icon = mHasRes ? new DrawableIconWithRes(drawable, icon.getResId())
: new DrawableIcon(drawable);
@@ -335,18 +332,6 @@
});
}
- private static int getColor(int state) {
- switch (state) {
- case Tile.STATE_UNAVAILABLE:
- return R.color.qs_tile_tint_unavailable;
- case Tile.STATE_INACTIVE:
- return R.color.qs_tile_tint_inactive;
- case Tile.STATE_ACTIVE:
- return R.color.qs_tile_tint_active;
- }
- return 0;
- }
-
public static String toSpec(ComponentName name) {
return PREFIX + name.flattenToShortString() + ")";
}
diff --git a/packages/SystemUI/src/com/android/systemui/qs/external/TileColorPicker.java b/packages/SystemUI/src/com/android/systemui/qs/external/TileColorPicker.java
new file mode 100644
index 0000000..0cc17ff
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/qs/external/TileColorPicker.java
@@ -0,0 +1,60 @@
+/*
+ * Copyright (C) 2016 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.external;
+
+import android.content.Context;
+import android.content.res.ColorStateList;
+import android.service.quicksettings.Tile;
+import android.support.annotation.VisibleForTesting;
+import com.android.systemui.R;
+
+public class TileColorPicker {
+ @VisibleForTesting static final int[] DISABLE_STATE_SET = {-android.R.attr.state_enabled};
+ @VisibleForTesting static final int[] ENABLE_STATE_SET = {android.R.attr.state_enabled,
+ android.R.attr.state_activated};
+ @VisibleForTesting static final int[] INACTIVE_STATE_SET = {-android.R.attr.state_activated};
+ private static TileColorPicker sInstance;
+
+ private ColorStateList mColorStateList;
+
+ private TileColorPicker(Context context) {
+ mColorStateList = context.getResources().
+ getColorStateList(R.color.tint_color_selector, context.getTheme());
+ }
+
+ public static TileColorPicker getInstance(Context context) {
+ if (sInstance == null) {
+ sInstance = new TileColorPicker(context);
+ }
+ return sInstance;
+ }
+
+ public int getColor(int state) {
+ final int defaultColor = 0;
+
+ switch (state) {
+ case Tile.STATE_UNAVAILABLE:
+ return mColorStateList.getColorForState(DISABLE_STATE_SET, defaultColor);
+ case Tile.STATE_INACTIVE:
+ return mColorStateList.getColorForState(INACTIVE_STATE_SET, defaultColor);
+ case Tile.STATE_ACTIVE:
+ return mColorStateList.getColorForState(ENABLE_STATE_SET, defaultColor);
+ default:
+ return mColorStateList.getColorForState(ENABLE_STATE_SET, defaultColor);
+ }
+ }
+
+}
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/BatteryTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/BatteryTile.java
index fc1c1ac..87b00a7 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/BatteryTile.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/BatteryTile.java
@@ -19,7 +19,10 @@
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
+import android.graphics.PorterDuff.Mode;
+import android.graphics.PorterDuffColorFilter;
import android.graphics.drawable.Drawable;
+import android.service.quicksettings.Tile;
import android.text.SpannableStringBuilder;
import android.text.Spanned;
import android.text.style.RelativeSizeSpan;
@@ -40,6 +43,7 @@
import com.android.systemui.R;
import com.android.systemui.plugins.qs.QS.DetailAdapter;
import com.android.systemui.qs.QSTile;
+import com.android.systemui.qs.external.TileColorPicker;
import com.android.systemui.statusbar.policy.BatteryController;
import java.text.NumberFormat;
@@ -120,6 +124,8 @@
context.getColor(R.color.batterymeter_frame_color));
drawable.onBatteryLevelChanged(mLevel, mPluggedIn, mCharging);
drawable.onPowerSaveChanged(mPowerSave);
+ final int color = TileColorPicker.getInstance(context).getColor(Tile.STATE_ACTIVE);
+ drawable.setColorFilter(new PorterDuffColorFilter(color, Mode.SRC_IN));
return drawable;
}
@@ -205,6 +211,11 @@
mDrawable.onBatteryLevelChanged(100, false, false);
mDrawable.onPowerSaveChanged(true);
mDrawable.disableShowPercent();
+
+ final int color = TileColorPicker.getInstance(mCurrentView.getContext())
+ .getColor(Tile.STATE_ACTIVE);
+ mDrawable.setColorFilter(new PorterDuffColorFilter(color, Mode.SRC_IN));
+
((ImageView) mCurrentView.findViewById(android.R.id.icon)).setImageDrawable(mDrawable);
Checkable checkbox = (Checkable) mCurrentView.findViewById(android.R.id.toggle);
checkbox.setChecked(mPowerSave);
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/FlashlightTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/FlashlightTile.java
index 5b1638f..d86aebf 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/FlashlightTile.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/FlashlightTile.java
@@ -20,6 +20,7 @@
import android.content.Intent;
import android.graphics.drawable.Drawable;
import android.provider.MediaStore;
+import android.service.quicksettings.Tile;
import android.text.SpannableStringBuilder;
import android.text.style.ForegroundColorSpan;
import android.widget.Switch;
@@ -28,6 +29,7 @@
import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
import com.android.systemui.R;
import com.android.systemui.qs.QSTile;
+import com.android.systemui.qs.external.TileColorPicker;
import com.android.systemui.statusbar.policy.FlashlightController;
/** Quick settings tile: Control flashlight **/
@@ -104,7 +106,8 @@
if (!mFlashlightController.isAvailable()) {
Drawable icon = mHost.getContext().getDrawable(R.drawable.ic_signal_flashlight_disable)
.mutate();
- final int disabledColor = mHost.getContext().getColor(R.color.qs_tile_tint_unavailable);
+ final int disabledColor = TileColorPicker.getInstance(mContext)
+ .getColor(Tile.STATE_UNAVAILABLE);
icon.setTint(disabledColor);
state.icon = new DrawableIcon(icon);
state.label = new SpannableStringBuilder().append(state.label,
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/HotspotTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/HotspotTile.java
index dcee659..99485bb 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/HotspotTile.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/HotspotTile.java
@@ -22,6 +22,7 @@
import android.provider.Settings;
import android.provider.Settings.Global;
+import android.service.quicksettings.Tile;
import android.text.SpannableStringBuilder;
import android.text.style.ForegroundColorSpan;
import android.widget.Switch;
@@ -31,6 +32,7 @@
import com.android.systemui.R;
import com.android.systemui.qs.GlobalSetting;
import com.android.systemui.qs.QSTile;
+import com.android.systemui.qs.external.TileColorPicker;
import com.android.systemui.statusbar.policy.HotspotController;
/** Quick settings tile: Hotspot **/
@@ -124,7 +126,8 @@
boolean wasAirplane = state.isAirplaneMode;
state.isAirplaneMode = mAirplaneMode.getValue() != 0;
if (state.isAirplaneMode) {
- final int disabledColor = mHost.getContext().getColor(R.color.qs_tile_tint_unavailable);
+ final int disabledColor = TileColorPicker.getInstance(mContext)
+ .getColor(Tile.STATE_UNAVAILABLE);
state.label = new SpannableStringBuilder().append(state.label,
new ForegroundColorSpan(disabledColor),
SpannableStringBuilder.SPAN_INCLUSIVE_INCLUSIVE);
diff --git a/packages/SystemUI/src/com/android/systemui/recents/model/RecentsTaskLoadPlan.java b/packages/SystemUI/src/com/android/systemui/recents/model/RecentsTaskLoadPlan.java
index 5877440..5c7496d 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/model/RecentsTaskLoadPlan.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/model/RecentsTaskLoadPlan.java
@@ -38,6 +38,7 @@
import com.android.systemui.recents.RecentsDebugFlags;
import com.android.systemui.recents.misc.SystemServicesProxy;
+import com.android.systemui.recents.views.grid.TaskGridLayoutAlgorithm;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
@@ -150,11 +151,19 @@
Task.TaskKey taskKey = new Task.TaskKey(t.persistentId, t.stackId, t.baseIntent,
t.userId, t.firstActiveTime, t.lastActiveTime);
- // This task is only shown in the stack if it statisfies the historical time or min
+ // This task is only shown in the stack if it satisfies the historical time or min
// number of tasks constraints. Freeform tasks are also always shown.
boolean isFreeformTask = SystemServicesProxy.isFreeformStack(t.stackId);
- boolean isStackTask = isFreeformTask || !isHistoricalTask(t) ||
+ boolean isStackTask;
+ if (Recents.getConfiguration().isGridEnabled) {
+ // When grid layout is enabled, we only show the first
+ // TaskGridLayoutAlgorithm.MAX_LAYOUT_TASK_COUNT} tasks.
+ isStackTask = t.lastActiveTime >= lastStackActiveTime &&
+ i >= taskCount - TaskGridLayoutAlgorithm.MAX_LAYOUT_TASK_COUNT;
+ } else {
+ isStackTask = isFreeformTask || !isHistoricalTask(t) ||
(t.lastActiveTime >= lastStackActiveTime && i >= (taskCount - MIN_NUM_TASKS));
+ }
boolean isLaunchTarget = taskKey.id == runningTaskId;
// The last stack active time is the baseline for which we show visible tasks. Since
diff --git a/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackView.java b/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackView.java
index 760bf54..1f2007a 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackView.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackView.java
@@ -2192,6 +2192,11 @@
mFocusedTask.dump("", writer);
}
+ int numTaskViews = mTaskViews.size();
+ for (int i = 0; i < numTaskViews; i++) {
+ mTaskViews.get(i).dump(innerPrefix, writer);
+ }
+
mLayoutAlgorithm.dump(innerPrefix, writer);
mStackScroller.dump(innerPrefix, writer);
}
diff --git a/packages/SystemUI/src/com/android/systemui/recents/views/TaskView.java b/packages/SystemUI/src/com/android/systemui/recents/views/TaskView.java
index 2f4ad6a4d..36d5f83 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/views/TaskView.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/views/TaskView.java
@@ -58,6 +58,7 @@
import com.android.systemui.recents.model.Task;
import com.android.systemui.recents.model.TaskStack;
+import java.io.PrintWriter;
import java.util.ArrayList;
/**
@@ -715,4 +716,14 @@
setClipViewInStack(true);
});
}
+
+ public void dump(String prefix, PrintWriter writer) {
+ String innerPrefix = prefix + " ";
+
+ writer.print(prefix); writer.print("TaskView");
+ writer.print(" mTask="); writer.print(mTask.key.id);
+ writer.println();
+
+ mThumbnailView.dump(innerPrefix, writer);
+ }
}
diff --git a/packages/SystemUI/src/com/android/systemui/recents/views/TaskViewThumbnail.java b/packages/SystemUI/src/com/android/systemui/recents/views/TaskViewThumbnail.java
index d109807..58b929a 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/views/TaskViewThumbnail.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/views/TaskViewThumbnail.java
@@ -35,8 +35,11 @@
import android.view.ViewDebug;
import com.android.systemui.R;
+import com.android.systemui.recents.misc.Utilities;
import com.android.systemui.recents.model.Task;
+import java.io.PrintWriter;
+
/**
* The task thumbnail view. It implements an image view that allows for animating the dim and
@@ -343,4 +346,15 @@
mTask = null;
setThumbnail(null, null);
}
+
+ public void dump(String prefix, PrintWriter writer) {
+ String innerPrefix = prefix + " ";
+
+ writer.print(prefix); writer.print("TaskViewThumbnail");
+ writer.print(" mTaskViewRect="); writer.print(Utilities.dumpRect(mTaskViewRect));
+ writer.print(" mThumbnailRect="); writer.print(Utilities.dumpRect(mThumbnailRect));
+ writer.print(" mThumbnailScale="); writer.print(mThumbnailScale);
+ writer.print(" mDimAlpha="); writer.print(mDimAlpha);
+ writer.println();
+ }
}
diff --git a/packages/SystemUI/src/com/android/systemui/recents/views/grid/TaskGridLayoutAlgorithm.java b/packages/SystemUI/src/com/android/systemui/recents/views/grid/TaskGridLayoutAlgorithm.java
index be3af040..046ced4 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/views/grid/TaskGridLayoutAlgorithm.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/views/grid/TaskGridLayoutAlgorithm.java
@@ -30,7 +30,7 @@
public class TaskGridLayoutAlgorithm {
private final String TAG = "TaskGridLayoutAlgorithm";
- private final int MAX_LAYOUT_TASK_COUNT = 8;
+ public static final int MAX_LAYOUT_TASK_COUNT = 8;
/** The horizontal padding around the whole recents view. */
private int mPaddingLeftRight;
@@ -135,6 +135,16 @@
updateAppAspectRatio();
}
+ /**
+ * Returns the proper task view transform of a certain task view, according to its index and the
+ * amount of task views.
+ * @param taskIndex The index of the task view whose transform we want. It's never greater
+ * than {@link MAX_LAYOUT_TASK_COUNT}.
+ * @param taskCount The current amount of task views.
+ * @param transformOut The result transform that this method returns.
+ * @param stackLayout The base stack layout algorithm.
+ * @return The expected transform of the (taskIndex)th task view.
+ */
public TaskViewTransform getTransform(int taskIndex, int taskCount,
TaskViewTransform transformOut, TaskStackLayoutAlgorithm stackLayout) {
diff --git a/packages/SystemUI/src/com/android/systemui/screenshot/GlobalScreenshot.java b/packages/SystemUI/src/com/android/systemui/screenshot/GlobalScreenshot.java
index 0eef864..db021ff 100644
--- a/packages/SystemUI/src/com/android/systemui/screenshot/GlobalScreenshot.java
+++ b/packages/SystemUI/src/com/android/systemui/screenshot/GlobalScreenshot.java
@@ -59,6 +59,7 @@
import android.view.animation.Interpolator;
import android.widget.ImageView;
+import com.android.internal.messages.nano.SystemMessageProto.SystemMessage;
import com.android.systemui.R;
import com.android.systemui.SystemUI;
@@ -201,7 +202,8 @@
mNotificationBuilder.setFlag(Notification.FLAG_NO_CLEAR, true);
SystemUI.overrideNotificationAppName(context, mNotificationBuilder);
- mNotificationManager.notify(R.id.notification_screenshot, mNotificationBuilder.build());
+ mNotificationManager.notify(SystemMessage.NOTE_GLOBAL_SCREENSHOT,
+ mNotificationBuilder.build());
/**
* NOTE: The following code prepares the notification builder for updating the notification
@@ -348,7 +350,8 @@
.setPublicVersion(mPublicNotificationBuilder.build())
.setFlag(Notification.FLAG_NO_CLEAR, false);
- mNotificationManager.notify(R.id.notification_screenshot, mNotificationBuilder.build());
+ mNotificationManager.notify(SystemMessage.NOTE_GLOBAL_SCREENSHOT,
+ mNotificationBuilder.build());
}
mParams.finisher.run();
mParams.clearContext();
@@ -364,7 +367,7 @@
mParams.clearContext();
// Cancel the posted notification
- mNotificationManager.cancel(R.id.notification_screenshot);
+ mNotificationManager.cancel(SystemMessage.NOTE_GLOBAL_SCREENSHOT);
}
}
@@ -866,7 +869,7 @@
Notification n = new Notification.BigTextStyle(b)
.bigText(errorMsg)
.build();
- nManager.notify(R.id.notification_screenshot, n);
+ nManager.notify(SystemMessage.NOTE_GLOBAL_SCREENSHOT, n);
}
/**
@@ -878,7 +881,7 @@
// Clear the notification
final NotificationManager nm =
(NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE);
- nm.cancel(R.id.notification_screenshot);
+ nm.cancel(SystemMessage.NOTE_GLOBAL_SCREENSHOT);
}
}
@@ -896,7 +899,7 @@
final NotificationManager nm =
(NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE);
final Uri uri = Uri.parse(intent.getStringExtra(SCREENSHOT_URI_ID));
- nm.cancel(R.id.notification_screenshot);
+ nm.cancel(SystemMessage.NOTE_GLOBAL_SCREENSHOT);
// And delete the image from the media store
new DeleteImageInBackgroundTask(context).execute(uri);
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java b/packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java
index 80b43e6..db099bc 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java
@@ -42,7 +42,6 @@
import android.content.res.Configuration;
import android.database.ContentObserver;
import android.graphics.Rect;
-import android.graphics.drawable.Drawable;
import android.os.AsyncTask;
import android.os.Build;
import android.os.Bundle;
@@ -80,13 +79,13 @@
import android.view.WindowManager;
import android.view.WindowManagerGlobal;
import android.view.accessibility.AccessibilityManager;
-import android.widget.ImageView;
import android.widget.RemoteViews;
import android.widget.TextView;
import android.widget.Toast;
import com.android.internal.logging.MetricsLogger;
import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
+import com.android.internal.messages.nano.SystemMessageProto.SystemMessage;
import com.android.internal.statusbar.IStatusBarService;
import com.android.internal.statusbar.StatusBarIcon;
import com.android.internal.widget.LockPatternUtils;
@@ -544,7 +543,7 @@
} else if (BANNER_ACTION_CANCEL.equals(action) || BANNER_ACTION_SETUP.equals(action)) {
NotificationManager noMan = (NotificationManager)
mContext.getSystemService(Context.NOTIFICATION_SERVICE);
- noMan.cancel(R.id.notification_hidden);
+ noMan.cancel(SystemMessage.NOTE_HIDDEN_NOTIFICATIONS);
Settings.Secure.putInt(mContext.getContentResolver(),
Settings.Secure.SHOW_NOTE_ABOUT_NOTIFICATION_HIDING, 0);
@@ -753,7 +752,8 @@
mLockPatternUtils = new LockPatternUtils(mContext);
// Connect in to the status bar manager service
- mCommandQueue = new CommandQueue(this);
+ mCommandQueue = getComponent(CommandQueue.class);
+ mCommandQueue.addCallbacks(this);
int[] switches = new int[9];
ArrayList<IBinder> binders = new ArrayList<IBinder>();
@@ -885,7 +885,7 @@
NotificationManager noMan =
(NotificationManager) mContext.getSystemService(Context.NOTIFICATION_SERVICE);
- noMan.notify(R.id.notification_hidden, note.build());
+ noMan.notify(SystemMessage.NOTE_HIDDEN_NOTIFICATIONS, note.build());
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/CommandQueue.java b/packages/SystemUI/src/com/android/systemui/statusbar/CommandQueue.java
index 419c91b..a3e4d5b 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/CommandQueue.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/CommandQueue.java
@@ -21,13 +21,16 @@
import android.os.Bundle;
import android.os.Handler;
import android.os.IBinder;
+import android.os.Looper;
import android.os.Message;
+import android.support.annotation.VisibleForTesting;
import android.util.Pair;
import android.view.KeyEvent;
import com.android.internal.os.SomeArgs;
import com.android.internal.statusbar.IStatusBar;
import com.android.internal.statusbar.StatusBarIcon;
+import com.android.systemui.SystemUI;
/**
* This class takes the functions from IStatusBar that come in on
@@ -88,55 +91,68 @@
private static final String SHOW_IME_SWITCHER_KEY = "showImeSwitcherKey";
private final Object mLock = new Object();
- private Callbacks mCallbacks;
- private Handler mHandler = new H();
+ private Callbacks[] mCallbacks = new Callbacks[0];
+ private Handler mHandler = new H(Looper.getMainLooper());
/**
* These methods are called back on the main thread.
*/
public interface Callbacks {
- void setIcon(String slot, StatusBarIcon icon);
- void removeIcon(String slot);
- void disable(int state1, int state2, boolean animate);
- void animateExpandNotificationsPanel();
- void animateCollapsePanels(int flags);
- void animateExpandSettingsPanel(String obj);
- void setSystemUiVisibility(int vis, int fullscreenStackVis,
- int dockedStackVis, int mask, Rect fullscreenStackBounds, Rect dockedStackBounds);
- void topAppWindowChanged(boolean visible);
- void setImeWindowStatus(IBinder token, int vis, int backDisposition,
- boolean showImeSwitcher);
- void showRecentApps(boolean triggeredFromAltTab, boolean fromHome);
- void hideRecentApps(boolean triggeredFromAltTab, boolean triggeredFromHomeKey);
- void toggleRecentApps();
- void toggleSplitScreen();
- void preloadRecentApps();
- void dismissKeyboardShortcutsMenu();
- void toggleKeyboardShortcutsMenu(int deviceId);
- void cancelPreloadRecentApps();
- void setWindowState(int window, int state);
- void buzzBeepBlinked();
- void notificationLightOff();
- void notificationLightPulse(int argb, int onMillis, int offMillis);
- void showScreenPinningRequest(int taskId);
- void appTransitionPending();
- void appTransitionCancelled();
- void appTransitionStarting(long startTime, long duration);
- void appTransitionFinished();
- void showAssistDisclosure();
- void startAssist(Bundle args);
- void onCameraLaunchGestureDetected(int source);
- void showTvPictureInPictureMenu();
+ default void setIcon(String slot, StatusBarIcon icon) { }
+ default void removeIcon(String slot) { }
+ default void disable(int state1, int state2, boolean animate) { }
+ default void animateExpandNotificationsPanel() { }
+ default void animateCollapsePanels(int flags) { }
+ default void animateExpandSettingsPanel(String obj) { }
+ default void setSystemUiVisibility(int vis, int fullscreenStackVis,
+ int dockedStackVis, int mask, Rect fullscreenStackBounds, Rect dockedStackBounds) {
+ }
+ default void topAppWindowChanged(boolean visible) { }
+ default void setImeWindowStatus(IBinder token, int vis, int backDisposition,
+ boolean showImeSwitcher) { }
+ default void showRecentApps(boolean triggeredFromAltTab, boolean fromHome) { }
+ default void hideRecentApps(boolean triggeredFromAltTab, boolean triggeredFromHomeKey) { }
+ default void toggleRecentApps() { }
+ default void toggleSplitScreen() { }
+ default void preloadRecentApps() { }
+ default void dismissKeyboardShortcutsMenu() { }
+ default void toggleKeyboardShortcutsMenu(int deviceId) { }
+ default void cancelPreloadRecentApps() { }
+ default void setWindowState(int window, int state) { }
+ default void buzzBeepBlinked() { }
+ default void notificationLightOff() { }
+ default void notificationLightPulse(int argb, int onMillis, int offMillis) { }
+ default void showScreenPinningRequest(int taskId) { }
+ default void appTransitionPending() { }
+ default void appTransitionCancelled() { }
+ default void appTransitionStarting(long startTime, long duration) { }
+ default void appTransitionFinished() { }
+ default void showAssistDisclosure() { }
+ default void startAssist(Bundle args) { }
+ default void onCameraLaunchGestureDetected(int source) { }
+ default void showTvPictureInPictureMenu() { }
- void addQsTile(ComponentName tile);
- void remQsTile(ComponentName tile);
- void clickTile(ComponentName tile);
+ default void addQsTile(ComponentName tile) { }
+ default void remQsTile(ComponentName tile) { }
+ default void clickTile(ComponentName tile) { }
- void handleSystemNavigationKey(int arg1);
+ default void handleSystemNavigationKey(int arg1) { }
}
- public CommandQueue(Callbacks callbacks) {
- mCallbacks = callbacks;
+ @VisibleForTesting
+ protected CommandQueue() {
+ }
+
+ public void addCallbacks(Callbacks callbacks) {
+ Callbacks[] newArray = new Callbacks[mCallbacks.length + 1];
+ for (int i = 0; i < newArray.length - 1; i++) {
+ newArray[i] = mCallbacks[i];
+ if (newArray[i] == callbacks) {
+ throw new IllegalArgumentException("Callback was already added");
+ }
+ }
+ newArray[newArray.length - 1] = callbacks;
+ mCallbacks = newArray;
}
public void setIcon(String slot, StatusBarIcon icon) {
@@ -328,8 +344,8 @@
public void appTransitionCancelled() {
synchronized (mLock) {
- mHandler.removeMessages(MSG_APP_TRANSITION_PENDING);
- mHandler.sendEmptyMessage(MSG_APP_TRANSITION_PENDING);
+ mHandler.removeMessages(MSG_APP_TRANSITION_CANCELLED);
+ mHandler.sendEmptyMessage(MSG_APP_TRANSITION_CANCELLED);
}
}
@@ -400,6 +416,10 @@
}
private final class H extends Handler {
+ private H(Looper l) {
+ super(l);
+ }
+
public void handleMessage(Message msg) {
final int what = msg.what & MSG_MASK;
switch (what) {
@@ -407,118 +427,195 @@
switch (msg.arg1) {
case OP_SET_ICON: {
Pair<String, StatusBarIcon> p = (Pair<String, StatusBarIcon>) msg.obj;
- mCallbacks.setIcon(p.first, p.second);
+ for (int i = 0; i < mCallbacks.length; i++) {
+ mCallbacks[i].setIcon(p.first, p.second);
+ }
break;
}
case OP_REMOVE_ICON:
- mCallbacks.removeIcon((String) msg.obj);
+ for (int i = 0; i < mCallbacks.length; i++) {
+ mCallbacks[i].removeIcon((String) msg.obj);
+ }
break;
}
break;
}
case MSG_DISABLE:
- mCallbacks.disable(msg.arg1, msg.arg2, true /* animate */);
+ for (int i = 0; i < mCallbacks.length; i++) {
+ mCallbacks[i].disable(msg.arg1, msg.arg2, true /* animate */);
+ }
break;
case MSG_EXPAND_NOTIFICATIONS:
- mCallbacks.animateExpandNotificationsPanel();
+ for (int i = 0; i < mCallbacks.length; i++) {
+ mCallbacks[i].animateExpandNotificationsPanel();
+ }
break;
case MSG_COLLAPSE_PANELS:
- mCallbacks.animateCollapsePanels(0);
+ for (int i = 0; i < mCallbacks.length; i++) {
+ mCallbacks[i].animateCollapsePanels(0);
+ }
break;
case MSG_EXPAND_SETTINGS:
- mCallbacks.animateExpandSettingsPanel((String) msg.obj);
+ for (int i = 0; i < mCallbacks.length; i++) {
+ mCallbacks[i].animateExpandSettingsPanel((String) msg.obj);
+ }
break;
case MSG_SET_SYSTEMUI_VISIBILITY:
SomeArgs args = (SomeArgs) msg.obj;
- mCallbacks.setSystemUiVisibility(args.argi1, args.argi2, args.argi3,
- args.argi4, (Rect) args.arg1, (Rect) args.arg2);
+ for (int i = 0; i < mCallbacks.length; i++) {
+ mCallbacks[i].setSystemUiVisibility(args.argi1, args.argi2, args.argi3,
+ args.argi4, (Rect) args.arg1, (Rect) args.arg2);
+ }
args.recycle();
break;
case MSG_TOP_APP_WINDOW_CHANGED:
- mCallbacks.topAppWindowChanged(msg.arg1 != 0);
+ for (int i = 0; i < mCallbacks.length; i++) {
+ mCallbacks[i].topAppWindowChanged(msg.arg1 != 0);
+ }
break;
case MSG_SHOW_IME_BUTTON:
- mCallbacks.setImeWindowStatus((IBinder) msg.obj, msg.arg1, msg.arg2,
- msg.getData().getBoolean(SHOW_IME_SWITCHER_KEY, false));
+ for (int i = 0; i < mCallbacks.length; i++) {
+ mCallbacks[i].setImeWindowStatus((IBinder) msg.obj, msg.arg1, msg.arg2,
+ msg.getData().getBoolean(SHOW_IME_SWITCHER_KEY, false));
+ }
break;
case MSG_SHOW_RECENT_APPS:
- mCallbacks.showRecentApps(msg.arg1 != 0, msg.arg2 != 0);
+ for (int i = 0; i < mCallbacks.length; i++) {
+ mCallbacks[i].showRecentApps(msg.arg1 != 0, msg.arg2 != 0);
+ }
break;
case MSG_HIDE_RECENT_APPS:
- mCallbacks.hideRecentApps(msg.arg1 != 0, msg.arg2 != 0);
+ for (int i = 0; i < mCallbacks.length; i++) {
+ mCallbacks[i].hideRecentApps(msg.arg1 != 0, msg.arg2 != 0);
+ }
break;
case MSG_TOGGLE_RECENT_APPS:
- mCallbacks.toggleRecentApps();
+ for (int i = 0; i < mCallbacks.length; i++) {
+ mCallbacks[i].toggleRecentApps();
+ }
break;
case MSG_PRELOAD_RECENT_APPS:
- mCallbacks.preloadRecentApps();
+ for (int i = 0; i < mCallbacks.length; i++) {
+ mCallbacks[i].preloadRecentApps();
+ }
break;
case MSG_CANCEL_PRELOAD_RECENT_APPS:
- mCallbacks.cancelPreloadRecentApps();
+ for (int i = 0; i < mCallbacks.length; i++) {
+ mCallbacks[i].cancelPreloadRecentApps();
+ }
break;
case MSG_DISMISS_KEYBOARD_SHORTCUTS:
- mCallbacks.dismissKeyboardShortcutsMenu();
+ for (int i = 0; i < mCallbacks.length; i++) {
+ mCallbacks[i].dismissKeyboardShortcutsMenu();
+ }
break;
case MSG_TOGGLE_KEYBOARD_SHORTCUTS:
- mCallbacks.toggleKeyboardShortcutsMenu(msg.arg1);
+ for (int i = 0; i < mCallbacks.length; i++) {
+ mCallbacks[i].toggleKeyboardShortcutsMenu(msg.arg1);
+ }
break;
case MSG_SET_WINDOW_STATE:
- mCallbacks.setWindowState(msg.arg1, msg.arg2);
+ for (int i = 0; i < mCallbacks.length; i++) {
+ mCallbacks[i].setWindowState(msg.arg1, msg.arg2);
+ }
break;
case MSG_BUZZ_BEEP_BLINKED:
- mCallbacks.buzzBeepBlinked();
+ for (int i = 0; i < mCallbacks.length; i++) {
+ mCallbacks[i].buzzBeepBlinked();
+ }
break;
case MSG_NOTIFICATION_LIGHT_OFF:
- mCallbacks.notificationLightOff();
+ for (int i = 0; i < mCallbacks.length; i++) {
+ mCallbacks[i].notificationLightOff();
+ }
break;
case MSG_NOTIFICATION_LIGHT_PULSE:
- mCallbacks.notificationLightPulse((Integer) msg.obj, msg.arg1, msg.arg2);
+ for (int i = 0; i < mCallbacks.length; i++) {
+ mCallbacks[i].notificationLightPulse((Integer) msg.obj, msg.arg1, msg.arg2);
+ }
break;
case MSG_SHOW_SCREEN_PIN_REQUEST:
- mCallbacks.showScreenPinningRequest(msg.arg1);
+ for (int i = 0; i < mCallbacks.length; i++) {
+ mCallbacks[i].showScreenPinningRequest(msg.arg1);
+ }
break;
case MSG_APP_TRANSITION_PENDING:
- mCallbacks.appTransitionPending();
+ for (int i = 0; i < mCallbacks.length; i++) {
+ mCallbacks[i].appTransitionPending();
+ }
break;
case MSG_APP_TRANSITION_CANCELLED:
- mCallbacks.appTransitionCancelled();
+ for (int i = 0; i < mCallbacks.length; i++) {
+ mCallbacks[i].appTransitionCancelled();
+ }
break;
case MSG_APP_TRANSITION_STARTING:
- Pair<Long, Long> data = (Pair<Long, Long>) msg.obj;
- mCallbacks.appTransitionStarting(data.first, data.second);
+ for (int i = 0; i < mCallbacks.length; i++) {
+ Pair<Long, Long> data = (Pair<Long, Long>) msg.obj;
+ mCallbacks[i].appTransitionStarting(data.first, data.second);
+ }
break;
case MSG_APP_TRANSITION_FINISHED:
- mCallbacks.appTransitionFinished();
+ for (int i = 0; i < mCallbacks.length; i++) {
+ mCallbacks[i].appTransitionFinished();
+ }
break;
case MSG_ASSIST_DISCLOSURE:
- mCallbacks.showAssistDisclosure();
+ for (int i = 0; i < mCallbacks.length; i++) {
+ mCallbacks[i].showAssistDisclosure();
+ }
break;
case MSG_START_ASSIST:
- mCallbacks.startAssist((Bundle) msg.obj);
+ for (int i = 0; i < mCallbacks.length; i++) {
+ mCallbacks[i].startAssist((Bundle) msg.obj);
+ }
break;
case MSG_CAMERA_LAUNCH_GESTURE:
- mCallbacks.onCameraLaunchGestureDetected(msg.arg1);
+ for (int i = 0; i < mCallbacks.length; i++) {
+ mCallbacks[i].onCameraLaunchGestureDetected(msg.arg1);
+ }
break;
case MSG_SHOW_TV_PICTURE_IN_PICTURE_MENU:
- mCallbacks.showTvPictureInPictureMenu();
+ for (int i = 0; i < mCallbacks.length; i++) {
+ mCallbacks[i].showTvPictureInPictureMenu();
+ }
break;
case MSG_ADD_QS_TILE:
- mCallbacks.addQsTile((ComponentName) msg.obj);
+ for (int i = 0; i < mCallbacks.length; i++) {
+ mCallbacks[i].addQsTile((ComponentName) msg.obj);
+ }
break;
case MSG_REMOVE_QS_TILE:
- mCallbacks.remQsTile((ComponentName) msg.obj);
+ for (int i = 0; i < mCallbacks.length; i++) {
+ mCallbacks[i].remQsTile((ComponentName) msg.obj);
+ }
break;
case MSG_CLICK_QS_TILE:
- mCallbacks.clickTile((ComponentName) msg.obj);
+ for (int i = 0; i < mCallbacks.length; i++) {
+ mCallbacks[i].clickTile((ComponentName) msg.obj);
+ }
break;
case MSG_TOGGLE_APP_SPLIT_SCREEN:
- mCallbacks.toggleSplitScreen();
+ for (int i = 0; i < mCallbacks.length; i++) {
+ mCallbacks[i].toggleSplitScreen();
+ }
break;
case MSG_HANDLE_SYSNAV_KEY:
- mCallbacks.handleSystemNavigationKey(msg.arg1);
+ for (int i = 0; i < mCallbacks.length; i++) {
+ mCallbacks[i].handleSystemNavigationKey(msg.arg1);
+ }
break;
}
}
}
+
+ // Need this class since CommandQueue already extends IStatusBar.Stub, so CommandQueueStart
+ // is needed so it can extend SystemUI.
+ public static class CommandQueueStart extends SystemUI {
+ @Override
+ public void start() {
+ putComponent(CommandQueue.class, new CommandQueue());
+ }
+ }
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/KeyboardShortcuts.java b/packages/SystemUI/src/com/android/systemui/statusbar/KeyboardShortcuts.java
index f43fc40..bd5fb92 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/KeyboardShortcuts.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/KeyboardShortcuts.java
@@ -381,7 +381,12 @@
if (appShortcuts != null) {
result.add(appShortcuts);
}
- showKeyboardShortcutsDialog(result);
+ synchronized (sLock) {
+ // showKeyboardShortcutsDialog only if it has not been dismissed already
+ if (sInstance != null) {
+ showKeyboardShortcutsDialog(result);
+ }
+ }
}
}, deviceId);
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/ServiceMonitor.java b/packages/SystemUI/src/com/android/systemui/statusbar/ServiceMonitor.java
deleted file mode 100644
index db46dc6..0000000
--- a/packages/SystemUI/src/com/android/systemui/statusbar/ServiceMonitor.java
+++ /dev/null
@@ -1,305 +0,0 @@
-/*
- * Copyright (C) 2013 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.statusbar;
-
-import android.content.BroadcastReceiver;
-import android.content.ComponentName;
-import android.content.ContentResolver;
-import android.content.Context;
-import android.content.Intent;
-import android.content.IntentFilter;
-import android.content.ServiceConnection;
-import android.content.pm.PackageManager;
-import android.database.ContentObserver;
-import android.net.Uri;
-import android.os.Bundle;
-import android.os.Handler;
-import android.os.IBinder;
-import android.os.Message;
-import android.os.RemoteException;
-import android.os.UserHandle;
-import android.provider.Settings;
-import android.util.Log;
-
-import java.util.Arrays;
-
-/**
- * Manages a persistent connection to a service component defined in a secure setting.
- *
- * <p>If a valid service component is specified in the secure setting, starts it up and keeps it
- * running; handling setting changes, package updates, component disabling, and unexpected
- * process termination.
- *
- * <p>Clients can listen for important events using the supplied {@link Callbacks}.
- */
-public class ServiceMonitor {
- private static final int RECHECK_DELAY = 2000;
- private static final int WAIT_FOR_STOP = 500;
-
- public interface Callbacks {
- /** The service does not exist or failed to bind */
- void onNoService();
- /** The service is about to start, this is a chance to perform cleanup and
- * delay the start if necessary */
- long onServiceStartAttempt();
- }
-
- // internal handler + messages used to serialize access to internal state
- public static final int MSG_START_SERVICE = 1;
- public static final int MSG_CONTINUE_START_SERVICE = 2;
- public static final int MSG_STOP_SERVICE = 3;
- public static final int MSG_PACKAGE_INTENT = 4;
- public static final int MSG_CHECK_BOUND = 5;
- public static final int MSG_SERVICE_DISCONNECTED = 6;
-
- private final Handler mHandler = new Handler() {
- public void handleMessage(Message msg) {
- switch(msg.what) {
- case MSG_START_SERVICE:
- startService();
- break;
- case MSG_CONTINUE_START_SERVICE:
- continueStartService();
- break;
- case MSG_STOP_SERVICE:
- stopService();
- break;
- case MSG_PACKAGE_INTENT:
- packageIntent((Intent)msg.obj);
- break;
- case MSG_CHECK_BOUND:
- checkBound();
- break;
- case MSG_SERVICE_DISCONNECTED:
- serviceDisconnected((ComponentName)msg.obj);
- break;
- }
- }
- };
-
- private final ContentObserver mSettingObserver = new ContentObserver(mHandler) {
- public void onChange(boolean selfChange) {
- onChange(selfChange, null);
- }
-
- public void onChange(boolean selfChange, Uri uri) {
- if (mDebug) Log.d(mTag, "onChange selfChange=" + selfChange + " uri=" + uri);
- ComponentName cn = getComponentNameFromSetting();
- if (cn == null && mServiceName == null || cn != null && cn.equals(mServiceName)) {
- if (mDebug) Log.d(mTag, "skipping no-op restart");
- return;
- }
- if (mBound) {
- mHandler.sendEmptyMessage(MSG_STOP_SERVICE);
- }
- mHandler.sendEmptyMessageDelayed(MSG_START_SERVICE, WAIT_FOR_STOP);
- }
- };
-
- private final class SC implements ServiceConnection, IBinder.DeathRecipient {
- private ComponentName mName;
- private IBinder mService;
-
- public void onServiceConnected(ComponentName name, IBinder service) {
- if (mDebug) Log.d(mTag, "onServiceConnected name=" + name + " service=" + service);
- mName = name;
- mService = service;
- try {
- service.linkToDeath(this, 0);
- } catch (RemoteException e) {
- Log.w(mTag, "Error linking to death", e);
- }
- }
-
- public void onServiceDisconnected(ComponentName name) {
- if (mDebug) Log.d(mTag, "onServiceDisconnected name=" + name);
- boolean unlinked = mService.unlinkToDeath(this, 0);
- if (mDebug) Log.d(mTag, " unlinked=" + unlinked);
- mHandler.sendMessage(mHandler.obtainMessage(MSG_SERVICE_DISCONNECTED, mName));
- }
-
- public void binderDied() {
- if (mDebug) Log.d(mTag, "binderDied");
- mHandler.sendMessage(mHandler.obtainMessage(MSG_SERVICE_DISCONNECTED, mName));
- }
- }
-
- private final BroadcastReceiver mBroadcastReceiver = new BroadcastReceiver() {
- public void onReceive(Context context, Intent intent) {
- String pkg = intent.getData().getSchemeSpecificPart();
- if (mServiceName != null && mServiceName.getPackageName().equals(pkg)) {
- mHandler.sendMessage(mHandler.obtainMessage(MSG_PACKAGE_INTENT, intent));
- }
- }
- };
-
- private final String mTag;
- private final boolean mDebug;
-
- private final Context mContext;
- private final String mSettingKey;
- private final Callbacks mCallbacks;
-
- private ComponentName mServiceName;
- private SC mServiceConnection;
- private boolean mBound;
-
- public ServiceMonitor(String ownerTag, boolean debug,
- Context context, String settingKey, Callbacks callbacks) {
- mTag = ownerTag + ".ServiceMonitor";
- mDebug = debug;
- mContext = context;
- mSettingKey = settingKey;
- mCallbacks = callbacks;
- }
-
- public void start() {
- // listen for setting changes
- ContentResolver cr = mContext.getContentResolver();
- cr.registerContentObserver(Settings.Secure.getUriFor(mSettingKey),
- false /*notifyForDescendents*/, mSettingObserver, UserHandle.USER_ALL);
-
- // listen for package/component changes
- IntentFilter filter = new IntentFilter();
- filter.addAction(Intent.ACTION_PACKAGE_ADDED);
- filter.addAction(Intent.ACTION_PACKAGE_CHANGED);
- filter.addAction(Intent.ACTION_PACKAGE_REMOVED);
- filter.addDataScheme("package");
- mContext.registerReceiver(mBroadcastReceiver, filter);
-
- mHandler.sendEmptyMessage(MSG_START_SERVICE);
- }
-
- private ComponentName getComponentNameFromSetting() {
- String cn = Settings.Secure.getStringForUser(mContext.getContentResolver(),
- mSettingKey, UserHandle.USER_CURRENT);
- return cn == null ? null : ComponentName.unflattenFromString(cn);
- }
-
- // everything below is called on the handler
-
- private void packageIntent(Intent intent) {
- if (mDebug) Log.d(mTag, "packageIntent intent=" + intent
- + " extras=" + bundleToString(intent.getExtras()));
- if (Intent.ACTION_PACKAGE_ADDED.equals(intent.getAction())) {
- mHandler.sendEmptyMessage(MSG_START_SERVICE);
- } else if (Intent.ACTION_PACKAGE_CHANGED.equals(intent.getAction())
- || Intent.ACTION_PACKAGE_REMOVED.equals(intent.getAction())) {
- final PackageManager pm = mContext.getPackageManager();
- final boolean serviceEnabled = isPackageAvailable()
- && pm.getApplicationEnabledSetting(mServiceName.getPackageName())
- != PackageManager.COMPONENT_ENABLED_STATE_DISABLED
- && pm.getComponentEnabledSetting(mServiceName)
- != PackageManager.COMPONENT_ENABLED_STATE_DISABLED;
- if (mBound && !serviceEnabled) {
- stopService();
- scheduleCheckBound();
- } else if (!mBound && serviceEnabled) {
- startService();
- }
- }
- }
-
- private void stopService() {
- if (mDebug) Log.d(mTag, "stopService");
- boolean stopped = mContext.stopService(new Intent().setComponent(mServiceName));
- if (mDebug) Log.d(mTag, " stopped=" + stopped);
- mContext.unbindService(mServiceConnection);
- mBound = false;
- }
-
- private void startService() {
- mServiceName = getComponentNameFromSetting();
- if (mDebug) Log.d(mTag, "startService mServiceName=" + mServiceName);
- if (mServiceName == null) {
- mBound = false;
- mCallbacks.onNoService();
- } else {
- long delay = mCallbacks.onServiceStartAttempt();
- mHandler.sendEmptyMessageDelayed(MSG_CONTINUE_START_SERVICE, delay);
- }
- }
-
- private void continueStartService() {
- if (mDebug) Log.d(mTag, "continueStartService");
- Intent intent = new Intent().setComponent(mServiceName);
- try {
- mServiceConnection = new SC();
- mBound = mContext.bindService(intent, mServiceConnection, Context.BIND_AUTO_CREATE);
- if (mDebug) Log.d(mTag, "mBound: " + mBound);
- } catch (Throwable t) {
- Log.w(mTag, "Error binding to service: " + mServiceName, t);
- }
- if (!mBound) {
- mCallbacks.onNoService();
- }
- }
-
- private void serviceDisconnected(ComponentName serviceName) {
- if (mDebug) Log.d(mTag, "serviceDisconnected serviceName=" + serviceName
- + " mServiceName=" + mServiceName);
- if (serviceName.equals(mServiceName)) {
- mBound = false;
- scheduleCheckBound();
- }
- }
-
- private void checkBound() {
- if (mDebug) Log.d(mTag, "checkBound mBound=" + mBound);
- if (!mBound) {
- startService();
- }
- }
-
- private void scheduleCheckBound() {
- mHandler.removeMessages(MSG_CHECK_BOUND);
- mHandler.sendEmptyMessageDelayed(MSG_CHECK_BOUND, RECHECK_DELAY);
- }
-
- private static String bundleToString(Bundle bundle) {
- if (bundle == null) return null;
- StringBuilder sb = new StringBuilder("{");
- for (String key : bundle.keySet()) {
- if (sb.length() > 1) sb.append(',');
- Object v = bundle.get(key);
- v = (v instanceof String[]) ? Arrays.asList((String[]) v) : v;
- sb.append(key).append('=').append(v);
- }
- return sb.append('}').toString();
- }
-
- public ComponentName getComponent() {
- return getComponentNameFromSetting();
- }
-
- public void setComponent(ComponentName component) {
- final String setting = component == null ? null : component.flattenToShortString();
- Settings.Secure.putStringForUser(mContext.getContentResolver(),
- mSettingKey, setting, UserHandle.USER_CURRENT);
- }
-
- public boolean isPackageAvailable() {
- final ComponentName component = getComponent();
- if (component == null) return false;
- try {
- return mContext.getPackageManager().isPackageAvailable(component.getPackageName());
- } catch (RuntimeException e) {
- Log.w(mTag, "Error checking package availability", e);
- return false;
- }
- }
-}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/SystemBars.java b/packages/SystemUI/src/com/android/systemui/statusbar/SystemBars.java
index 8819c60..275fd70 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/SystemBars.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/SystemBars.java
@@ -27,47 +27,21 @@
import java.io.PrintWriter;
/**
- * Ensure a single status bar service implementation is running at all times.
- *
- * <p>The implementation either comes from a service component running in a remote process (defined
- * using a secure setting), else falls back to using the in-process implementation according
- * to the product config.
+ * Ensure a single status bar service implementation is running at all times, using the in-process
+ * implementation according to the product config.
*/
-public class SystemBars extends SystemUI implements ServiceMonitor.Callbacks {
+public class SystemBars extends SystemUI {
private static final String TAG = "SystemBars";
private static final boolean DEBUG = false;
private static final int WAIT_FOR_BARS_TO_DIE = 500;
- // manages the implementation coming from the remote process
- private ServiceMonitor mServiceMonitor;
-
// in-process fallback implementation, per the product config
private BaseStatusBar mStatusBar;
@Override
public void start() {
if (DEBUG) Log.d(TAG, "start");
- mServiceMonitor = new ServiceMonitor(TAG, DEBUG,
- mContext, Settings.Secure.BAR_SERVICE_COMPONENT, this);
- mServiceMonitor.start(); // will call onNoService if no remote service is found
- }
-
- @Override
- public void onNoService() {
- if (DEBUG) Log.d(TAG, "onNoService");
- createStatusBarFromConfig(); // fallback to using an in-process implementation
- }
-
- @Override
- public long onServiceStartAttempt() {
- if (DEBUG) Log.d(TAG, "onServiceStartAttempt mStatusBar="+mStatusBar);
- if (mStatusBar != null) {
- // tear down the in-process version, we'll recreate it again if needed
- mStatusBar.destroy();
- mStatusBar = null;
- return WAIT_FOR_BARS_TO_DIE;
- }
- return 0;
+ createStatusBarFromConfig();
}
@Override
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/UserSwitcherController.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/UserSwitcherController.java
index bb4b91e..4785ba9 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/UserSwitcherController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/UserSwitcherController.java
@@ -49,6 +49,7 @@
import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
import com.android.internal.annotations.VisibleForTesting;
+import com.android.internal.messages.nano.SystemMessageProto.SystemMessage;
import com.android.internal.util.UserIcons;
import com.android.settingslib.RestrictedLockUtils;
import com.android.systemui.GuestResumeSessionReceiver;
@@ -79,8 +80,6 @@
private static final String ACTION_LOGOUT_USER = "com.android.systemui.LOGOUT_USER";
private static final int PAUSE_REFRESH_USERS_TIMEOUT_MS = 3000;
- private static final int ID_REMOVE_GUEST = 1010;
- private static final int ID_LOGOUT_USER = 1011;
private static final String TAG_REMOVE_GUEST = "remove_guest";
private static final String TAG_LOGOUT_USER = "logout_user";
@@ -572,8 +571,8 @@
mContext.getString(R.string.user_logout_notification_action),
logoutPI);
SystemUI.overrideNotificationAppName(mContext, builder);
- NotificationManager.from(mContext).notifyAsUser(TAG_LOGOUT_USER, ID_LOGOUT_USER,
- builder.build(), new UserHandle(userId));
+ NotificationManager.from(mContext).notifyAsUser(TAG_LOGOUT_USER,
+ SystemMessage.NOTE_LOGOUT_USER, builder.build(), new UserHandle(userId));
}
};
@@ -595,8 +594,8 @@
mContext.getString(R.string.guest_notification_remove_action),
removeGuestPI);
SystemUI.overrideNotificationAppName(mContext, builder);
- NotificationManager.from(mContext).notifyAsUser(TAG_REMOVE_GUEST, ID_REMOVE_GUEST,
- builder.build(), new UserHandle(guestUserId));
+ NotificationManager.from(mContext).notifyAsUser(TAG_REMOVE_GUEST,
+ SystemMessage.NOTE_REMOVE_GUEST, builder.build(), new UserHandle(guestUserId));
}
private final Runnable mUnpauseRefreshUsers = new Runnable() {
diff --git a/packages/SystemUI/src/com/android/systemui/usb/StorageNotification.java b/packages/SystemUI/src/com/android/systemui/usb/StorageNotification.java
index 97d5e10..2c90e62 100644
--- a/packages/SystemUI/src/com/android/systemui/usb/StorageNotification.java
+++ b/packages/SystemUI/src/com/android/systemui/usb/StorageNotification.java
@@ -41,6 +41,7 @@
import android.util.SparseArray;
import com.android.internal.R;
+import com.android.internal.messages.nano.SystemMessageProto.SystemMessage;
import com.android.systemui.SystemUI;
import java.util.List;
@@ -48,11 +49,6 @@
public class StorageNotification extends SystemUI {
private static final String TAG = "StorageNotification";
- private static final int PUBLIC_ID = 0x53505542; // SPUB
- private static final int PRIVATE_ID = 0x53505256; // SPRV
- private static final int DISK_ID = 0x5344534b; // SDSK
- private static final int MOVE_ID = 0x534d4f56; // SMOV
-
private static final String ACTION_SNOOZE_VOLUME = "com.android.systemui.action.SNOOZE_VOLUME";
private static final String ACTION_FINISH_WIZARD = "com.android.systemui.action.FINISH_WIZARD";
@@ -91,7 +87,8 @@
@Override
public void onVolumeForgotten(String fsUuid) {
// Stop annoying the user
- mNotificationManager.cancelAsUser(fsUuid, PRIVATE_ID, UserHandle.ALL);
+ mNotificationManager.cancelAsUser(fsUuid, SystemMessage.NOTE_STORAGE_PRIVATE,
+ UserHandle.ALL);
}
@Override
@@ -119,7 +116,8 @@
public void onReceive(Context context, Intent intent) {
// When finishing the adoption wizard, clean up any notifications
// for moving primary storage
- mNotificationManager.cancelAsUser(null, MOVE_ID, UserHandle.ALL);
+ mNotificationManager.cancelAsUser(null, SystemMessage.NOTE_STORAGE_MOVE,
+ UserHandle.ALL);
}
};
@@ -190,7 +188,8 @@
final VolumeInfo info = mStorageManager.findVolumeByUuid(fsUuid);
if ((info != null && info.isMountedWritable()) || rec.isSnoozed()) {
// Yay, private volume is here, or user snoozed
- mNotificationManager.cancelAsUser(fsUuid, PRIVATE_ID, UserHandle.ALL);
+ mNotificationManager.cancelAsUser(fsUuid, SystemMessage.NOTE_STORAGE_PRIVATE,
+ UserHandle.ALL);
} else {
// Boo, annoy the user to reinsert the private volume
@@ -211,8 +210,8 @@
.setDeleteIntent(buildSnoozeIntent(fsUuid));
SystemUI.overrideNotificationAppName(mContext, builder);
- mNotificationManager.notifyAsUser(fsUuid, PRIVATE_ID, builder
- .build(), UserHandle.ALL);
+ mNotificationManager.notifyAsUser(fsUuid, SystemMessage.NOTE_STORAGE_PRIVATE,
+ builder.build(), UserHandle.ALL);
}
}
}
@@ -237,12 +236,13 @@
.setCategory(Notification.CATEGORY_ERROR);
SystemUI.overrideNotificationAppName(mContext, builder);
- mNotificationManager.notifyAsUser(disk.getId(), DISK_ID, builder.build(),
- UserHandle.ALL);
+ mNotificationManager.notifyAsUser(disk.getId(), SystemMessage.NOTE_STORAGE_DISK,
+ builder.build(), UserHandle.ALL);
} else {
// Yay, we have volumes!
- mNotificationManager.cancelAsUser(disk.getId(), DISK_ID, UserHandle.ALL);
+ mNotificationManager.cancelAsUser(disk.getId(), SystemMessage.NOTE_STORAGE_DISK,
+ UserHandle.ALL);
}
}
@@ -252,7 +252,8 @@
* @param disk The disk that went away.
*/
private void onDiskDestroyedInternal(@NonNull DiskInfo disk) {
- mNotificationManager.cancelAsUser(disk.getId(), DISK_ID, UserHandle.ALL);
+ mNotificationManager.cancelAsUser(disk.getId(), SystemMessage.NOTE_STORAGE_DISK,
+ UserHandle.ALL);
}
private void onVolumeStateChangedInternal(VolumeInfo vol) {
@@ -308,9 +309,11 @@
}
if (notif != null) {
- mNotificationManager.notifyAsUser(vol.getId(), PUBLIC_ID, notif, UserHandle.ALL);
+ mNotificationManager.notifyAsUser(vol.getId(), SystemMessage.NOTE_STORAGE_PUBLIC,
+ notif, UserHandle.ALL);
} else {
- mNotificationManager.cancelAsUser(vol.getId(), PUBLIC_ID, UserHandle.ALL);
+ mNotificationManager.cancelAsUser(vol.getId(), SystemMessage.NOTE_STORAGE_PUBLIC,
+ UserHandle.ALL);
}
}
@@ -488,7 +491,7 @@
.setOngoing(true);
SystemUI.overrideNotificationAppName(mContext, builder);
- mNotificationManager.notifyAsUser(move.packageName, MOVE_ID,
+ mNotificationManager.notifyAsUser(move.packageName, SystemMessage.NOTE_STORAGE_MOVE,
builder.build(), UserHandle.ALL);
}
@@ -496,7 +499,8 @@
if (move.packageName != null) {
// We currently ignore finished app moves; just clear the last
// published progress
- mNotificationManager.cancelAsUser(move.packageName, MOVE_ID, UserHandle.ALL);
+ mNotificationManager.cancelAsUser(move.packageName, SystemMessage.NOTE_STORAGE_MOVE,
+ UserHandle.ALL);
return;
}
@@ -537,8 +541,8 @@
.setAutoCancel(true);
SystemUI.overrideNotificationAppName(mContext, builder);
- mNotificationManager.notifyAsUser(move.packageName, MOVE_ID, builder.build(),
- UserHandle.ALL);
+ mNotificationManager.notifyAsUser(move.packageName, SystemMessage.NOTE_STORAGE_MOVE,
+ builder.build(), UserHandle.ALL);
}
private int getSmallIcon(DiskInfo disk, int state) {
diff --git a/packages/SystemUI/src/com/android/systemui/volume/VolumeDialogController.java b/packages/SystemUI/src/com/android/systemui/volume/VolumeDialogController.java
index 17dd8d6..0e5ff43 100644
--- a/packages/SystemUI/src/com/android/systemui/volume/VolumeDialogController.java
+++ b/packages/SystemUI/src/com/android/systemui/volume/VolumeDialogController.java
@@ -99,7 +99,6 @@
private final Vibrator mVibrator;
private final boolean mHasVibrator;
- private boolean mEnabled;
private boolean mDestroyed;
private VolumePolicy mVolumePolicy;
private boolean mShowDndTile = true;
@@ -198,7 +197,6 @@
public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
pw.println(VolumeDialogController.class.getSimpleName() + " state:");
- pw.print(" mEnabled: "); pw.println(mEnabled);
pw.print(" mDestroyed: "); pw.println(mDestroyed);
pw.print(" mVolumePolicy: "); pw.println(mVolumePolicy);
pw.print(" mState: "); pw.println(mState.toString(4));
@@ -749,8 +747,6 @@
private final class SettingObserver extends ContentObserver {
- private final Uri SERVICE_URI = Settings.Secure.getUriFor(
- Settings.Secure.VOLUME_CONTROLLER_SERVICE_COMPONENT);
private final Uri ZEN_MODE_URI =
Settings.Global.getUriFor(Settings.Global.ZEN_MODE);
private final Uri ZEN_MODE_CONFIG_URI =
@@ -761,10 +757,8 @@
}
public void init() {
- mContext.getContentResolver().registerContentObserver(SERVICE_URI, false, this);
mContext.getContentResolver().registerContentObserver(ZEN_MODE_URI, false, this);
mContext.getContentResolver().registerContentObserver(ZEN_MODE_CONFIG_URI, false, this);
- onChange(true, SERVICE_URI);
}
public void destroy() {
@@ -774,17 +768,6 @@
@Override
public void onChange(boolean selfChange, Uri uri) {
boolean changed = false;
- if (SERVICE_URI.equals(uri)) {
- final String setting = Settings.Secure.getString(mContext.getContentResolver(),
- Settings.Secure.VOLUME_CONTROLLER_SERVICE_COMPONENT);
- final boolean enabled = setting != null && mComponent != null
- && mComponent.equals(ComponentName.unflattenFromString(setting));
- if (enabled == mEnabled) return;
- if (enabled) {
- register();
- }
- mEnabled = enabled;
- }
if (ZEN_MODE_URI.equals(uri)) {
changed = updateZenModeW();
}
diff --git a/packages/SystemUI/src/com/android/systemui/volume/VolumeUI.java b/packages/SystemUI/src/com/android/systemui/volume/VolumeUI.java
index c820302..73d9ea7 100644
--- a/packages/SystemUI/src/com/android/systemui/volume/VolumeUI.java
+++ b/packages/SystemUI/src/com/android/systemui/volume/VolumeUI.java
@@ -16,31 +16,13 @@
package com.android.systemui.volume;
-import android.app.Notification;
-import android.app.NotificationManager;
-import android.app.PendingIntent;
-import android.content.BroadcastReceiver;
-import android.content.ComponentName;
-import android.content.Context;
-import android.content.DialogInterface;
-import android.content.DialogInterface.OnClickListener;
-import android.content.Intent;
-import android.content.IntentFilter;
-import android.content.pm.ApplicationInfo;
import android.content.res.Configuration;
-import android.media.AudioManager;
-import android.media.session.MediaSessionManager;
import android.os.Handler;
-import android.provider.Settings;
-import android.text.TextUtils;
import android.util.Log;
-import com.android.systemui.Prefs;
import com.android.systemui.R;
import com.android.systemui.SystemUI;
import com.android.systemui.qs.tiles.DndTile;
-import com.android.systemui.statusbar.ServiceMonitor;
-import com.android.systemui.statusbar.phone.SystemUIDialog;
import com.android.systemui.statusbar.policy.ZenModeController;
import com.android.systemui.statusbar.policy.ZenModeControllerImpl;
@@ -52,34 +34,18 @@
private static boolean LOGD = Log.isLoggable(TAG, Log.DEBUG);
private final Handler mHandler = new Handler();
- private final Receiver mReceiver = new Receiver();
- private final RestorationNotification mRestorationNotification = new RestorationNotification();
private boolean mEnabled;
- private AudioManager mAudioManager;
- private NotificationManager mNotificationManager;
- private MediaSessionManager mMediaSessionManager;
- private ServiceMonitor mVolumeControllerService;
-
private VolumeDialogComponent mVolumeComponent;
@Override
public void start() {
mEnabled = mContext.getResources().getBoolean(R.bool.enable_volume_ui);
if (!mEnabled) return;
- mAudioManager = (AudioManager) mContext.getSystemService(Context.AUDIO_SERVICE);
- mNotificationManager =
- (NotificationManager) mContext.getSystemService(Context.NOTIFICATION_SERVICE);
- mMediaSessionManager = (MediaSessionManager) mContext
- .getSystemService(Context.MEDIA_SESSION_SERVICE);
final ZenModeController zenController = new ZenModeControllerImpl(mContext, mHandler);
mVolumeComponent = new VolumeDialogComponent(this, mContext, null, zenController);
putComponent(VolumeComponent.class, getVolumeComponent());
- mReceiver.start();
- mVolumeControllerService = new ServiceMonitor(TAG, LOGD,
- mContext, Settings.Secure.VOLUME_CONTROLLER_SERVICE_COMPONENT,
- new ServiceMonitorCallbacks());
- mVolumeControllerService.start();
+ setDefaultVolumeController();
}
private VolumeComponent getVolumeComponent() {
@@ -97,154 +63,12 @@
public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
pw.print("mEnabled="); pw.println(mEnabled);
if (!mEnabled) return;
- pw.print("mVolumeControllerService="); pw.println(mVolumeControllerService.getComponent());
getVolumeComponent().dump(fd, pw, args);
}
- private void setDefaultVolumeController(boolean register) {
- if (register) {
- DndTile.setVisible(mContext, true);
- if (LOGD) Log.d(TAG, "Registering default volume controller");
- getVolumeComponent().register();
- } else {
- if (LOGD) Log.d(TAG, "Unregistering default volume controller");
- mAudioManager.setVolumeController(null);
- mMediaSessionManager.setRemoteVolumeController(null);
- }
- }
-
- private String getAppLabel(ComponentName component) {
- final String pkg = component.getPackageName();
- try {
- final ApplicationInfo ai = mContext.getPackageManager().getApplicationInfo(pkg, 0);
- final String rt = mContext.getPackageManager().getApplicationLabel(ai).toString();
- if (!TextUtils.isEmpty(rt)) {
- return rt;
- }
- } catch (Exception e) {
- Log.w(TAG, "Error loading app label", e);
- }
- return pkg;
- }
-
- private void showServiceActivationDialog(final ComponentName component) {
- final SystemUIDialog d = new SystemUIDialog(mContext);
- d.setMessage(mContext.getString(R.string.volumeui_prompt_message, getAppLabel(component)));
- d.setPositiveButton(R.string.volumeui_prompt_allow, new OnClickListener() {
- @Override
- public void onClick(DialogInterface dialog, int which) {
- mVolumeControllerService.setComponent(component);
- }
- });
- d.setNegativeButton(R.string.volumeui_prompt_deny, null);
- d.show();
- }
-
- private final class ServiceMonitorCallbacks implements ServiceMonitor.Callbacks {
- @Override
- public void onNoService() {
- if (LOGD) Log.d(TAG, "onNoService");
- setDefaultVolumeController(true);
- mRestorationNotification.hide();
- if (!mVolumeControllerService.isPackageAvailable()) {
- mVolumeControllerService.setComponent(null);
- }
- }
-
- @Override
- public long onServiceStartAttempt() {
- if (LOGD) Log.d(TAG, "onServiceStartAttempt");
- // poke the setting to update the uid
- mVolumeControllerService.setComponent(mVolumeControllerService.getComponent());
- setDefaultVolumeController(false);
- getVolumeComponent().dismissNow();
- mRestorationNotification.show();
- return 0;
- }
- }
-
- private final class Receiver extends BroadcastReceiver {
- private static final String ENABLE = "com.android.systemui.vui.ENABLE";
- private static final String DISABLE = "com.android.systemui.vui.DISABLE";
- private static final String EXTRA_COMPONENT = "component";
-
- private static final String PREF = "com.android.systemui.PREF";
- private static final String EXTRA_KEY = "key";
- private static final String EXTRA_VALUE = "value";
-
- public void start() {
- final IntentFilter filter = new IntentFilter();
- filter.addAction(ENABLE);
- filter.addAction(DISABLE);
- filter.addAction(PREF);
- mContext.registerReceiver(this, filter, null, mHandler);
- }
-
- @Override
- public void onReceive(Context context, Intent intent) {
- final String action = intent.getAction();
- if (PREF.equals(action)) {
- final String key = intent.getStringExtra(EXTRA_KEY);
- if (key != null && intent.getExtras() != null) {
- final Object value = intent.getExtras().get(EXTRA_VALUE);
- if (value == null) {
- Prefs.remove(mContext, key);
- } else if (value instanceof Boolean) {
- Prefs.putBoolean(mContext, key, (Boolean) value);
- } else if (value instanceof Integer) {
- Prefs.putInt(mContext, key, (Integer) value);
- } else if (value instanceof Long) {
- Prefs.putLong(mContext, key, (Long) value);
- }
- }
- return;
- }
- final ComponentName component = intent.getParcelableExtra(EXTRA_COMPONENT);
- final boolean current = component != null
- && component.equals(mVolumeControllerService.getComponent());
- if (ENABLE.equals(action) && component != null) {
- if (!current) {
- showServiceActivationDialog(component);
- }
- }
- if (DISABLE.equals(action) && component != null) {
- if (current) {
- mVolumeControllerService.setComponent(null);
- }
- }
- }
- }
-
- private final class RestorationNotification {
- public void hide() {
- mNotificationManager.cancel(R.id.notification_volumeui);
- }
-
- public void show() {
- final ComponentName component = mVolumeControllerService.getComponent();
- if (component == null) {
- Log.w(TAG, "Not showing restoration notification, component not active");
- return;
- }
- final Intent intent = new Intent(Receiver.DISABLE)
- .putExtra(Receiver.EXTRA_COMPONENT, component);
- Notification.Builder builder = new Notification.Builder(mContext)
- .setSmallIcon(R.drawable.ic_volume_media)
- .setWhen(0)
- .setShowWhen(false)
- .setOngoing(true)
- .setContentTitle(mContext.getString(
- R.string.volumeui_notification_title, getAppLabel(component)))
- .setContentText(mContext.getString(R.string.volumeui_notification_text))
- .setContentIntent(PendingIntent.getBroadcast(mContext, 0, intent,
- PendingIntent.FLAG_UPDATE_CURRENT))
- .setPriority(Notification.PRIORITY_MIN)
- .setVisibility(Notification.VISIBILITY_PUBLIC)
- .setColor(mContext.getColor(
- com.android.internal.R.color.system_notification_accent_color));
- overrideNotificationAppName(mContext, builder);
- mNotificationManager.notify(R.id.notification_volumeui,
- builder.build());
- }
+ private void setDefaultVolumeController() {
+ DndTile.setVisible(mContext, true);
+ if (LOGD) Log.d(TAG, "Registering default volume controller");
+ getVolumeComponent().register();
}
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/plugins/PluginInstanceManagerTest.java b/packages/SystemUI/tests/src/com/android/systemui/plugins/PluginInstanceManagerTest.java
index 9050b83..01fd97c 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/plugins/PluginInstanceManagerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/plugins/PluginInstanceManagerTest.java
@@ -17,11 +17,15 @@
import static junit.framework.Assert.assertFalse;
import static junit.framework.Assert.assertTrue;
+import static org.mockito.Matchers.any;
+import static org.mockito.Matchers.anyInt;
+import static org.mockito.Matchers.eq;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
import android.app.Activity;
+import android.app.NotificationManager;
import android.content.BroadcastReceiver;
import android.content.ComponentName;
import android.content.Context;
@@ -34,9 +38,11 @@
import android.content.pm.ResolveInfo;
import android.content.pm.ServiceInfo;
import android.os.HandlerThread;
+import android.os.UserHandle;
import android.support.test.runner.AndroidJUnit4;
import android.test.suitebuilder.annotation.SmallTest;
+import com.android.internal.messages.nano.SystemMessageProto.SystemMessage;
import com.android.systemui.SysuiTestCase;
import org.junit.After;
@@ -72,7 +78,7 @@
mMockPm = mock(PackageManager.class);
mMockListener = mock(PluginListener.class);
mMockManager = mock(PluginManager.class);
- when(mMockManager.getClassLoader(Mockito.any(), Mockito.any()))
+ when(mMockManager.getClassLoader(any(), any()))
.thenReturn(getClass().getClassLoader());
mPluginInstanceManager = new PluginInstanceManager(mContextWrapper, mMockPm, "myAction",
mMockListener, true, mHandlerThread.getLooper(), 1, mMockManager, true);
@@ -87,8 +93,8 @@
}
@Test
- public void testNoPlugins() {
- when(mMockPm.queryIntentServices(Mockito.any(), Mockito.anyInt())).thenReturn(
+ public void testNoPlugins() throws Exception {
+ when(mMockPm.queryIntentServices(any(), anyInt())).thenReturn(
Collections.emptyList());
mPluginInstanceManager.loadAll();
@@ -100,7 +106,7 @@
}
@Test
- public void testPluginCreate() {
+ public void testPluginCreate() throws Exception {
createPlugin();
// Verify startup lifecycle
@@ -110,7 +116,7 @@
}
@Test
- public void testPluginDestroy() {
+ public void testPluginDestroy() throws Exception {
createPlugin(); // Get into valid created state.
mPluginInstanceManager.destroy();
@@ -124,7 +130,9 @@
}
@Test
- public void testIncorrectVersion() {
+ public void testIncorrectVersion() throws Exception {
+ NotificationManager nm = mock(NotificationManager.class);
+ mContext.addMockSystemService(Context.NOTIFICATION_SERVICE, nm);
setupFakePmQuery();
when(sMockPlugin.getVersion()).thenReturn(2);
@@ -136,10 +144,12 @@
// Plugin shouldn't be connected because it is the wrong version.
verify(mMockListener, Mockito.never()).onPluginConnected(
ArgumentCaptor.forClass(Plugin.class).capture());
+ verify(nm).notifyAsUser(eq(TestPlugin.class.getName()), eq(SystemMessage.NOTE_PLUGIN),
+ any(), eq(UserHandle.ALL));
}
@Test
- public void testReloadOnChange() {
+ public void testReloadOnChange() throws Exception {
createPlugin(); // Get into valid created state.
mPluginInstanceManager.onPackageChange("com.android.systemui");
@@ -159,7 +169,7 @@
}
@Test
- public void testNonDebuggable() {
+ public void testNonDebuggable() throws Exception {
// Create a version that thinks the build is not debuggable.
mPluginInstanceManager = new PluginInstanceManager(mContextWrapper, mMockPm, "myAction",
mMockListener, true, mHandlerThread.getLooper(), 1, mMockManager, false);
@@ -176,7 +186,7 @@
}
@Test
- public void testCheckAndDisable() {
+ public void testCheckAndDisable() throws Exception {
createPlugin(); // Get into valid created state.
// Start with an unrelated class.
@@ -197,7 +207,7 @@
}
@Test
- public void testDisableAll() {
+ public void testDisableAll() throws Exception {
createPlugin(); // Get into valid created state.
mPluginInstanceManager.disableAll();
@@ -208,29 +218,26 @@
ArgumentCaptor.forClass(int.class).capture());
}
- private void setupFakePmQuery() {
+ private void setupFakePmQuery() throws Exception {
List<ResolveInfo> list = new ArrayList<>();
ResolveInfo info = new ResolveInfo();
- info.serviceInfo = new ServiceInfo();
+ info.serviceInfo = mock(ServiceInfo.class);
info.serviceInfo.packageName = "com.android.systemui";
info.serviceInfo.name = TestPlugin.class.getName();
+ when(info.serviceInfo.loadLabel(any())).thenReturn("Test Plugin");
list.add(info);
- when(mMockPm.queryIntentServices(Mockito.any(), Mockito.anyInt())).thenReturn(list);
+ when(mMockPm.queryIntentServices(any(), Mockito.anyInt())).thenReturn(list);
+ when(mMockPm.getServiceInfo(any(), anyInt())).thenReturn(info.serviceInfo);
when(mMockPm.checkPermission(Mockito.anyString(), Mockito.anyString())).thenReturn(
PackageManager.PERMISSION_GRANTED);
- try {
- ApplicationInfo appInfo = getContext().getApplicationInfo();
- when(mMockPm.getApplicationInfo(Mockito.anyString(), Mockito.anyInt())).thenReturn(
- appInfo);
- } catch (NameNotFoundException e) {
- // Shouldn't be possible, but if it is, we want to fail.
- throw new RuntimeException(e);
- }
+ ApplicationInfo appInfo = getContext().getApplicationInfo();
+ when(mMockPm.getApplicationInfo(Mockito.anyString(), Mockito.anyInt())).thenReturn(
+ appInfo);
}
- private void createPlugin() {
+ private void createPlugin() throws Exception {
setupFakePmQuery();
mPluginInstanceManager.loadAll();
diff --git a/packages/SystemUI/tests/src/com/android/systemui/plugins/PluginManagerTest.java b/packages/SystemUI/tests/src/com/android/systemui/plugins/PluginManagerTest.java
index 4b1827d..d5ada67 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/plugins/PluginManagerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/plugins/PluginManagerTest.java
@@ -13,13 +13,21 @@
*/
package com.android.systemui.plugins;
+import static org.mockito.Matchers.eq;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
+import android.app.NotificationManager;
+import android.content.ComponentName;
+import android.content.Context;
+import android.content.Intent;
+import android.content.pm.PackageManager;
+import android.net.Uri;
import android.support.test.runner.AndroidJUnit4;
import android.test.suitebuilder.annotation.SmallTest;
+import com.android.internal.messages.nano.SystemMessageProto.SystemMessage;
import com.android.systemui.SysuiTestCase;
import com.android.systemui.plugins.PluginManager.PluginInstanceManagerFactory;
@@ -113,6 +121,24 @@
ArgumentCaptor.forClass(Throwable.class).capture());
}
+ @Test
+ public void testDisableIntent() {
+ NotificationManager nm = mock(NotificationManager.class);
+ PackageManager pm = mock(PackageManager.class);
+ mContext.addMockSystemService(Context.NOTIFICATION_SERVICE, nm);
+ mContext.setMockPackageManager(pm);
+
+ ComponentName testComponent = new ComponentName(getContext().getPackageName(),
+ PluginManagerTest.class.getName());
+ Intent intent = new Intent(PluginManager.DISABLE_PLUGIN);
+ intent.setData(Uri.parse("package://" + testComponent.flattenToString()));
+ mPluginManager.onReceive(mContext, intent);
+ verify(nm).cancel(eq(testComponent.getClassName()), eq(SystemMessage.NOTE_PLUGIN));
+ verify(pm).setComponentEnabledSetting(eq(testComponent),
+ eq(PackageManager.COMPONENT_ENABLED_STATE_DISABLED),
+ eq(PackageManager.DONT_KILL_APP));
+ }
+
private void resetExceptionHandler() {
mPluginExceptionHandler = Thread.getDefaultUncaughtExceptionHandler();
// Set back the real exception handler so the test can crash if it wants to.
diff --git a/packages/SystemUI/tests/src/com/android/systemui/power/PowerNotificationWarningsTest.java b/packages/SystemUI/tests/src/com/android/systemui/power/PowerNotificationWarningsTest.java
index 5c87fb0..34cfa7b 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/power/PowerNotificationWarningsTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/power/PowerNotificationWarningsTest.java
@@ -22,6 +22,7 @@
import static junit.framework.Assert.assertFalse;
import static junit.framework.Assert.assertTrue;
+import static org.mockito.Matchers.eq;
import static org.mockito.Mockito.any;
import static org.mockito.Mockito.anyInt;
import static org.mockito.Mockito.anyString;
@@ -34,6 +35,7 @@
import android.support.test.runner.AndroidJUnit4;
import android.test.suitebuilder.annotation.SmallTest;
+import com.android.internal.messages.nano.SystemMessageProto.SystemMessage;
import com.android.systemui.SysuiTestCase;
import org.junit.Before;
@@ -76,28 +78,34 @@
public void testShowInvalidChargerNotification_NotifyAsUser() {
mPowerNotificationWarnings.showInvalidChargerWarning();
verify(mMockNotificationManager, times(1))
- .notifyAsUser(anyString(), anyInt(), any(), any());
+ .notifyAsUser(anyString(), eq(SystemMessage.NOTE_BAD_CHARGER), any(), any());
+ verify(mMockNotificationManager, times(1)).cancelAsUser(anyString(),
+ eq(SystemMessage.NOTE_POWER_LOW), any());
}
@Test
public void testDismissInvalidChargerNotification_CancelAsUser() {
mPowerNotificationWarnings.showInvalidChargerWarning();
mPowerNotificationWarnings.dismissInvalidChargerWarning();
- verify(mMockNotificationManager, times(1)).cancelAsUser(anyString(), anyInt(), any());
+ verify(mMockNotificationManager, times(1)).cancelAsUser(anyString(),
+ eq(SystemMessage.NOTE_BAD_CHARGER), any());
}
@Test
public void testShowLowBatteryNotification_NotifyAsUser() {
mPowerNotificationWarnings.showLowBatteryWarning(false);
verify(mMockNotificationManager, times(1))
- .notifyAsUser(anyString(), anyInt(), any(), any());
+ .notifyAsUser(anyString(), eq(SystemMessage.NOTE_POWER_LOW), any(), any());
+ verify(mMockNotificationManager, times(1)).cancelAsUser(anyString(),
+ eq(SystemMessage.NOTE_BAD_CHARGER), any());
}
@Test
public void testDismissLowBatteryNotification_CancelAsUser() {
mPowerNotificationWarnings.showLowBatteryWarning(false);
mPowerNotificationWarnings.dismissLowBatteryWarning();
- verify(mMockNotificationManager, times(1)).cancelAsUser(anyString(), anyInt(), any());
+ verify(mMockNotificationManager, times(1)).cancelAsUser(anyString(),
+ eq(SystemMessage.NOTE_POWER_LOW), any());
}
@Test
@@ -105,7 +113,8 @@
mPowerNotificationWarnings.showLowBatteryWarning(false);
ArgumentCaptor<Notification> captor = ArgumentCaptor.forClass(Notification.class);
verify(mMockNotificationManager)
- .notifyAsUser(anyString(), anyInt(), captor.capture(), any());
+ .notifyAsUser(anyString(), eq(SystemMessage.NOTE_POWER_LOW),
+ captor.capture(), any());
assertEquals(null, captor.getValue().sound);
}
@@ -114,7 +123,23 @@
mPowerNotificationWarnings.showLowBatteryWarning(true);
ArgumentCaptor<Notification> captor = ArgumentCaptor.forClass(Notification.class);
verify(mMockNotificationManager)
- .notifyAsUser(anyString(), anyInt(), captor.capture(), any());
+ .notifyAsUser(anyString(), eq(SystemMessage.NOTE_POWER_LOW),
+ captor.capture(), any());
assertNotEqual(null, captor.getValue().sound);
}
+
+ @Test
+ public void testShowTemperatureWarning_NotifyAsUser() {
+ mPowerNotificationWarnings.showTemperatureWarning();
+ verify(mMockNotificationManager, times(1))
+ .notifyAsUser(anyString(), eq(SystemMessage.NOTE_HIGH_TEMP), any(), any());
+ }
+
+ @Test
+ public void testDismissTemperatureWarning_CancelAsUser() {
+ mPowerNotificationWarnings.showTemperatureWarning();
+ mPowerNotificationWarnings.dismissTemperatureWarning();
+ verify(mMockNotificationManager, times(1)).cancelAsUser(anyString(),
+ eq(SystemMessage.NOTE_HIGH_TEMP), any());
+ }
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/external/TileColorPickerTest.java b/packages/SystemUI/tests/src/com/android/systemui/qs/external/TileColorPickerTest.java
new file mode 100644
index 0000000..ba451e1
--- /dev/null
+++ b/packages/SystemUI/tests/src/com/android/systemui/qs/external/TileColorPickerTest.java
@@ -0,0 +1,71 @@
+/*
+ * Copyright (C) 2016 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.external;
+
+import android.content.res.ColorStateList;
+import android.service.quicksettings.Tile;
+import android.support.test.runner.AndroidJUnit4;
+import android.test.suitebuilder.annotation.SmallTest;
+import com.android.systemui.SysuiTestCase;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import com.android.systemui.R;
+
+import static junit.framework.Assert.assertEquals;
+
+@SmallTest
+@RunWith(AndroidJUnit4.class)
+public class TileColorPickerTest extends SysuiTestCase {
+ private static final int DEFAULT_COLOR = 0;
+
+ private TileColorPicker mTileColorPicker;
+ private ColorStateList mTintColorStateList;
+
+ @Before
+ public void setUp() {
+ mTileColorPicker = TileColorPicker.getInstance(mContext);
+ mTintColorStateList = mContext.getResources().
+ getColorStateList(R.color.tint_color_selector, mContext.getTheme());
+ }
+
+ @Test
+ public void testGetColor_StateUnavailable_ReturnUnavailableColor() {
+ final int color = mTileColorPicker.getColor(Tile.STATE_UNAVAILABLE);
+ final int expectedColor = mTintColorStateList.getColorForState(
+ TileColorPicker.DISABLE_STATE_SET, DEFAULT_COLOR);
+
+ assertEquals(expectedColor, color);
+ }
+
+ @Test
+ public void testGetColor_StateInactive_ReturnInactiveColor() {
+ final int color = mTileColorPicker.getColor(Tile.STATE_INACTIVE);
+ final int expectedColor = mTintColorStateList.getColorForState(
+ TileColorPicker.INACTIVE_STATE_SET, DEFAULT_COLOR);
+
+ assertEquals(expectedColor, color);
+ }
+
+ @Test
+ public void testGetColor_StateActive_ReturnActiveColor() {
+ final int color = mTileColorPicker.getColor(Tile.STATE_ACTIVE);
+ final int expectedColor = mTintColorStateList.getColorForState(
+ TileColorPicker.ENABLE_STATE_SET, DEFAULT_COLOR);
+
+ assertEquals(expectedColor, color);
+ }
+}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/CommandQueueTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/CommandQueueTest.java
new file mode 100644
index 0000000..43f8629
--- /dev/null
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/CommandQueueTest.java
@@ -0,0 +1,295 @@
+/*
+ * 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.systemui.statusbar;
+
+import static org.mockito.Matchers.eq;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.verifyNoMoreInteractions;
+
+import android.content.ComponentName;
+import android.graphics.Rect;
+import android.os.Bundle;
+
+import com.android.internal.statusbar.StatusBarIcon;
+import com.android.systemui.SysuiTestCase;
+import com.android.systemui.statusbar.CommandQueue.Callbacks;
+
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+
+public class CommandQueueTest extends SysuiTestCase {
+
+ private CommandQueue mCommandQueue;
+ private Callbacks mCallbacks;
+
+ @Before
+ public void setup() {
+ mCommandQueue = new CommandQueue();
+ mCallbacks = mock(Callbacks.class);
+ mCommandQueue.addCallbacks(mCallbacks);
+ }
+
+ @After
+ public void tearDown() {
+ verifyNoMoreInteractions(mCallbacks);
+ }
+
+ @Test
+ public void testIcon() {
+ String slot = "testSlot";
+ StatusBarIcon icon = mock(StatusBarIcon.class);
+ mCommandQueue.setIcon(slot, icon);
+ waitForIdleSync();
+ verify(mCallbacks).setIcon(eq(slot), eq(icon));
+
+ mCommandQueue.removeIcon(slot);
+ waitForIdleSync();
+ verify(mCallbacks).removeIcon(eq(slot));
+ }
+
+ @Test
+ public void testDisable() {
+ int state1 = 14;
+ int state2 = 42;
+ mCommandQueue.disable(state1, state2);
+ waitForIdleSync();
+ verify(mCallbacks).disable(eq(state1), eq(state2), eq(true));
+ }
+
+ @Test
+ public void testExpandNotifications() {
+ mCommandQueue.animateExpandNotificationsPanel();
+ waitForIdleSync();
+ verify(mCallbacks).animateExpandNotificationsPanel();
+ }
+
+ @Test
+ public void testCollapsePanels() {
+ mCommandQueue.animateCollapsePanels();
+ waitForIdleSync();
+ verify(mCallbacks).animateCollapsePanels(eq(0));
+ }
+
+ @Test
+ public void testExpandSettings() {
+ String panel = "some_panel";
+ mCommandQueue.animateExpandSettingsPanel(panel);
+ waitForIdleSync();
+ verify(mCallbacks).animateExpandSettingsPanel(eq(panel));
+ }
+
+ @Test
+ public void testSetSystemUiVisibility() {
+ Rect r = new Rect();
+ mCommandQueue.setSystemUiVisibility(1, 2, 3, 4, null, r);
+ waitForIdleSync();
+ verify(mCallbacks).setSystemUiVisibility(eq(1), eq(2), eq(3), eq(4), eq(null), eq(r));
+ }
+
+ @Test
+ public void testTopAppWindowChanged() {
+ mCommandQueue.topAppWindowChanged(true);
+ waitForIdleSync();
+ verify(mCallbacks).topAppWindowChanged(eq(true));
+ }
+
+ @Test
+ public void testShowImeButton() {
+ mCommandQueue.setImeWindowStatus(null, 1, 2, true);
+ waitForIdleSync();
+ verify(mCallbacks).setImeWindowStatus(eq(null), eq(1), eq(2), eq(true));
+ }
+
+ @Test
+ public void testShowRecentApps() {
+ mCommandQueue.showRecentApps(true, false);
+ waitForIdleSync();
+ verify(mCallbacks).showRecentApps(eq(true), eq(false));
+ }
+
+ @Test
+ public void testHideRecentApps() {
+ mCommandQueue.hideRecentApps(true, false);
+ waitForIdleSync();
+ verify(mCallbacks).hideRecentApps(eq(true), eq(false));
+ }
+
+ @Test
+ public void testToggleRecentApps() {
+ mCommandQueue.toggleRecentApps();
+ waitForIdleSync();
+ verify(mCallbacks).toggleRecentApps();
+ }
+
+ @Test
+ public void testPreloadRecentApps() {
+ mCommandQueue.preloadRecentApps();
+ waitForIdleSync();
+ verify(mCallbacks).preloadRecentApps();
+ }
+
+ @Test
+ public void testCancelPreloadRecentApps() {
+ mCommandQueue.cancelPreloadRecentApps();
+ waitForIdleSync();
+ verify(mCallbacks).cancelPreloadRecentApps();
+ }
+
+ @Test
+ public void testDismissKeyboardShortcuts() {
+ mCommandQueue.dismissKeyboardShortcutsMenu();
+ waitForIdleSync();
+ verify(mCallbacks).dismissKeyboardShortcutsMenu();
+ }
+
+ @Test
+ public void testToggleKeyboardShortcuts() {
+ mCommandQueue.toggleKeyboardShortcutsMenu(1);
+ waitForIdleSync();
+ verify(mCallbacks).toggleKeyboardShortcutsMenu(eq(1));
+ }
+
+ @Test
+ public void testSetWindowState() {
+ mCommandQueue.setWindowState(1, 2);
+ waitForIdleSync();
+ verify(mCallbacks).setWindowState(eq(1), eq(2));
+ }
+
+ @Test
+ public void testBuzzBeepBlink() {
+ mCommandQueue.buzzBeepBlinked();
+ waitForIdleSync();
+ verify(mCallbacks).buzzBeepBlinked();
+ }
+
+ @Test
+ public void testNotificationLightOff() {
+ mCommandQueue.notificationLightOff();
+ waitForIdleSync();
+ verify(mCallbacks).notificationLightOff();
+ }
+
+ @Test
+ public void testNotificationLightPulse() {
+ mCommandQueue.notificationLightPulse(1, 2, 3);
+ waitForIdleSync();
+ verify(mCallbacks).notificationLightPulse(eq(1), eq(2), eq(3));
+ }
+
+ @Test
+ public void testScreenPinRequest() {
+ mCommandQueue.showScreenPinningRequest(1);
+ waitForIdleSync();
+ verify(mCallbacks).showScreenPinningRequest(eq(1));
+ }
+
+ @Test
+ public void testAppTransitionPending() {
+ mCommandQueue.appTransitionPending();
+ waitForIdleSync();
+ verify(mCallbacks).appTransitionPending();
+ }
+
+ @Test
+ public void testAppTransitionCancelled() {
+ mCommandQueue.appTransitionCancelled();
+ waitForIdleSync();
+ verify(mCallbacks).appTransitionCancelled();
+ }
+
+ @Test
+ public void testAppTransitionStarting() {
+ mCommandQueue.appTransitionStarting(1, 2);
+ waitForIdleSync();
+ verify(mCallbacks).appTransitionStarting(eq(1L), eq(2L));
+ }
+
+ @Test
+ public void testAppTransitionFinished() {
+ mCommandQueue.appTransitionFinished();
+ waitForIdleSync();
+ verify(mCallbacks).appTransitionFinished();
+ }
+
+ @Test
+ public void testAssistDisclosure() {
+ mCommandQueue.showAssistDisclosure();
+ waitForIdleSync();
+ verify(mCallbacks).showAssistDisclosure();
+ }
+
+ @Test
+ public void testStartAssist() {
+ Bundle b = new Bundle();
+ mCommandQueue.startAssist(b);
+ waitForIdleSync();
+ verify(mCallbacks).startAssist(eq(b));
+ }
+
+ @Test
+ public void testCameraLaunchGesture() {
+ mCommandQueue.onCameraLaunchGestureDetected(1);
+ waitForIdleSync();
+ verify(mCallbacks).onCameraLaunchGestureDetected(eq(1));
+ }
+
+ @Test
+ public void testShowTvPipMenu() {
+ mCommandQueue.showTvPictureInPictureMenu();
+ waitForIdleSync();
+ verify(mCallbacks).showTvPictureInPictureMenu();
+ }
+
+ @Test
+ public void testAddQsTile() {
+ ComponentName c = new ComponentName("testpkg", "testcls");
+ mCommandQueue.addQsTile(c);
+ waitForIdleSync();
+ verify(mCallbacks).addQsTile(eq(c));
+ }
+
+ @Test
+ public void testRemoveQsTile() {
+ ComponentName c = new ComponentName("testpkg", "testcls");
+ mCommandQueue.remQsTile(c);
+ waitForIdleSync();
+ verify(mCallbacks).remQsTile(eq(c));
+ }
+
+ @Test
+ public void testClickQsTile() {
+ ComponentName c = new ComponentName("testpkg", "testcls");
+ mCommandQueue.clickQsTile(c);
+ waitForIdleSync();
+ verify(mCallbacks).clickTile(eq(c));
+ }
+
+ @Test
+ public void testToggleAppSplitScreen() {
+ mCommandQueue.toggleSplitScreen();
+ waitForIdleSync();
+ verify(mCallbacks).toggleSplitScreen();
+ }
+
+ @Test
+ public void testHandleSysnavKey() {
+ mCommandQueue.handleSystemNavigationKey(1);
+ waitForIdleSync();
+ verify(mCallbacks).handleSystemNavigationKey(eq(1));
+ }
+}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/utils/TestableContext.java b/packages/SystemUI/tests/src/com/android/systemui/utils/TestableContext.java
index a952806..710f88a 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/utils/TestableContext.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/utils/TestableContext.java
@@ -23,6 +23,7 @@
import android.content.Intent;
import android.content.IntentFilter;
import android.content.ServiceConnection;
+import android.content.pm.PackageManager;
import android.content.res.Resources;
import android.os.Handler;
import android.os.IBinder;
@@ -42,6 +43,7 @@
private ArrayMap<ComponentName, IBinder> mMockServices;
private ArrayMap<ServiceConnection, ComponentName> mActiveServices;
+ private PackageManager mMockPackageManager;
private Tracker mReceiver;
private Tracker mService;
private Tracker mComponent;
@@ -59,6 +61,18 @@
mComponent = test.getTracker("component");
}
+ public void setMockPackageManager(PackageManager mock) {
+ mMockPackageManager = mock;
+ }
+
+ @Override
+ public PackageManager getPackageManager() {
+ if (mMockPackageManager != null) {
+ return mMockPackageManager;
+ }
+ return super.getPackageManager();
+ }
+
@Override
public Resources getResources() {
return super.getResources();
diff --git a/proto/src/metrics_constants.proto b/proto/src/metrics_constants.proto
index eed7e70..57c4565 100644
--- a/proto/src/metrics_constants.proto
+++ b/proto/src/metrics_constants.proto
@@ -3165,6 +3165,16 @@
// CATEGORY: Settings
DIALOG_SUPPORT_SYSTEM_INFORMATION = 756;
+ // These values should never appear in log outputs - they are reserved for
+ // internal Tron use.
+ RESERVED_FOR_LOGBUILDER_VIEW = 757;
+ RESERVED_FOR_LOGBUILDER_CATEGORY = 758;
+ RESERVED_FOR_LOGBUILDER_TYPE = 759;
+
+ // ACTION: "Do not show again" was enabled in the support disclaimer and the
+ // user accepted
+ ACTION_SKIP_DISCLAIMER_SELECTED = 760;
+
// ---- End O Constants, all O constants go above this line ----
// Add new aosp constants above this line.
diff --git a/proto/src/system_messages.proto b/proto/src/system_messages.proto
new file mode 100644
index 0000000..5b91776
--- /dev/null
+++ b/proto/src/system_messages.proto
@@ -0,0 +1,79 @@
+// 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.
+
+syntax = "proto2";
+
+option java_package = "com.android.internal.messages";
+option java_outer_classname = "SystemMessageProto";
+
+package com_android_notifications;
+
+// Descriptors for system messages: notifications, dialogs, toasts, etc.
+message SystemMessage {
+
+ // System message IDs
+ // These are non-consecutive in order to preserve some existing, ad hoc IDs.
+ enum ID {
+ // Unknown
+ NOTE_UNKNOWN = 0;
+
+ // Notify the user that a screenshot was captured.
+ // Package: com.android.systemui
+ NOTE_GLOBAL_SCREENSHOT = 1;
+
+ // Warn the user about an invalid charger.
+ // Package: com.android.systemui
+ NOTE_BAD_CHARGER = 2;
+
+ // Warn the user about low battery.
+ // Package: com.android.systemui
+ NOTE_POWER_LOW = 3;
+
+ // Warn the user that the device has gotten warm.
+ // Package: com.android.systemui
+ NOTE_HIGH_TEMP = 4;
+
+ // Warn the user that some notifications are hidden.
+ // Package: com.android.systemui
+ NOTE_HIDDEN_NOTIFICATIONS = 5;
+
+ // Notify the user of a problem with a plugin (dev devices only).
+ // Package: com.android.systemui
+ NOTE_PLUGIN = 6;
+
+ // Confirm that the user wants to remove the guest account.
+ // Package: com.android.systemui
+ NOTE_REMOVE_GUEST = 1010;
+
+ // Confirm that the user wants to log out of the device.
+ // Package: com.android.systemui
+ NOTE_LOGOUT_USER = 1011;
+
+ // Notify the user about public volume state changes..
+ // Package: com.android.systemui
+ NOTE_STORAGE_PUBLIC = 0x53505542;
+
+ // Notify the user about private volume state changes.
+ // Package: com.android.systemui
+ NOTE_STORAGE_PRIVATE = 0x53505256;
+
+ // Notify the user about an unsupported storage device..
+ // Package: com.android.systemui
+ NOTE_STORAGE_DISK = 0x5344534b;
+
+ // Notify the user that data or apps are being moved to external storage.
+ // Package: com.android.systemui
+ NOTE_STORAGE_MOVE = 0x534d4f56;
+ }
+}
diff --git a/services/Android.mk b/services/Android.mk
index 2911983..0d57efe 100644
--- a/services/Android.mk
+++ b/services/Android.mk
@@ -24,6 +24,7 @@
appwidget \
autofill \
backup \
+ coverage\
devicepolicy \
midi \
net \
@@ -37,6 +38,10 @@
# The convention is to name each service module 'services.$(module_name)'
LOCAL_STATIC_JAVA_LIBRARIES := $(addprefix services.,$(services))
+ifeq ($(EMMA_INSTRUMENT_FRAMEWORK),true)
+LOCAL_EMMA_INSTRUMENT := true
+endif
+
include $(BUILD_JAVA_LIBRARY)
# native library
diff --git a/services/appwidget/java/com/android/server/appwidget/AppWidgetServiceImpl.java b/services/appwidget/java/com/android/server/appwidget/AppWidgetServiceImpl.java
index 6404604..87eb380 100644
--- a/services/appwidget/java/com/android/server/appwidget/AppWidgetServiceImpl.java
+++ b/services/appwidget/java/com/android/server/appwidget/AppWidgetServiceImpl.java
@@ -48,6 +48,7 @@
import android.content.pm.ParceledListSlice;
import android.content.pm.ResolveInfo;
import android.content.pm.ServiceInfo;
+import android.content.pm.ShortcutServiceInternal;
import android.content.pm.UserInfo;
import android.content.res.Resources;
import android.content.res.TypedArray;
@@ -1542,6 +1543,36 @@
}
@Override
+ public boolean requestPinAppWidget(String callingPackage, ComponentName componentName,
+ IntentSender resultSender) {
+ final int callingUid = Binder.getCallingUid();
+ final int userId = UserHandle.getUserId(callingUid);
+
+ if (DEBUG) {
+ Slog.i(TAG, "requestPinAppWidget() " + userId);
+ }
+
+ final AppWidgetProviderInfo info;
+
+ synchronized (mLock) {
+ ensureGroupStateLoadedLocked(userId);
+
+ // Look for the widget associated with the caller.
+ Provider provider = lookupProviderLocked(new ProviderId(callingUid, componentName));
+ if (provider == null || provider.zombie) {
+ return false;
+ }
+ info = provider.info;
+ if ((info.widgetCategory & AppWidgetProviderInfo.WIDGET_CATEGORY_HOME_SCREEN) == 0) {
+ return false;
+ }
+ }
+
+ return LocalServices.getService(ShortcutServiceInternal.class)
+ .requestPinAppWidget(callingPackage, info, resultSender, userId);
+ }
+
+ @Override
public ParceledListSlice<AppWidgetProviderInfo> getInstalledProvidersForProfile(int categoryFilter,
int profileId) {
final int userId = UserHandle.getCallingUserId();
diff --git a/services/core/java/com/android/server/BatteryService.java b/services/core/java/com/android/server/BatteryService.java
index 573ad63..dd550f2 100644
--- a/services/core/java/com/android/server/BatteryService.java
+++ b/services/core/java/com/android/server/BatteryService.java
@@ -347,13 +347,14 @@
+ ", chargerWirelessOnline=" + mBatteryProps.chargerWirelessOnline
+ ", maxChargingCurrent" + mBatteryProps.maxChargingCurrent
+ ", maxChargingVoltage" + mBatteryProps.maxChargingVoltage
- + ", chargeCounter" + mBatteryProps.batteryChargeCounter
+ ", batteryStatus=" + mBatteryProps.batteryStatus
+ ", batteryHealth=" + mBatteryProps.batteryHealth
+ ", batteryPresent=" + mBatteryProps.batteryPresent
+ ", batteryLevel=" + mBatteryProps.batteryLevel
+ ", batteryTechnology=" + mBatteryProps.batteryTechnology
+ ", batteryVoltage=" + mBatteryProps.batteryVoltage
+ + ", batteryChargeCounter=" + mBatteryProps.batteryChargeCounter
+ + ", batteryFullCharge=" + mBatteryProps.batteryFullCharge
+ ", batteryTemperature=" + mBatteryProps.batteryTemperature
+ ", mBatteryLevelCritical=" + mBatteryLevelCritical
+ ", mPlugType=" + mPlugType);
@@ -363,7 +364,8 @@
try {
mBatteryStats.setBatteryState(mBatteryProps.batteryStatus, mBatteryProps.batteryHealth,
mPlugType, mBatteryProps.batteryLevel, mBatteryProps.batteryTemperature,
- mBatteryProps.batteryVoltage, mBatteryProps.batteryChargeCounter);
+ mBatteryProps.batteryVoltage, mBatteryProps.batteryChargeCounter,
+ mBatteryProps.batteryFullCharge);
} catch (RemoteException e) {
// Should never happen.
}
diff --git a/services/core/java/com/android/server/BluetoothManagerService.java b/services/core/java/com/android/server/BluetoothManagerService.java
index 3419963..e7f1d16f 100644
--- a/services/core/java/com/android/server/BluetoothManagerService.java
+++ b/services/core/java/com/android/server/BluetoothManagerService.java
@@ -2045,6 +2045,11 @@
}
writer.flush();
+ if (args.length == 0) {
+ // Add arg to produce output
+ args = new String[1];
+ args[0] = "--print";
+ }
}
if (mBluetoothBinder == null) {
diff --git a/services/core/java/com/android/server/ConnectivityService.java b/services/core/java/com/android/server/ConnectivityService.java
index 7572dfe..f271b08 100644
--- a/services/core/java/com/android/server/ConnectivityService.java
+++ b/services/core/java/com/android/server/ConnectivityService.java
@@ -4597,9 +4597,28 @@
} catch (Exception e) {
loge("Exception in setDnsConfigurationForNetwork: " + e);
}
+ final NetworkAgentInfo defaultNai = getDefaultNetwork();
+ if (defaultNai != null && defaultNai.network.netId == netId) {
+ setDefaultDnsSystemProperties(dnses);
+ }
flushVmDnsCache();
}
+ private void setDefaultDnsSystemProperties(Collection<InetAddress> dnses) {
+ int last = 0;
+ for (InetAddress dns : dnses) {
+ ++last;
+ String key = "net.dns" + last;
+ String value = dns.getHostAddress();
+ SystemProperties.set(key, value);
+ }
+ for (int i = last + 1; i <= mNumDnsEntries; ++i) {
+ String key = "net.dns" + i;
+ SystemProperties.set(key, "");
+ }
+ mNumDnsEntries = last;
+ }
+
private String getNetworkPermission(NetworkCapabilities nc) {
// TODO: make these permission strings AIDL constants instead.
if (!nc.hasCapability(NET_CAPABILITY_NOT_RESTRICTED)) {
@@ -4816,6 +4835,7 @@
notifyLockdownVpn(newNetwork);
handleApplyDefaultProxy(newNetwork.linkProperties.getHttpProxy());
updateTcpBufferSizes(newNetwork);
+ setDefaultDnsSystemProperties(newNetwork.linkProperties.getDnsServers());
}
private void processListenRequests(NetworkAgentInfo nai, boolean capabilitiesChanged) {
diff --git a/services/core/java/com/android/server/EventLogTags.logtags b/services/core/java/com/android/server/EventLogTags.logtags
index eb2cd0b..d42fe11 100644
--- a/services/core/java/com/android/server/EventLogTags.logtags
+++ b/services/core/java/com/android/server/EventLogTags.logtags
@@ -154,7 +154,8 @@
3110 unknown_sources_enabled (value|1)
# Package Manager critical info
3120 pm_critical_info (msg|3)
-
+# Disk usage stats for verifying quota correctness
+3121 pm_package_stats (manual_time|2|3),(quota_time|2|3),(manual_data|2|2),(quota_data|2|2),(manual_cache|2|2),(quota_cache|2|2)
# ---------------------------
# WindowManagerService.java
diff --git a/services/core/java/com/android/server/HardwarePropertiesManagerService.java b/services/core/java/com/android/server/HardwarePropertiesManagerService.java
index 23cf64a..36a16cd 100644
--- a/services/core/java/com/android/server/HardwarePropertiesManagerService.java
+++ b/services/core/java/com/android/server/HardwarePropertiesManagerService.java
@@ -16,6 +16,8 @@
package com.android.server;
+import android.Manifest;
+import android.app.ActivityManager;
import android.app.admin.DevicePolicyManager;
import android.content.Context;
import android.content.pm.PackageManager;
@@ -80,8 +82,9 @@
*
* @param callingPackage The calling package name.
*
- * @throws SecurityException if something other than the profile or device owner, or the
- * current VR service tries to retrieve information provided by this service.
+ * @throws SecurityException if something other than the profile or device owner, the
+ * current VR service, or a caller holding the {@link Manifest.permission#DEVICE_POWER}
+ * permission tries to retrieve information provided by this service.
*/
private void enforceHardwarePropertiesRetrievalAllowed(String callingPackage)
throws SecurityException {
@@ -100,9 +103,11 @@
final VrManagerInternal vrService = LocalServices.getService(VrManagerInternal.class);
final DevicePolicyManager dpm = mContext.getSystemService(DevicePolicyManager.class);
if (!dpm.isDeviceOwnerApp(callingPackage) && !dpm.isProfileOwnerApp(callingPackage)
- && !vrService.isCurrentVrListener(callingPackage, userId)) {
- throw new SecurityException("The caller is not a device or profile owner or bound "
- + "VrListenerService.");
+ && !vrService.isCurrentVrListener(callingPackage, userId)
+ && mContext.checkCallingOrSelfPermission(Manifest.permission.DEVICE_POWER)
+ != PackageManager.PERMISSION_GRANTED) {
+ throw new SecurityException("The caller is not a device or profile owner, bound "
+ + "VrListenerService, or holding the DEVICE_POWER permission.");
}
}
}
diff --git a/services/core/java/com/android/server/InputMethodManagerService.java b/services/core/java/com/android/server/InputMethodManagerService.java
index 372e9a6..f718fa1 100644
--- a/services/core/java/com/android/server/InputMethodManagerService.java
+++ b/services/core/java/com/android/server/InputMethodManagerService.java
@@ -1666,6 +1666,13 @@
@Override
public void onServiceDisconnected(ComponentName name) {
+ // Note that mContext.unbindService(this) does not trigger this. Hence if we are here the
+ // disconnection is not intended by IMMS (e.g. triggered because the current IMS crashed),
+ // which is irregular but can eventually happen for everyone just by continuing using the
+ // device. Thus it is important to make sure that all the internal states are properly
+ // refreshed when this method is called back. Running
+ // adb install -r <APK that implements the current IME>
+ // would be a good way to trigger such a situation.
synchronized (mMethodMap) {
if (DEBUG) Slog.v(TAG, "Service disconnected: " + name
+ " mCurIntent=" + mCurIntent);
@@ -1677,11 +1684,7 @@
mLastBindTime = SystemClock.uptimeMillis();
mShowRequested = mInputShown;
mInputShown = false;
- if (mCurClient != null) {
- executeOrSendMessage(mCurClient.client, mCaller.obtainMessageIIO(
- MSG_UNBIND_CLIENT, InputMethodClient.UNBIND_REASON_DISCONNECT_IME,
- mCurSeq, mCurClient.client));
- }
+ unbindCurrentClientLocked(InputMethodClient.UNBIND_REASON_DISCONNECT_IME);
}
}
}
diff --git a/services/core/java/com/android/server/LockSettingsService.java b/services/core/java/com/android/server/LockSettingsService.java
index 4d6ffe6..a5552b8 100644
--- a/services/core/java/com/android/server/LockSettingsService.java
+++ b/services/core/java/com/android/server/LockSettingsService.java
@@ -176,12 +176,8 @@
}
@Override
- public void onBootPhase(int phase) {
- if (phase == SystemService.PHASE_ACTIVITY_MANAGER_READY) {
- mLockSettingsService.maybeShowEncryptionNotifications();
- } else if (phase == SystemService.PHASE_BOOT_COMPLETED) {
- // TODO
- }
+ public void onStartUser(int userHandle) {
+ mLockSettingsService.onStartUser(userHandle);
}
@Override
@@ -313,27 +309,25 @@
* If the account is credential-encrypted, show notification requesting the user to unlock
* the device.
*/
- private void maybeShowEncryptionNotifications() {
- final List<UserInfo> users = mUserManager.getUsers();
- for (int i = 0; i < users.size(); i++) {
- UserInfo user = users.get(i);
- UserHandle userHandle = user.getUserHandle();
- final boolean isSecure = mStorage.hasPassword(user.id) || mStorage.hasPattern(user.id);
- if (isSecure && !mUserManager.isUserUnlockingOrUnlocked(userHandle)) {
- if (!user.isManagedProfile()) {
- // When the user is locked, we communicate it loud-and-clear
- // on the lockscreen; we only show a notification below for
- // locked managed profiles.
- } else {
- UserInfo parent = mUserManager.getProfileParent(user.id);
- if (parent != null &&
- mUserManager.isUserUnlockingOrUnlocked(parent.getUserHandle()) &&
- !mUserManager.isQuietModeEnabled(userHandle)) {
- // Only show notifications for managed profiles once their parent
- // user is unlocked.
- showEncryptionNotificationForProfile(userHandle);
- }
- }
+ private void maybeShowEncryptionNotificationForUser(@UserIdInt int userId) {
+ final UserInfo user = mUserManager.getUserInfo(userId);
+ if (!user.isManagedProfile()) {
+ // When the user is locked, we communicate it loud-and-clear
+ // on the lockscreen; we only show a notification below for
+ // locked managed profiles.
+ return;
+ }
+
+ final UserHandle userHandle = user.getUserHandle();
+ final boolean isSecure = mStorage.hasPassword(userId) || mStorage.hasPattern(userId);
+ if (isSecure && !mUserManager.isUserUnlockingOrUnlocked(userHandle)) {
+ UserInfo parent = mUserManager.getProfileParent(userId);
+ if (parent != null &&
+ mUserManager.isUserUnlockingOrUnlocked(parent.getUserHandle()) &&
+ !mUserManager.isQuietModeEnabled(userHandle)) {
+ // Only show notifications for managed profiles once their parent
+ // user is unlocked.
+ showEncryptionNotificationForProfile(userHandle);
}
}
}
@@ -384,7 +378,7 @@
mNotificationManager.notifyAsUser(null, FBE_ENCRYPTED_NOTIFICATION, notification, user);
}
- public void hideEncryptionNotification(UserHandle userHandle) {
+ private void hideEncryptionNotification(UserHandle userHandle) {
if (DEBUG) Slog.v(TAG, "hide encryption notification, user: "+ userHandle.getIdentifier());
mNotificationManager.cancelAsUser(null, FBE_ENCRYPTED_NOTIFICATION, userHandle);
}
@@ -393,6 +387,10 @@
hideEncryptionNotification(new UserHandle(userId));
}
+ public void onStartUser(final int userId) {
+ maybeShowEncryptionNotificationForUser(userId);
+ }
+
public void onUnlockUser(final int userId) {
// Hide notification first, as tie managed profile lock takes time
hideEncryptionNotification(new UserHandle(userId));
diff --git a/services/core/java/com/android/server/NetworkScoreService.java b/services/core/java/com/android/server/NetworkScoreService.java
index 983d039..2f05d0f4 100644
--- a/services/core/java/com/android/server/NetworkScoreService.java
+++ b/services/core/java/com/android/server/NetworkScoreService.java
@@ -34,9 +34,9 @@
import android.net.INetworkScoreCache;
import android.net.INetworkScoreService;
import android.net.NetworkKey;
+import android.net.NetworkScoreManager;
import android.net.NetworkScorerAppManager;
import android.net.NetworkScorerAppManager.NetworkScorerAppData;
-import android.net.NetworkScoreManager;
import android.net.RecommendationRequest;
import android.net.RecommendationResult;
import android.net.ScoredNetwork;
@@ -301,7 +301,8 @@
// If we're not connected at all then create a new connection.
if (mServiceConnection == null) {
- mServiceConnection = new ScoringServiceConnection(componentName);
+ mServiceConnection = new ScoringServiceConnection(componentName,
+ scorerData.packageUid);
}
// Make sure the connection is connected (idempotent)
@@ -325,7 +326,7 @@
@Override
public boolean updateScores(ScoredNetwork[] networks) {
- if (!mNetworkScorerAppManager.isCallerActiveScorer(getCallingUid())) {
+ if (!isCallerActiveScorer(getCallingUid())) {
throw new SecurityException("Caller with UID " + getCallingUid() +
" is not the active scorer.");
}
@@ -380,13 +381,16 @@
}
}
+ private boolean isCallerSystemUid() {
+ // REQUEST_NETWORK_SCORES is a signature only permission.
+ return mContext.checkCallingOrSelfPermission(permission.REQUEST_NETWORK_SCORES) ==
+ PackageManager.PERMISSION_GRANTED;
+ }
+
@Override
public boolean clearScores() {
- // Only the active scorer or the system (who can broadcast BROADCAST_NETWORK_PRIVILEGED)
- // should be allowed to flush all scores.
- if (mNetworkScorerAppManager.isCallerActiveScorer(getCallingUid()) ||
- mContext.checkCallingOrSelfPermission(permission.BROADCAST_NETWORK_PRIVILEGED) ==
- PackageManager.PERMISSION_GRANTED) {
+ // Only the active scorer or the system should be allowed to flush all scores.
+ if (isCallerActiveScorer(getCallingUid()) || isCallerSystemUid()) {
final long token = Binder.clearCallingIdentity();
try {
clearInternal();
@@ -409,20 +413,29 @@
// In the future, should this API be opened to 3p apps, we will need to lock this down and
// figure out another way to streamline the UX.
- // mContext.enforceCallingOrSelfPermission(permission.BROADCAST_NETWORK_PRIVILEGED, TAG);
mContext.enforceCallingOrSelfPermission(permission.SCORE_NETWORKS, TAG);
// Scorers (recommendation providers) are selected and no longer set.
return false;
}
+ /**
+ * Determine whether the application with the given UID is the enabled scorer.
+ *
+ * @param callingUid the UID to check
+ * @return true if the provided UID is the active scorer, false otherwise.
+ */
+ @Override
+ public boolean isCallerActiveScorer(int callingUid) {
+ synchronized (mServiceConnectionLock) {
+ return mServiceConnection != null && mServiceConnection.mScoringAppUid == callingUid;
+ }
+ }
+
@Override
public void disableScoring() {
- // Only the active scorer or the system (who can broadcast BROADCAST_NETWORK_PRIVILEGED)
- // should be allowed to disable scoring.
- if (mNetworkScorerAppManager.isCallerActiveScorer(getCallingUid()) ||
- mContext.checkCallingOrSelfPermission(permission.BROADCAST_NETWORK_PRIVILEGED) ==
- PackageManager.PERMISSION_GRANTED) {
+ // Only the active scorer or the system should be allowed to disable scoring.
+ if (isCallerActiveScorer(getCallingUid()) || isCallerSystemUid()) {
// no-op for now but we could write to the setting if needed.
} else {
throw new SecurityException(
@@ -450,7 +463,7 @@
public void registerNetworkScoreCache(int networkType,
INetworkScoreCache scoreCache,
int filterType) {
- mContext.enforceCallingOrSelfPermission(permission.BROADCAST_NETWORK_PRIVILEGED, TAG);
+ mContext.enforceCallingOrSelfPermission(permission.REQUEST_NETWORK_SCORES, TAG);
final long token = Binder.clearCallingIdentity();
try {
synchronized (mScoreCaches) {
@@ -475,7 +488,7 @@
@Override
public void unregisterNetworkScoreCache(int networkType, INetworkScoreCache scoreCache) {
- mContext.enforceCallingOrSelfPermission(permission.BROADCAST_NETWORK_PRIVILEGED, TAG);
+ mContext.enforceCallingOrSelfPermission(permission.REQUEST_NETWORK_SCORES, TAG);
final long token = Binder.clearCallingIdentity();
try {
synchronized (mScoreCaches) {
@@ -496,7 +509,7 @@
@Override
public RecommendationResult requestRecommendation(RecommendationRequest request) {
- mContext.enforceCallingOrSelfPermission(permission.BROADCAST_NETWORK_PRIVILEGED, TAG);
+ mContext.enforceCallingOrSelfPermission(permission.REQUEST_NETWORK_SCORES, TAG);
throwIfCalledOnMainThread();
final long token = Binder.clearCallingIdentity();
try {
@@ -526,7 +539,7 @@
@Override
public boolean requestScores(NetworkKey[] networks) {
- mContext.enforceCallingOrSelfPermission(permission.BROADCAST_NETWORK_PRIVILEGED, TAG);
+ mContext.enforceCallingOrSelfPermission(permission.REQUEST_NETWORK_SCORES, TAG);
final long token = Binder.clearCallingIdentity();
try {
final INetworkRecommendationProvider provider = getRecommendationProvider();
@@ -624,12 +637,14 @@
private static class ScoringServiceConnection implements ServiceConnection {
private final ComponentName mComponentName;
+ private final int mScoringAppUid;
private volatile boolean mBound = false;
private volatile boolean mConnected = false;
private volatile INetworkRecommendationProvider mRecommendationProvider;
- ScoringServiceConnection(ComponentName componentName) {
+ ScoringServiceConnection(ComponentName componentName, int scoringAppUid) {
mComponentName = componentName;
+ mScoringAppUid = scoringAppUid;
}
void connect(Context context) {
diff --git a/services/core/java/com/android/server/PersistentDataBlockService.java b/services/core/java/com/android/server/PersistentDataBlockService.java
index 8a0d4df..417d375 100644
--- a/services/core/java/com/android/server/PersistentDataBlockService.java
+++ b/services/core/java/com/android/server/PersistentDataBlockService.java
@@ -116,12 +116,12 @@
@Override
public void onStart() {
// Do init on a separate thread, will join in PHASE_ACTIVITY_MANAGER_READY
- FgThread.getHandler().post(() -> {
+ SystemServerInitThreadPool.get().submit(() -> {
enforceChecksumValidity();
formatIfOemUnlockEnabled();
publishBinderService(Context.PERSISTENT_DATA_BLOCK_SERVICE, mService);
mInitDoneSignal.countDown();
- });
+ }, TAG + ".onStart");
}
@Override
diff --git a/services/core/java/com/android/server/SystemServerInitThreadPool.java b/services/core/java/com/android/server/SystemServerInitThreadPool.java
new file mode 100644
index 0000000..d196850
--- /dev/null
+++ b/services/core/java/com/android/server/SystemServerInitThreadPool.java
@@ -0,0 +1,96 @@
+/*
+ * Copyright (C) 2016 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;
+
+import android.os.Build;
+import android.os.Process;
+import android.util.Slog;
+
+import com.android.internal.util.ConcurrentUtils;
+import com.android.internal.util.Preconditions;
+
+import java.util.List;
+import java.util.concurrent.Callable;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Future;
+import java.util.concurrent.TimeUnit;
+
+/**
+ * Thread pool used during initialization of system server.
+ * <p>System services can {@link #submit(Runnable)} tasks for execution during boot.
+ * The pool will be shut down after {@link SystemService#PHASE_BOOT_COMPLETED}.
+ * New tasks <em>should not</em> be submitted afterwards.
+ *
+ * @hide
+ */
+public class SystemServerInitThreadPool {
+ private static final String TAG = SystemServerInitThreadPool.class.getSimpleName();
+ private static final int SHUTDOWN_TIMEOUT_MILLIS = 20000;
+ private static final boolean IS_DEBUGGABLE = Build.IS_DEBUGGABLE;
+
+ private static SystemServerInitThreadPool sInstance;
+
+ private ExecutorService mService = ConcurrentUtils.newFixedThreadPool(2,
+ "system-server-init-thread", Process.THREAD_PRIORITY_FOREGROUND);
+
+ public static synchronized SystemServerInitThreadPool get() {
+ if (sInstance == null) {
+ sInstance = new SystemServerInitThreadPool();
+ }
+ Preconditions.checkState(sInstance.mService != null, "Cannot get " + TAG
+ + " - it has been shut down");
+ return sInstance;
+ }
+
+ public Future<?> submit(Runnable runnable, String description) {
+ if (IS_DEBUGGABLE) {
+ return mService.submit(() -> {
+ Slog.d(TAG, "Started executing " + description);
+ try {
+ runnable.run();
+ } catch (RuntimeException e) {
+ Slog.e(TAG, "Failure in " + description + ": " + e, e);
+ throw e;
+ }
+ Slog.d(TAG, "Finished executing " + description);
+ });
+ }
+ return mService.submit(runnable);
+ }
+
+ static synchronized void shutdown() {
+ if (sInstance != null && sInstance.mService != null) {
+ sInstance.mService.shutdown();
+ boolean terminated;
+ try {
+ terminated = sInstance.mService.awaitTermination(SHUTDOWN_TIMEOUT_MILLIS,
+ TimeUnit.MILLISECONDS);
+ } catch (InterruptedException e) {
+ Thread.currentThread().interrupt();
+ throw new IllegalStateException(TAG + " init interrupted");
+ }
+ List<Runnable> unstartedRunnables = sInstance.mService.shutdownNow();
+ if (!terminated) {
+ throw new IllegalStateException("Cannot shutdown. Unstarted tasks "
+ + unstartedRunnables);
+ }
+ sInstance.mService = null; // Make mService eligible for GC
+ Slog.d(TAG, "Shutdown successful");
+ }
+ }
+
+}
diff --git a/services/core/java/com/android/server/UiModeManagerService.java b/services/core/java/com/android/server/UiModeManagerService.java
index 6ea6fb7..5e1e1e0 100644
--- a/services/core/java/com/android/server/UiModeManagerService.java
+++ b/services/core/java/com/android/server/UiModeManagerService.java
@@ -208,11 +208,13 @@
Settings.Secure.UI_NIGHT_MODE, defaultNightMode);
// Update the initial, static configurations.
- synchronized (this) {
- updateConfigurationLocked();
- sendConfigurationLocked();
- }
+ SystemServerInitThreadPool.get().submit(() -> {
+ synchronized (mLock) {
+ updateConfigurationLocked();
+ sendConfigurationLocked();
+ }
+ }, TAG + ".onStart");
publishBinderService(Context.UI_MODE_SERVICE, mService);
}
diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java
index 87b4221..49c4995 100644
--- a/services/core/java/com/android/server/am/ActivityManagerService.java
+++ b/services/core/java/com/android/server/am/ActivityManagerService.java
@@ -215,6 +215,7 @@
import android.util.ArrayMap;
import android.util.ArraySet;
import android.util.AtomicFile;
+import android.util.BootTimingsTraceLog;
import android.util.DebugUtils;
import android.util.DisplayMetrics;
import android.util.EventLog;
@@ -256,6 +257,7 @@
import java.util.Set;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.atomic.AtomicLong;
+import java.util.concurrent.CountDownLatch;
import dalvik.system.VMRuntime;
@@ -1464,6 +1466,7 @@
MONITOR_THREAD_CPU_USAGE);
final AtomicLong mLastCpuTime = new AtomicLong(0);
final AtomicBoolean mProcessCpuMutexFree = new AtomicBoolean(true);
+ final CountDownLatch mProcessCpuInitLatch = new CountDownLatch(1);
long mLastWriteTime = 0;
@@ -2646,13 +2649,9 @@
}
mTrackingAssociations = "1".equals(SystemProperties.get("debug.track-associations"));
-
mTempConfig.setToDefaults();
mTempConfig.setLocales(LocaleList.getDefault());
mConfigurationSeq = mTempConfig.seq = 1;
-
- mProcessCpuTracker.init();
-
mStackSupervisor = new ActivityStackSupervisor(this);
mStackSupervisor.onConfigurationChanged(mTempConfig);
mKeyguardController = mStackSupervisor.mKeyguardController;
@@ -2666,6 +2665,10 @@
mProcessCpuThread = new Thread("CpuTracker") {
@Override
public void run() {
+ synchronized (mProcessCpuTracker) {
+ mProcessCpuInitLatch.countDown();
+ mProcessCpuTracker.init();
+ }
while (true) {
try {
try {
@@ -2713,6 +2716,16 @@
mAppOpsService.publish(mContext);
Slog.d("AppOps", "AppOpsService published");
LocalServices.addService(ActivityManagerInternal.class, new LocalService());
+ // Wait for the synchronized block started in mProcessCpuThread,
+ // so that any other acccess to mProcessCpuTracker from main thread
+ // will be blocked during mProcessCpuTracker initialization.
+ try {
+ mProcessCpuInitLatch.await();
+ } catch (InterruptedException e) {
+ Slog.wtf(TAG, "Interrupted wait during start", e);
+ Thread.currentThread().interrupt();
+ throw new IllegalStateException("Interrupted wait during start");
+ }
}
void onUserStoppedLocked(int userId) {
@@ -3629,13 +3642,14 @@
* resources like shared libraries and access user-wide resources
*/
if (ArrayUtils.isEmpty(permGids)) {
- gids = new int[2];
+ gids = new int[3];
} else {
- gids = new int[permGids.length + 2];
- System.arraycopy(permGids, 0, gids, 2, permGids.length);
+ gids = new int[permGids.length + 3];
+ System.arraycopy(permGids, 0, gids, 3, permGids.length);
}
gids[0] = UserHandle.getSharedAppGid(UserHandle.getAppId(uid));
- gids[1] = UserHandle.getUserGid(UserHandle.getUserId(uid));
+ gids[1] = UserHandle.getCacheAppGid(UserHandle.getAppId(uid));
+ gids[2] = UserHandle.getUserGid(UserHandle.getUserId(uid));
}
checkTime(startTime, "startProcess: building args");
if (mFactoryTest != FactoryTest.FACTORY_TEST_OFF) {
@@ -4735,7 +4749,7 @@
if (r == null) {
return ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED;
}
- return mWindowManager.getAppOrientation(r.appToken);
+ return r.getRequestedOrientation();
}
}
@@ -12056,6 +12070,12 @@
}
}
+ /**
+ * @deprecated This method is only used by a few internal components and it will soon be
+ * replaced by a proper bug report API (which will be restricted to a few, pre-defined apps).
+ * No new code should be calling it.
+ */
+ @Deprecated
public void requestBugReport(int bugreportType) {
String extraOptions = null;
switch (bugreportType) {
@@ -13205,7 +13225,8 @@
}
}
- public void systemReady(final Runnable goingCallback) {
+ public void systemReady(final Runnable goingCallback, BootTimingsTraceLog traceLog) {
+ traceLog.traceBegin("PhaseActivityManagerReady");
synchronized(this) {
if (mSystemReady) {
// If we're done calling all the receivers, run the next "boot phase" passed in
@@ -13302,7 +13323,7 @@
}
if (goingCallback != null) goingCallback.run();
-
+ traceLog.traceBegin("ActivityManagerStartApps");
mBatteryStatsService.noteEvent(BatteryStats.HistoryItem.EVENT_USER_RUNNING_START,
Integer.toString(currentUserId), currentUserId);
mBatteryStatsService.noteEvent(BatteryStats.HistoryItem.EVENT_USER_FOREGROUND_START,
@@ -13377,6 +13398,8 @@
}
mStackSupervisor.resumeFocusedStackTopActivityLocked();
mUserController.sendUserSwitchBroadcastsLocked(-1, currentUserId);
+ traceLog.traceEnd(); // ActivityManagerStartApps
+ traceLog.traceEnd(); // PhaseActivityManagerReady
}
}
@@ -22638,6 +22661,11 @@
}
}
+ @Override
+ public int restartUserInBackground(final int userId) {
+ return mUserController.restartUser(userId, /* foreground */ false);
+ }
+
/**
* Attach an agent to the specified process (proces name or PID)
*/
diff --git a/services/core/java/com/android/server/am/ActivityMetricsLogger.java b/services/core/java/com/android/server/am/ActivityMetricsLogger.java
index 32dec96..3f166fe 100644
--- a/services/core/java/com/android/server/am/ActivityMetricsLogger.java
+++ b/services/core/java/com/android/server/am/ActivityMetricsLogger.java
@@ -17,6 +17,7 @@
import android.os.SystemClock;
import android.util.Slog;
+import com.android.internal.logging.LogBuilder;
import com.android.internal.logging.MetricsLogger;
import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
@@ -170,6 +171,13 @@
processRunning);
MetricsLogger.action(mContext, MetricsEvent.APP_TRANSITION_DEVICE_UPTIME_SECONDS,
(int) (SystemClock.uptimeMillis() / 1000));
+
+ LogBuilder builder = new LogBuilder();
+ builder.addTaggedData(MetricsEvent.APP_TRANSITION_COMPONENT_NAME, componentName);
+ builder.addTaggedData(MetricsEvent.APP_TRANSITION_PROCESS_RUNNING, processRunning ? 1 : 0);
+ builder.addTaggedData(MetricsEvent.APP_TRANSITION_DEVICE_UPTIME_SECONDS,
+ SystemClock.uptimeMillis() / 1000);
+ MetricsLogger.action(builder);
}
/**
diff --git a/services/core/java/com/android/server/am/ActivityRecord.java b/services/core/java/com/android/server/am/ActivityRecord.java
index ef19700..0e4ab96 100644
--- a/services/core/java/com/android/server/am/ActivityRecord.java
+++ b/services/core/java/com/android/server/am/ActivityRecord.java
@@ -21,17 +21,26 @@
import static android.app.ActivityManager.StackId.FREEFORM_WORKSPACE_STACK_ID;
import static android.app.ActivityManager.StackId.HOME_STACK_ID;
import static android.app.ActivityManager.StackId.PINNED_STACK_ID;
+import static android.content.Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS;
import static android.content.pm.ActivityInfo.CONFIG_ORIENTATION;
import static android.content.pm.ActivityInfo.CONFIG_SCREEN_LAYOUT;
import static android.content.pm.ActivityInfo.CONFIG_SCREEN_SIZE;
import static android.content.pm.ActivityInfo.CONFIG_SMALLEST_SCREEN_SIZE;
+import static android.content.pm.ActivityInfo.FLAG_EXCLUDE_FROM_RECENTS;
+import static android.content.pm.ActivityInfo.FLAG_IMMERSIVE;
+import static android.content.pm.ActivityInfo.FLAG_MULTIPROCESS;
import static android.content.pm.ActivityInfo.FLAG_SHOW_FOR_ALL_USERS;
import static android.content.pm.ActivityInfo.FLAG_ALWAYS_FOCUSABLE;
+import static android.content.pm.ActivityInfo.FLAG_STATE_NOT_NEEDED;
+import static android.content.pm.ActivityInfo.LAUNCH_MULTIPLE;
+import static android.content.pm.ActivityInfo.LAUNCH_SINGLE_TOP;
import static android.content.pm.ActivityInfo.RESIZE_MODE_FORCE_RESIZEABLE;
import static android.content.pm.ActivityInfo.RESIZE_MODE_RESIZEABLE;
import static android.content.pm.ActivityInfo.RESIZE_MODE_RESIZEABLE_AND_PIPABLE;
import static android.content.pm.ActivityInfo.RESIZE_MODE_RESIZEABLE_VIA_SDK_VERSION;
import static android.content.pm.ActivityInfo.RESIZE_MODE_UNRESIZEABLE;
+import static android.os.Build.VERSION_CODES.HONEYCOMB;
+import static android.os.Process.SYSTEM_UID;
import static android.view.Display.DEFAULT_DISPLAY;
import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_CONFIGURATION;
import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_SAVED_STATE;
@@ -92,6 +101,8 @@
import com.android.server.AttributeCache;
import com.android.server.am.ActivityStack.ActivityState;
import com.android.server.am.ActivityStackSupervisor.ActivityContainer;
+import com.android.server.wm.AppWindowContainerController;
+import com.android.server.wm.AppWindowContainerListener;
import java.io.File;
import java.io.IOException;
@@ -110,7 +121,7 @@
/**
* An entry in the history stack, representing an activity.
*/
-final class ActivityRecord {
+final class ActivityRecord implements AppWindowContainerListener {
private static final String TAG = TAG_WITH_CLASS_NAME ? "ActivityRecord" : TAG_AM;
private static final String TAG_CONFIGURATION = TAG + POSTFIX_CONFIGURATION;
private static final String TAG_SAVED_STATE = TAG + POSTFIX_SAVED_STATE;
@@ -135,6 +146,7 @@
final ActivityManagerService service; // owner
final IApplicationToken.Stub appToken; // window manager token
+ AppWindowContainerController mWindowContainerController;
final ActivityInfo info; // all about me
final ApplicationInfo appInfo; // information about activity's app
final int launchedFromUid; // always the uid who started the activity.
@@ -150,7 +162,7 @@
final boolean stateNotNeeded; // As per ActivityInfo.flags
boolean fullscreen; // covers the full screen?
final boolean noDisplay; // activity is not displayed?
- final boolean componentSpecified; // did caller specify an explicit component?
+ private final boolean componentSpecified; // did caller specify an explicit component?
final boolean rootVoiceInteraction; // was this the root activity of a voice interaction?
static final int APPLICATION_ACTIVITY_TYPE = 0;
@@ -158,18 +170,18 @@
static final int RECENTS_ACTIVITY_TYPE = 2;
int mActivityType;
- CharSequence nonLocalizedLabel; // the label information from the package mgr.
- int labelRes; // the label information from the package mgr.
- int icon; // resource identifier of activity's icon.
- int logo; // resource identifier of activity's logo.
- int theme; // resource identifier of activity's theme.
- int realTheme; // actual theme resource we will use, never 0.
- int windowFlags; // custom window flags for preview window.
+ private CharSequence nonLocalizedLabel; // the label information from the package mgr.
+ private int labelRes; // the label information from the package mgr.
+ private int icon; // resource identifier of activity's icon.
+ private int logo; // resource identifier of activity's logo.
+ private int theme; // resource identifier of activity's theme.
+ private int realTheme; // actual theme resource we will use, never 0.
+ private int windowFlags; // custom window flags for preview window.
TaskRecord task; // the task this is in.
- long createTime = System.currentTimeMillis();
+ private long createTime = System.currentTimeMillis();
long displayStartTime; // when we started launching this activity
long fullyDrawnStartTime; // when we started launching this activity
- long startTime; // last time this activity was started
+ private long startTime; // last time this activity was started
long lastVisibleTime; // last time this activity became visible
long cpuTimeAtResume; // the cpu time of host process at the time of resuming activity
long pauseTime; // last time we started pausing the activity
@@ -542,70 +554,9 @@
static class Token extends IApplicationToken.Stub {
private final WeakReference<ActivityRecord> weakActivity;
- private final ActivityManagerService mService;
- Token(ActivityRecord activity, ActivityManagerService service) {
+ Token(ActivityRecord activity) {
weakActivity = new WeakReference<>(activity);
- mService = service;
- }
-
- @Override
- public void windowsDrawn() {
- synchronized (mService) {
- ActivityRecord r = tokenToActivityRecordLocked(this);
- if (r != null) {
- r.windowsDrawnLocked();
- }
- }
- }
-
- @Override
- public void windowsVisible() {
- synchronized (mService) {
- ActivityRecord r = tokenToActivityRecordLocked(this);
- if (r != null) {
- r.windowsVisibleLocked();
- }
- }
- }
-
- @Override
- public void windowsGone() {
- synchronized (mService) {
- ActivityRecord r = tokenToActivityRecordLocked(this);
- if (r != null) {
- if (DEBUG_SWITCH) Log.v(TAG_SWITCH, "windowsGone(): " + r);
- r.nowVisible = false;
- }
- }
- }
-
- @Override
- public boolean keyDispatchingTimedOut(String reason) {
- ActivityRecord r;
- ActivityRecord anrActivity;
- ProcessRecord anrApp;
- synchronized (mService) {
- r = tokenToActivityRecordLocked(this);
- if (r == null) {
- return false;
- }
- anrActivity = r.getWaitingHistoryRecordLocked();
- anrApp = r.app;
- }
- return mService.inputDispatchingTimedOut(anrApp, anrActivity, r, false, reason);
- }
-
- @Override
- public long getKeyDispatchingTimeout() {
- synchronized (mService) {
- ActivityRecord r = tokenToActivityRecordLocked(this);
- if (r == null) {
- return 0;
- }
- r = r.getWaitingHistoryRecordLocked();
- return ActivityManagerService.getInputDispatchingTimeoutLocked(r);
- }
}
private static ActivityRecord tokenToActivityRecordLocked(Token token) {
@@ -652,7 +603,7 @@
ActivityStackSupervisor supervisor,
ActivityContainer container, ActivityOptions options, ActivityRecord sourceRecord) {
service = _service;
- appToken = new Token(this, service);
+ appToken = new Token(this);
info = aInfo;
launchedFromUid = _launchedFromUid;
launchedFromPackage = _launchedFromPackage;
@@ -700,97 +651,110 @@
}
}
- // This starts out true, since the initial state of an activity
- // is that we have everything, and we shouldn't never consider it
- // lacking in state to be removed if it dies.
+ // This starts out true, since the initial state of an activity is that we have everything,
+ // and we shouldn't never consider it lacking in state to be removed if it dies.
haveState = true;
- if (aInfo != null) {
- // If the class name in the intent doesn't match that of the target, this is
- // probably an alias. We have to create a new ComponentName object to keep track
- // of the real activity name, so that FLAG_ACTIVITY_CLEAR_TOP is handled properly.
- if (aInfo.targetActivity == null
- || (aInfo.targetActivity.equals(_intent.getComponent().getClassName())
- && (aInfo.launchMode == ActivityInfo.LAUNCH_MULTIPLE
- || aInfo.launchMode == ActivityInfo.LAUNCH_SINGLE_TOP))) {
- realActivity = _intent.getComponent();
- } else {
- realActivity = new ComponentName(aInfo.packageName, aInfo.targetActivity);
- }
- taskAffinity = aInfo.taskAffinity;
- stateNotNeeded = (aInfo.flags&
- ActivityInfo.FLAG_STATE_NOT_NEEDED) != 0;
- appInfo = aInfo.applicationInfo;
- nonLocalizedLabel = aInfo.nonLocalizedLabel;
- labelRes = aInfo.labelRes;
- if (nonLocalizedLabel == null && labelRes == 0) {
- ApplicationInfo app = aInfo.applicationInfo;
- nonLocalizedLabel = app.nonLocalizedLabel;
- labelRes = app.labelRes;
- }
- icon = aInfo.getIconResource();
- logo = aInfo.getLogoResource();
- theme = aInfo.getThemeResource();
- realTheme = theme;
- if (realTheme == 0) {
- realTheme = aInfo.applicationInfo.targetSdkVersion
- < Build.VERSION_CODES.HONEYCOMB
- ? android.R.style.Theme
- : android.R.style.Theme_Holo;
- }
- if ((aInfo.flags&ActivityInfo.FLAG_HARDWARE_ACCELERATED) != 0) {
- windowFlags |= LayoutParams.FLAG_HARDWARE_ACCELERATED;
- }
- if ((aInfo.flags&ActivityInfo.FLAG_MULTIPROCESS) != 0
- && _caller != null
- && (aInfo.applicationInfo.uid == Process.SYSTEM_UID
- || aInfo.applicationInfo.uid == _caller.info.uid)) {
- processName = _caller.processName;
- } else {
- processName = aInfo.processName;
- }
-
- if (intent != null && (aInfo.flags & ActivityInfo.FLAG_EXCLUDE_FROM_RECENTS) != 0) {
- intent.addFlags(Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS);
- }
-
- packageName = aInfo.applicationInfo.packageName;
- launchMode = aInfo.launchMode;
-
- AttributeCache.Entry ent = AttributeCache.instance().get(packageName,
- realTheme, com.android.internal.R.styleable.Window, userId);
- final boolean translucent = ent != null && (ent.array.getBoolean(
- com.android.internal.R.styleable.Window_windowIsTranslucent, false)
- || (!ent.array.hasValue(
- com.android.internal.R.styleable.Window_windowIsTranslucent)
- && ent.array.getBoolean(
- com.android.internal.R.styleable.Window_windowSwipeToDismiss,
- false)));
- fullscreen = ent != null && !ent.array.getBoolean(
- com.android.internal.R.styleable.Window_windowIsFloating, false)
- && !translucent;
- noDisplay = ent != null && ent.array.getBoolean(
- com.android.internal.R.styleable.Window_windowNoDisplay, false);
-
- setActivityType(_componentSpecified, _launchedFromUid, _intent, sourceRecord);
-
- immersive = (aInfo.flags & ActivityInfo.FLAG_IMMERSIVE) != 0;
-
- requestedVrComponent = (aInfo.requestedVrComponent == null) ?
- null : ComponentName.unflattenFromString(aInfo.requestedVrComponent);
+ // If the class name in the intent doesn't match that of the target, this is
+ // probably an alias. We have to create a new ComponentName object to keep track
+ // of the real activity name, so that FLAG_ACTIVITY_CLEAR_TOP is handled properly.
+ if (aInfo.targetActivity == null
+ || (aInfo.targetActivity.equals(_intent.getComponent().getClassName())
+ && (aInfo.launchMode == LAUNCH_MULTIPLE
+ || aInfo.launchMode == LAUNCH_SINGLE_TOP))) {
+ realActivity = _intent.getComponent();
} else {
- realActivity = null;
- taskAffinity = null;
- stateNotNeeded = false;
- appInfo = null;
- processName = null;
- packageName = null;
- fullscreen = true;
- noDisplay = false;
- mActivityType = APPLICATION_ACTIVITY_TYPE;
- immersive = false;
- requestedVrComponent = null;
+ realActivity = new ComponentName(aInfo.packageName, aInfo.targetActivity);
}
+ taskAffinity = aInfo.taskAffinity;
+ stateNotNeeded = (aInfo.flags & FLAG_STATE_NOT_NEEDED) != 0;
+ appInfo = aInfo.applicationInfo;
+ nonLocalizedLabel = aInfo.nonLocalizedLabel;
+ labelRes = aInfo.labelRes;
+ if (nonLocalizedLabel == null && labelRes == 0) {
+ ApplicationInfo app = aInfo.applicationInfo;
+ nonLocalizedLabel = app.nonLocalizedLabel;
+ labelRes = app.labelRes;
+ }
+ icon = aInfo.getIconResource();
+ logo = aInfo.getLogoResource();
+ theme = aInfo.getThemeResource();
+ realTheme = theme;
+ if (realTheme == 0) {
+ realTheme = aInfo.applicationInfo.targetSdkVersion < HONEYCOMB
+ ? android.R.style.Theme : android.R.style.Theme_Holo;
+ }
+ if ((aInfo.flags & ActivityInfo.FLAG_HARDWARE_ACCELERATED) != 0) {
+ windowFlags |= LayoutParams.FLAG_HARDWARE_ACCELERATED;
+ }
+ if ((aInfo.flags & FLAG_MULTIPROCESS) != 0 && _caller != null
+ && (aInfo.applicationInfo.uid == SYSTEM_UID
+ || aInfo.applicationInfo.uid == _caller.info.uid)) {
+ processName = _caller.processName;
+ } else {
+ processName = aInfo.processName;
+ }
+
+ if ((aInfo.flags & FLAG_EXCLUDE_FROM_RECENTS) != 0) {
+ intent.addFlags(FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS);
+ }
+
+ packageName = aInfo.applicationInfo.packageName;
+ launchMode = aInfo.launchMode;
+
+ AttributeCache.Entry ent = AttributeCache.instance().get(packageName,
+ realTheme, com.android.internal.R.styleable.Window, userId);
+ final boolean translucent = ent != null && (ent.array.getBoolean(
+ com.android.internal.R.styleable.Window_windowIsTranslucent, false)
+ || (!ent.array.hasValue(
+ com.android.internal.R.styleable.Window_windowIsTranslucent)
+ && ent.array.getBoolean(
+ com.android.internal.R.styleable.Window_windowSwipeToDismiss,
+ false)));
+ fullscreen = ent != null && !ent.array.getBoolean(
+ com.android.internal.R.styleable.Window_windowIsFloating, false) && !translucent;
+ noDisplay = ent != null && ent.array.getBoolean(
+ com.android.internal.R.styleable.Window_windowNoDisplay, false);
+
+ setActivityType(_componentSpecified, _launchedFromUid, _intent, sourceRecord);
+
+ immersive = (aInfo.flags & FLAG_IMMERSIVE) != 0;
+
+ requestedVrComponent = (aInfo.requestedVrComponent == null) ?
+ null : ComponentName.unflattenFromString(aInfo.requestedVrComponent);
+ }
+
+ void createWindowContainer() {
+ if (mWindowContainerController != null) {
+ throw new IllegalArgumentException("Window container=" + mWindowContainerController
+ + " already created for r=" + this);
+
+ }
+
+ inHistory = true;
+
+ task.updateOverrideConfigurationFromLaunchBounds();
+
+ mWindowContainerController = new AppWindowContainerController(appToken, this, task.taskId,
+ Integer.MAX_VALUE /* add on top */, info.screenOrientation, fullscreen,
+ (info.flags & FLAG_SHOW_FOR_ALL_USERS) != 0, info.configChanges,
+ task.voiceSession != null, mLaunchTaskBehind, isAlwaysFocusable(),
+ appInfo.targetSdkVersion, mRotationAnimationHint,
+ ActivityManagerService.getInputDispatchingTimeoutLocked(this) * 1000000L);
+
+ task.addActivityToTop(this);
+
+ onOverrideConfigurationSent();
+ }
+
+ void removeWindowContainer() {
+ mWindowContainerController.removeContainer(getDisplayId());
+ }
+
+ // TODO: Remove once task record is converted to use controller in which case we can use
+ // positionChildAt()
+ void positionWindowContainerAt(int index) {
+ mWindowContainerController.positionAt(task.taskId, index);
}
private boolean isHomeIntent(Intent intent) {
@@ -890,12 +854,6 @@
return true;
}
- void putInHistory() {
- if (!inHistory) {
- inHistory = true;
- }
- }
-
void takeFromHistory() {
if (inHistory) {
inHistory = false;
@@ -931,7 +889,7 @@
return (info.persistableMode == ActivityInfo.PERSIST_ROOT_ONLY ||
info.persistableMode == ActivityInfo.PERSIST_ACROSS_REBOOTS) &&
(intent == null ||
- (intent.getFlags() & Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS) == 0);
+ (intent.getFlags() & FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS) == 0);
}
boolean isFocusable() {
@@ -1222,14 +1180,14 @@
void pauseKeyDispatchingLocked() {
if (!keysPaused) {
keysPaused = true;
- service.mWindowManager.pauseKeyDispatching(appToken);
+ mWindowContainerController.pauseKeyDispatching();
}
}
void resumeKeyDispatchingLocked() {
if (keysPaused) {
keysPaused = false;
- service.mWindowManager.resumeKeyDispatching(appToken);
+ mWindowContainerController.resumeKeyDispatching();
}
}
@@ -1277,7 +1235,7 @@
return null;
}
- final float scale;
+ float scale = 0;
if (DEBUG_SCREENSHOTS) Slog.d(TAG_SCREENSHOTS, "\tTaking screenshot");
// When this flag is set, we currently take the fullscreen screenshot of the activity but
@@ -1288,17 +1246,21 @@
scale = service.mFullscreenThumbnailScale;
}
- return service.mWindowManager.screenshotApplications(appToken, DEFAULT_DISPLAY, w, h,
- scale);
+ return mWindowContainerController.screenshotApplications(getDisplayId(), w, h, scale);
}
+ void setVisibility(boolean visible) {
+ mWindowContainerController.setVisibility(visible);
+ }
+
+ // TODO: Look into merging with #setVisibility()
void setVisible(boolean newVisible) {
visible = newVisible;
if (!visible && mUpdateTaskThumbnailWhenHidden) {
updateThumbnailLocked(screenshotActivityLocked(), null /* description */);
mUpdateTaskThumbnailWhenHidden = false;
}
- service.mWindowManager.setAppVisibility(appToken, visible);
+ mWindowContainerController.setVisibility(visible);
final ArrayList<ActivityContainer> containers = mChildContainers;
for (int containerNdx = containers.size() - 1; containerNdx >= 0; --containerNdx) {
final ActivityContainer container = containers.get(containerNdx);
@@ -1307,6 +1269,14 @@
mStackSupervisor.mAppVisibilitiesChangedSinceLastPause = true;
}
+ void notifyAppResumed(boolean wasStopped, boolean allowSavedSurface) {
+ mWindowContainerController.notifyAppResumed(wasStopped, allowSavedSurface);
+ }
+
+ void notifyUnknownVisibilityLaunched() {
+ mWindowContainerController.notifyUnknownVisibilityLaunched();
+ }
+
/**
* @return true if the input activity should be made visible, ignoring any effect Keyguard
* might have on the visibility
@@ -1458,6 +1428,7 @@
service.notifyTaskPersisterLocked(task, false);
}
if (DEBUG_SAVED_STATE) Slog.i(TAG_SAVED_STATE, "Saving icicle of " + this + ": " + icicle);
+
if (newIcicle != null) {
// If icicle is null, this is happening due to a timeout, so we haven't really saved
// the state.
@@ -1472,7 +1443,7 @@
stopped = true;
state = ActivityState.STOPPED;
- service.mWindowManager.notifyAppStopped(appToken);
+ mWindowContainerController.notifyAppStopped();
if (stack.getVisibleBehindActivity() == this) {
mStackSupervisor.requestVisibleBehindLocked(this, false /* visible */);
@@ -1536,14 +1507,14 @@
public void startFreezingScreenLocked(ProcessRecord app, int configChanges) {
if (mayFreezeScreenLocked(app)) {
- service.mWindowManager.startAppFreezingScreen(appToken, configChanges);
+ mWindowContainerController.startFreezingScreen(configChanges);
}
}
public void stopFreezingScreenLocked(boolean force) {
if (force || frozenBeforeDestroy) {
frozenBeforeDestroy = false;
- service.mWindowManager.stopAppFreezingScreen(appToken, force);
+ mWindowContainerController.stopFreezingScreen(force);
}
}
@@ -1617,48 +1588,73 @@
stack.mLaunchStartTime = 0;
}
- void windowsDrawnLocked() {
- mStackSupervisor.mActivityMetricsLogger.notifyWindowsDrawn();
- if (displayStartTime != 0) {
- reportLaunchTimeLocked(SystemClock.uptimeMillis());
- }
- mStackSupervisor.sendWaitingVisibleReportLocked(this);
- startTime = 0;
- finishLaunchTickingLocked();
- if (task != null) {
- task.hasBeenVisible = true;
- }
- }
-
- void windowsVisibleLocked() {
- mStackSupervisor.reportActivityVisibleLocked(this);
- if (DEBUG_SWITCH) Log.v(TAG_SWITCH, "windowsVisibleLocked(): " + this);
- if (!nowVisible) {
- nowVisible = true;
- lastVisibleTime = SystemClock.uptimeMillis();
- if (!idle) {
- // Instead of doing the full stop routine here, let's just hide any activities
- // we now can, and let them stop when the normal idle happens.
- mStackSupervisor.processStoppingActivitiesLocked(false);
- } else {
- // If this activity was already idle, then we now need to make sure we perform
- // the full stop of any activities that are waiting to do so. This is because
- // we won't do that while they are still waiting for this one to become visible.
- final int size = mStackSupervisor.mWaitingVisibleActivities.size();
- if (size > 0) {
- for (int i = 0; i < size; i++) {
- ActivityRecord r = mStackSupervisor.mWaitingVisibleActivities.get(i);
- if (DEBUG_SWITCH) Log.v(TAG_SWITCH, "Was waiting for visible: " + r);
- }
- mStackSupervisor.mWaitingVisibleActivities.clear();
- mStackSupervisor.scheduleIdleLocked();
- }
+ @Override
+ public void onWindowsDrawn() {
+ synchronized (service) {
+ mStackSupervisor.mActivityMetricsLogger.notifyWindowsDrawn();
+ if (displayStartTime != 0) {
+ reportLaunchTimeLocked(SystemClock.uptimeMillis());
}
- service.scheduleAppGcsLocked();
+ mStackSupervisor.sendWaitingVisibleReportLocked(this);
+ startTime = 0;
+ finishLaunchTickingLocked();
+ if (task != null) {
+ task.hasBeenVisible = true;
+ }
}
}
- ActivityRecord getWaitingHistoryRecordLocked() {
+ @Override
+ public void onWindowsVisible() {
+ synchronized (service) {
+ mStackSupervisor.reportActivityVisibleLocked(this);
+ if (DEBUG_SWITCH) Log.v(TAG_SWITCH, "windowsVisibleLocked(): " + this);
+ if (!nowVisible) {
+ nowVisible = true;
+ lastVisibleTime = SystemClock.uptimeMillis();
+ if (!idle) {
+ // Instead of doing the full stop routine here, let's just hide any activities
+ // we now can, and let them stop when the normal idle happens.
+ mStackSupervisor.processStoppingActivitiesLocked(false);
+ } else {
+ // If this activity was already idle, then we now need to make sure we perform
+ // the full stop of any activities that are waiting to do so. This is because
+ // we won't do that while they are still waiting for this one to become visible.
+ final int size = mStackSupervisor.mWaitingVisibleActivities.size();
+ if (size > 0) {
+ for (int i = 0; i < size; i++) {
+ ActivityRecord r = mStackSupervisor.mWaitingVisibleActivities.get(i);
+ if (DEBUG_SWITCH) Log.v(TAG_SWITCH, "Was waiting for visible: " + r);
+ }
+ mStackSupervisor.mWaitingVisibleActivities.clear();
+ mStackSupervisor.scheduleIdleLocked();
+ }
+ }
+ service.scheduleAppGcsLocked();
+ }
+ }
+ }
+
+ @Override
+ public void onWindowsGone() {
+ synchronized (service) {
+ if (DEBUG_SWITCH) Log.v(TAG_SWITCH, "windowsGone(): " + this);
+ nowVisible = false;
+ }
+ }
+
+ @Override
+ public boolean keyDispatchingTimedOut(String reason) {
+ ActivityRecord anrActivity;
+ ProcessRecord anrApp;
+ synchronized (service) {
+ anrActivity = getWaitingHistoryRecordLocked();
+ anrApp = app;
+ }
+ return service.inputDispatchingTimedOut(anrApp, anrActivity, this, false, reason);
+ }
+
+ private ActivityRecord getWaitingHistoryRecordLocked() {
// First find the real culprit... if this activity is waiting for
// another activity to start or has stopped, then the key dispatching
// timeout should not be caused by this.
@@ -1800,25 +1796,40 @@
void showStartingWindow(ActivityRecord prev, boolean createIfNeeded) {
final CompatibilityInfo compatInfo =
service.compatibilityInfoForPackageLocked(info.applicationInfo);
- final boolean shown = service.mWindowManager.setAppStartingWindow(
- appToken, packageName, theme, compatInfo, nonLocalizedLabel, labelRes, icon,
- logo, windowFlags, prev != null ? prev.appToken : null, createIfNeeded);
+ final boolean shown = mWindowContainerController.addStartingWindow(packageName, theme,
+ compatInfo, nonLocalizedLabel, labelRes, icon, logo, windowFlags,
+ prev != null ? prev.appToken : null, createIfNeeded);
if (shown) {
mStartingWindowState = STARTING_WINDOW_SHOWN;
}
}
+ void removeOrphanedStartingWindow(boolean behindFullscreenActivity) {
+ if (state == ActivityState.INITIALIZING
+ && mStartingWindowState == STARTING_WINDOW_SHOWN
+ && behindFullscreenActivity) {
+ if (DEBUG_VISIBILITY) Slog.w(TAG_VISIBILITY, "Found orphaned starting window " + this);
+ mStartingWindowState = STARTING_WINDOW_REMOVED;
+ mWindowContainerController.removeStartingWindow();
+ }
+ }
+
+ int getRequestedOrientation() {
+ return mWindowContainerController.getOrientation();
+ }
+
void setRequestedOrientation(int requestedOrientation) {
if (task != null && (!task.mFullscreen || !task.getStack().mFullscreen)) {
// Fixed screen orientation isn't supported when activities aren't in full screen mode.
return;
}
- service.mWindowManager.setAppOrientation(appToken, requestedOrientation);
final int displayId = getDisplayId();
- final Configuration config = service.mWindowManager.updateOrientationFromAppTokens(
- mStackSupervisor.getDisplayOverrideConfiguration(displayId),
- mayFreezeScreenLocked(app) ? appToken : null, displayId);
+ final Configuration displayConfig =
+ mStackSupervisor.getDisplayOverrideConfiguration(displayId);
+
+ final Configuration config = mWindowContainerController.setOrientation(requestedOrientation,
+ displayId, displayConfig, mayFreezeScreenLocked(app));
if (config != null) {
frozenBeforeDestroy = true;
if (!service.updateDisplayOverrideConfigurationLocked(config, this,
diff --git a/services/core/java/com/android/server/am/ActivityStack.java b/services/core/java/com/android/server/am/ActivityStack.java
index beeadac..f7c3cea 100644
--- a/services/core/java/com/android/server/am/ActivityStack.java
+++ b/services/core/java/com/android/server/am/ActivityStack.java
@@ -61,8 +61,6 @@
import static com.android.server.am.ActivityManagerDebugConfig.TAG_WITH_CLASS_NAME;
import static com.android.server.am.ActivityRecord.APPLICATION_ACTIVITY_TYPE;
import static com.android.server.am.ActivityRecord.HOME_ACTIVITY_TYPE;
-import static com.android.server.am.ActivityRecord.STARTING_WINDOW_REMOVED;
-import static com.android.server.am.ActivityRecord.STARTING_WINDOW_SHOWN;
import static com.android.server.am.ActivityStackSupervisor.FindTaskResult;
import static com.android.server.am.ActivityStackSupervisor.ON_TOP;
import static com.android.server.am.ActivityStackSupervisor.PRESERVE_WINDOWS;
@@ -1392,24 +1390,6 @@
return null;
}
- ActivityStack getNextFocusableStackLocked() {
- ArrayList<ActivityStack> stacks = mStacks;
- final ActivityRecord parent = mActivityContainer.mParentActivity;
- if (parent != null) {
- stacks = parent.getStack().mStacks;
- }
- if (stacks != null) {
- for (int i = stacks.size() - 1; i >= 0; --i) {
- ActivityStack stack = stacks.get(i);
- if (stack != this && stack.isFocusable()
- && stack.getStackVisibilityLocked(null) != STACK_INVISIBLE) {
- return stack;
- }
- }
- }
- return null;
- }
-
/** Returns true if the stack contains a fullscreen task. */
private boolean hasFullscreenTask() {
for (int i = mTaskHistory.size() - 1; i >= 0; --i) {
@@ -2046,15 +2026,7 @@
continue;
}
- if (r.state == ActivityState.INITIALIZING
- && r.mStartingWindowState == STARTING_WINDOW_SHOWN
- && behindFullscreenActivity) {
- if (DEBUG_VISIBILITY) Slog.w(TAG_VISIBILITY,
- "Found orphaned starting window " + r);
- r.mStartingWindowState = STARTING_WINDOW_REMOVED;
- mWindowManager.removeAppStartingWindow(r.appToken);
- }
-
+ r.removeOrphanedStartingWindow(behindFullscreenActivity);
behindFullscreenActivity |= r.fullscreen;
}
}
@@ -2108,9 +2080,15 @@
return false;
}
- ActivityRecord parent = mActivityContainer.mParentActivity;
- if ((parent != null && parent.state != ActivityState.RESUMED) ||
- !mActivityContainer.isAttachedLocked()) {
+ // Find the topmost activity in this stack that is not finishing.
+ final ActivityRecord next = topRunningActivityLocked();
+
+ final boolean hasRunningActivity = next != null;
+
+ final ActivityRecord parent = mActivityContainer.mParentActivity;
+ final boolean isParentNotResumed = parent != null && parent.state != ActivityState.RESUMED;
+ if (hasRunningActivity
+ && (isParentNotResumed || !mActivityContainer.isAttachedLocked())) {
// Do not resume this stack if its parent is not resumed.
// TODO: If in a loop, make sure that parent stack resumeTopActivity is called 1st.
return false;
@@ -2118,33 +2096,14 @@
mStackSupervisor.cancelInitializingActivities();
- // Find the first activity that is not finishing.
- final ActivityRecord next = topRunningActivityLocked();
-
// Remember how we'll process this pause/resume situation, and ensure
// that the state is reset however we wind up proceeding.
final boolean userLeaving = mStackSupervisor.mUserLeaving;
mStackSupervisor.mUserLeaving = false;
- final TaskRecord prevTask = prev != null ? prev.task : null;
- if (next == null) {
- // There are no more activities!
- final String reason = "noMoreActivities";
- if (!mFullscreen && adjustFocusToNextFocusableStackLocked(reason)) {
- // Try to move focus to the next visible stack with a running activity if this
- // stack is not covering the entire screen.
- return mStackSupervisor.resumeFocusedStackTopActivityLocked(
- mStackSupervisor.getFocusedStack(), prev, null);
- }
-
- // Let's just start up the Launcher...
- ActivityOptions.abort(options);
- if (DEBUG_STATES) Slog.d(TAG_STATES,
- "resumeTopActivityLocked: No more activities go home");
- if (DEBUG_STACK) mStackSupervisor.validateTopActivitiesLocked();
- // Only resume home if on home display
- return isOnHomeDisplay() &&
- mStackSupervisor.resumeHomeStackTask(prev, reason);
+ if (!hasRunningActivity) {
+ // There are no activities left in the stack, let's look somewhere else.
+ return resumeTopActivityInNextFocusableStack(prev, options, "noMoreActivities");
}
next.delayedResume = false;
@@ -2162,6 +2121,7 @@
}
final TaskRecord nextTask = next.task;
+ final TaskRecord prevTask = prev != null ? prev.task : null;
if (prevTask != null && prevTask.getStack() == this &&
prevTask.isOverHomeStack() && prev.finishing && prev.frontOfTask) {
if (DEBUG_STACK) mStackSupervisor.validateTopActivitiesLocked();
@@ -2287,7 +2247,7 @@
// previous should actually be hidden depending on whether the
// new one is found to be full-screen or not.
if (prev.finishing) {
- mWindowManager.setAppVisibility(prev.appToken, false);
+ prev.setVisibility(false);
if (DEBUG_SWITCH) Slog.v(TAG_SWITCH,
"Not waiting for visible to hide: " + prev + ", waitingVisible="
+ mStackSupervisor.mWaitingVisibleActivities.contains(prev)
@@ -2329,7 +2289,7 @@
? TRANSIT_ACTIVITY_CLOSE
: TRANSIT_TASK_CLOSE, false);
}
- mWindowManager.setAppVisibility(prev.appToken, false);
+ prev.setVisibility(false);
} else {
if (DEBUG_TRANSITION) Slog.v(TAG_TRANSITION,
"Prepare open transition: prev=" + prev);
@@ -2384,7 +2344,7 @@
// This activity is now becoming visible.
if (!next.visible || next.stopped || lastActivityTranslucent) {
- mWindowManager.setAppVisibility(next.appToken, true);
+ next.setVisibility(true);
}
// schedule launch ticks to collect information about slow apps.
@@ -2433,7 +2393,7 @@
mStackSupervisor.scheduleResumeTopActivities();
}
if (!next.visible || next.stopped) {
- mWindowManager.setAppVisibility(next.appToken, true);
+ next.setVisibility(true);
}
next.completeResumeLocked();
if (DEBUG_STACK) mStackSupervisor.validateTopActivitiesLocked();
@@ -2471,7 +2431,7 @@
// Well the app will no longer be stopped.
// Clear app token stopped state in window manager if needed.
- mWindowManager.notifyAppResumed(next.appToken, next.stopped, allowSavedSurface);
+ next.notifyAppResumed(next.stopped, allowSavedSurface);
EventLog.writeEvent(EventLogTags.AM_RESUME_ACTIVITY, next.userId,
System.identityHashCode(next), next.task.taskId, next.shortComponentName);
@@ -2537,6 +2497,27 @@
return true;
}
+ private boolean resumeTopActivityInNextFocusableStack(ActivityRecord prev,
+ ActivityOptions options, String reason) {
+ if ((!mFullscreen || !isOnHomeDisplay())
+ && adjustFocusToNextFocusableStackLocked(reason)) {
+ // Try to move focus to the next visible stack with a running activity if this
+ // stack is not covering the entire screen or is on a secondary display (with no home
+ // stack).
+ return mStackSupervisor.resumeFocusedStackTopActivityLocked(
+ mStackSupervisor.getFocusedStack(), prev, null);
+ }
+
+ // Let's just start up the Launcher...
+ ActivityOptions.abort(options);
+ if (DEBUG_STATES) Slog.d(TAG_STATES,
+ "resumeTopActivityInNextFocusableStack: " + reason + ", go home");
+ if (DEBUG_STACK) mStackSupervisor.validateTopActivitiesLocked();
+ // Only resume home if on home display
+ return isOnHomeDisplay() &&
+ mStackSupervisor.resumeHomeStackTask(prev, reason);
+ }
+
private TaskRecord getNextTask(TaskRecord targetTask) {
final int index = mTaskHistory.indexOf(targetTask);
if (index >= 0) {
@@ -2669,9 +2650,7 @@
if (!startIt) {
if (DEBUG_ADD_REMOVE) Slog.i(TAG, "Adding activity " + r + " to task "
+ task, new RuntimeException("here").fillInStackTrace());
- task.addActivityToTop(r);
- r.putInHistory();
- addConfigOverride(r, task);
+ r.createWindowContainer();
ActivityOptions.abort(options);
return;
}
@@ -2682,12 +2661,10 @@
}
}
- // Place a new activity at top of stack, so it is next to interact
- // with the user.
+ // Place a new activity at top of stack, so it is next to interact with the user.
- // If we are not placing the new activity frontmost, we do not want
- // to deliver the onUserLeaving callback to the actual frontmost
- // activity
+ // If we are not placing the new activity frontmost, we do not want to deliver the
+ // onUserLeaving callback to the actual frontmost activity
if (task == r.task && mTaskHistory.indexOf(task) != (mTaskHistory.size() - 1)) {
mStackSupervisor.mUserLeaving = false;
if (DEBUG_USER_LEAVING) Slog.v(TAG_USER_LEAVING,
@@ -2699,10 +2676,9 @@
// Slot the activity into the history stack and proceed
if (DEBUG_ADD_REMOVE) Slog.i(TAG, "Adding activity " + r + " to stack to task " + task,
new RuntimeException("here").fillInStackTrace());
- task.addActivityToTop(r);
+ r.createWindowContainer();
task.setFrontOfTask();
- r.putInHistory();
if (!isHomeOrRecentsStack() || numActivities() > 0) {
// We want to show the starting preview window if we are
// switching to a new task, or the next activity's process is
@@ -2737,7 +2713,6 @@
mWindowManager.prepareAppTransition(transit, keepCurTransition);
mNoAnimActivities.remove(r);
}
- addConfigOverride(r, task);
boolean doShow = true;
if (newTask) {
// Even though this activity is starting fresh, we still need
@@ -2756,7 +2731,7 @@
if (r.mLaunchTaskBehind) {
// Don't do a starting window for mLaunchTaskBehind. More importantly make sure we
// tell WindowManager that r is visible even though it is at the back of the stack.
- mWindowManager.setAppVisibility(r.appToken, true);
+ r.setVisibility(true);
ensureActivitiesVisibleLocked(null, 0, !PRESERVE_WINDOWS);
} else if (SHOW_APP_STARTING_PREVIEW && doShow) {
// Figure out if we are transitioning from another activity that is
@@ -2780,7 +2755,6 @@
} else {
// If this is the first activity, don't do any fancy animations,
// because there is nothing for it to animate on top of.
- addConfigOverride(r, task);
ActivityOptions.abort(options);
}
}
@@ -2865,8 +2839,6 @@
+ " out to new task " + target.task);
}
- setAppTask(target, targetTask);
-
boolean noOptions = canMoveOptions;
final int start = replyChainEnd < 0 ? i : replyChainEnd;
for (int srcPos = start; srcPos >= i; --srcPos) {
@@ -2889,8 +2861,6 @@
"Pushing next activity " + p + " out to target's task " + target.task);
p.setTask(targetTask, null);
targetTask.addActivityAtBottom(p);
-
- setAppTask(p, targetTask);
}
mWindowManager.moveTaskToBottom(targetTask.taskId);
@@ -3028,7 +2998,6 @@
+ " callers=" + Debug.getCallers(3));
if (DEBUG_TASKS) Slog.v(TAG_TASKS, "Pulling activity " + p
+ " from " + srcPos + " in to resetting task " + task);
- setAppTask(p, task);
}
mWindowManager.moveTaskToTop(taskId);
@@ -3173,7 +3142,7 @@
}
private boolean adjustFocusToNextFocusableStackLocked(String reason) {
- final ActivityStack stack = getNextFocusableStackLocked();
+ final ActivityStack stack = mStackSupervisor.getNextFocusableStackLocked(this);
final String myReason = reason + " adjustFocusToNextFocusableStack";
if (stack == null) {
return false;
@@ -3223,7 +3192,7 @@
if (DEBUG_VISIBILITY) Slog.v(TAG_VISIBILITY,
"Stopping visible=" + r.visible + " for " + r);
if (!r.visible) {
- mWindowManager.setAppVisibility(r.appToken, false);
+ r.setVisibility(false);
}
EventLogTags.writeAmStopActivity(
r.userId, System.identityHashCode(r), r.shortComponentName);
@@ -3457,7 +3426,7 @@
mWindowManager.prepareAppTransition(transit, false);
// Tell window manager to prepare for this one to be removed.
- mWindowManager.setAppVisibility(r.appToken, false);
+ r.setVisibility(false);
if (mPausingActivity == null) {
if (DEBUG_PAUSE) Slog.v(TAG_PAUSE, "Finish needs to pause: " + r);
@@ -3475,7 +3444,7 @@
if (DEBUG_PAUSE) Slog.v(TAG_PAUSE, "Finish not pausing: " + r);
if (r.visible) {
mWindowManager.prepareAppTransition(transit, false);
- mWindowManager.setAppVisibility(r.appToken, false);
+ r.setVisibility(false);
mWindowManager.executeAppTransition();
if (!mStackSupervisor.mWaitingVisibleActivities.contains(r)) {
mStackSupervisor.mWaitingVisibleActivities.add(r);
@@ -3782,7 +3751,7 @@
r.state = ActivityState.DESTROYED;
if (DEBUG_APP) Slog.v(TAG_APP, "Clearing app during remove for activity " + r);
r.app = null;
- mWindowManager.removeAppToken(r.appToken, r.getDisplayId());
+ r.removeWindowContainer();
final TaskRecord task = r.task;
if (task != null && task.removeActivity(r)) {
if (DEBUG_STACK) Slog.i(TAG_STACK,
@@ -4981,17 +4950,6 @@
}
}
- void addConfigOverride(ActivityRecord r, TaskRecord task) {
- task.updateOverrideConfigurationFromLaunchBounds();
- // TODO: VI deal with activity
- mWindowManager.addAppToken(task.mActivities.indexOf(r), r.appToken,
- r.task.taskId, r.info.screenOrientation, r.fullscreen,
- (r.info.flags & FLAG_SHOW_FOR_ALL_USERS) != 0, r.info.configChanges,
- task.voiceSession != null, r.mLaunchTaskBehind, r.isAlwaysFocusable(),
- r.appInfo.targetSdkVersion, r.mRotationAnimationHint);
- r.onOverrideConfigurationSent();
- }
-
void moveToFrontAndResumeStateIfNeeded(
ActivityRecord r, boolean moveToFront, boolean setResume, String reason) {
if (!moveToFront) {
@@ -5030,7 +4988,6 @@
r.info, r.intent, null, null, true, r.mActivityType);
r.setTask(task, null);
task.addActivityToTop(r);
- setAppTask(r, task);
mStackSupervisor.scheduleReportPictureInPictureModeChangedIfNeeded(task, prevStack);
moveToFrontAndResumeStateIfNeeded(r, wasFocused, wasResumed, "moveActivityToStack");
if (wasResumed) {
@@ -5038,12 +4995,6 @@
}
}
- private void setAppTask(ActivityRecord r, TaskRecord task) {
- task.updateOverrideConfigurationFromLaunchBounds();
- mWindowManager.addAppToTask(r.appToken, task.taskId);
- r.onOverrideConfigurationSent();
- }
-
public int getStackId() {
return mStackId;
}
diff --git a/services/core/java/com/android/server/am/ActivityStackSupervisor.java b/services/core/java/com/android/server/am/ActivityStackSupervisor.java
index 235325b..8bd7c90 100644
--- a/services/core/java/com/android/server/am/ActivityStackSupervisor.java
+++ b/services/core/java/com/android/server/am/ActivityStackSupervisor.java
@@ -33,7 +33,6 @@
import static android.app.ActivityManager.StackId.INVALID_STACK_ID;
import static android.app.ActivityManager.StackId.LAST_STATIC_STACK_ID;
import static android.app.ActivityManager.StackId.PINNED_STACK_ID;
-import static android.app.ActivityManager.StackId.RECENTS_STACK_ID;
import static android.content.Intent.FLAG_ACTIVITY_MULTIPLE_TASK;
import static android.content.Intent.FLAG_ACTIVITY_NEW_TASK;
import static android.content.pm.PackageManager.PERMISSION_GRANTED;
@@ -179,8 +178,7 @@
import java.util.Objects;
import java.util.Set;
-public class ActivityStackSupervisor extends ConfigurationContainer
- implements DisplayListener {
+public class ActivityStackSupervisor extends ConfigurationContainer implements DisplayListener {
private static final String TAG = TAG_WITH_CLASS_NAME ? "ActivityStackSupervisor" : TAG_AM;
private static final String TAG_CONTAINERS = TAG + POSTFIX_CONTAINERS;
private static final String TAG_FOCUS = TAG + POSTFIX_FOCUS;
@@ -457,6 +455,13 @@
private final FindTaskResult mTmpFindTaskResult = new FindTaskResult();
/**
+ * Temp storage for display ids sorted in focus order.
+ * Maps position to id. Using {@link SparseIntArray} instead of {@link ArrayList} because
+ * it's more efficient, as the number of displays is usually small.
+ */
+ private SparseIntArray mTmpOrderedDisplayIds = new SparseIntArray();
+
+ /**
* Used to keep track whether app visibilities got changed since the last pause. Useful to
* determine whether to invoke the task stack change listener after pausing.
*/
@@ -639,7 +644,7 @@
void setFocusStackUnchecked(String reason, ActivityStack focusCandidate) {
if (!focusCandidate.isFocusable()) {
// The focus candidate isn't focusable. Move focus to the top stack that is focusable.
- focusCandidate = focusCandidate.getNextFocusableStackLocked();
+ focusCandidate = getNextFocusableStackLocked(focusCandidate);
}
if (focusCandidate != mFocusedStack) {
@@ -1204,7 +1209,7 @@
if (andResume) {
r.startFreezingScreenLocked(app, 0);
- mWindowManager.setAppVisibility(r.appToken, true);
+ r.setVisibility(true);
// schedule launch ticks to collect information about slow apps.
r.startLaunchTickingLocked();
@@ -1227,7 +1232,7 @@
}
if (mKeyguardController.isKeyguardLocked()) {
- mWindowManager.notifyUnknownAppVisibilityLaunched(r.appToken);
+ r.notifyUnknownVisibilityLaunched();
}
r.app = app;
@@ -2021,6 +2026,35 @@
return mActivityDisplays.valueAt(DEFAULT_DISPLAY).mStacks;
}
+ /**
+ * Get next focusable stack in the system. This will search across displays and stacks
+ * in last-focused order for a focusable and visible stack, different from the target stack.
+ *
+ * @param currentFocus The stack that previously had focus and thus needs to be ignored when
+ * searching for next candidate.
+ * @return Next focusable {@link ActivityStack}, null if not found.
+ */
+ ActivityStack getNextFocusableStackLocked(ActivityStack currentFocus) {
+ mWindowManager.getDisplaysInFocusOrder(mTmpOrderedDisplayIds);
+
+ for (int i = mTmpOrderedDisplayIds.size() - 1; i >= 0; --i) {
+ final int displayId = mTmpOrderedDisplayIds.get(i);
+ final List<ActivityStack> stacks = mActivityDisplays.get(displayId).mStacks;
+ if (stacks == null) {
+ continue;
+ }
+ for (int j = stacks.size() - 1; j >= 0; --j) {
+ final ActivityStack stack = stacks.get(j);
+ if (stack != currentFocus && stack.isFocusable()
+ && stack.getStackVisibilityLocked(null) != STACK_INVISIBLE) {
+ return stack;
+ }
+ }
+ }
+
+ return null;
+ }
+
ActivityRecord getHomeActivity() {
return getHomeActivityForUser(mCurrentUser);
}
@@ -2177,6 +2211,9 @@
// display because it no longer contains any tasks.
mAllowDockedStackResize = false;
}
+ final ActivityStack fullscreenStack = getStack(FULLSCREEN_WORKSPACE_STACK_ID);
+ final boolean isFullscreenStackVisible = fullscreenStack != null &&
+ fullscreenStack.getStackVisibilityLocked(null) == STACK_VISIBLE;
final ArrayList<TaskRecord> tasks = stack.getAllTasks();
final int size = tasks.size();
if (onTop) {
@@ -2186,9 +2223,8 @@
// Update the return-to to reflect where the pinned stack task was moved
// from so that we retain the stack that was previously visible if the
// pinned stack is recreated. See moveActivityToPinnedStackLocked().
- final int focusedStackId = getFocusedStack().getStackId();
- task.setTaskToReturnTo(focusedStackId == HOME_STACK_ID || !onTop
- ? HOME_ACTIVITY_TYPE : APPLICATION_ACTIVITY_TYPE);
+ task.setTaskToReturnTo(isFullscreenStackVisible && onTop ?
+ APPLICATION_ACTIVITY_TYPE : HOME_ACTIVITY_TYPE);
}
moveTaskToStackLocked(tasks.get(i).taskId,
FULLSCREEN_WORKSPACE_STACK_ID, onTop, onTop /*forceFocus*/,
@@ -2575,7 +2611,7 @@
"Added restored task=" + task + " to stack=" + stack);
final ArrayList<ActivityRecord> activities = task.mActivities;
for (int activityNdx = activities.size() - 1; activityNdx >= 0; --activityNdx) {
- stack.addConfigOverride(activities.get(activityNdx), task);
+ activities.get(activityNdx).createWindowContainer();
}
return true;
}
@@ -3167,7 +3203,7 @@
task.setLastThumbnailLocked(r.screenshotActivityLocked());
mRecentTasks.addLocked(task);
mService.mTaskChangeNotificationController.notifyTaskStackChanged();
- mWindowManager.setAppVisibility(r.appToken, false);
+ r.setVisibility(false);
// When launching tasks behind, update the last active time of the top task after the new
// task has been shown briefly
@@ -3299,6 +3335,10 @@
final int focusStackId = mFocusedStack.getStackId();
// We dismiss the docked stack whenever we switch users.
moveTasksToFullscreenStackLocked(DOCKED_STACK_ID, focusStackId == DOCKED_STACK_ID);
+ // Also dismiss the pinned stack whenever we switch users. Removing the pinned stack will
+ // also cause all tasks to be moved to the fullscreen stack at a position that is
+ // appropriate.
+ removeStackLocked(PINNED_STACK_ID);
mUserStackInFront.put(mCurrentUser, focusStackId);
final int restoreStackId = mUserStackInFront.get(userId, HOME_STACK_ID);
@@ -3358,7 +3398,7 @@
// normal flow and hide it once we determine that it is
// hidden by the activities in front of it.
if (DEBUG_STATES) Slog.v(TAG, "Before stopping, can hide: " + s);
- mWindowManager.setAppVisibility(s.appToken, false);
+ s.setVisibility(false);
}
}
if ((!waitingVisible || mService.isSleepingOrShuttingDownLocked()) && remove) {
diff --git a/services/core/java/com/android/server/am/ActivityStarter.java b/services/core/java/com/android/server/am/ActivityStarter.java
index 3bb9ccc..007a478 100644
--- a/services/core/java/com/android/server/am/ActivityStarter.java
+++ b/services/core/java/com/android/server/am/ActivityStarter.java
@@ -949,14 +949,18 @@
}
void sendPowerHintForLaunchStartIfNeeded(boolean forceSend) {
- // Trigger launch power hint if activity being launched is not in the current task
- final ActivityStack focusStack = mSupervisor.getFocusedStack();
- final ActivityRecord curTop = (focusStack == null)
- ? null : focusStack.topRunningNonDelayedActivityLocked(mNotTop);
- if ((forceSend || (!mPowerHintSent && curTop != null &&
- curTop.task != null && mStartActivity != null &&
- curTop.task != mStartActivity.task )) &&
- mService.mLocalPowerManager != null) {
+ boolean sendHint = forceSend;
+
+ if (!sendHint) {
+ // If not forced, send power hint when the activity's process is different than the
+ // current resumed activity.
+ final ActivityRecord resumedActivity = mSupervisor.getResumedActivityLocked();
+ sendHint = resumedActivity == null
+ || resumedActivity.app == null
+ || !resumedActivity.app.equals(mStartActivity.app);
+ }
+
+ if (sendHint && mService.mLocalPowerManager != null) {
mService.mLocalPowerManager.powerHint(PowerHint.LAUNCH, 1);
mPowerHintSent = true;
}
@@ -1238,7 +1242,7 @@
r.mTaskOverlay = true;
final TaskRecord task = mSupervisor.anyTaskForIdLocked(mOptions.getLaunchTaskId());
final ActivityRecord top = task != null ? task.getTopActivity() : null;
- if (top != null && !top.visible) {
+ if (top != null && top.state != RESUMED) {
// The caller specifies that we'd like to be avoided to be moved to the front, so be
// it!
diff --git a/services/core/java/com/android/server/am/BatteryStatsService.java b/services/core/java/com/android/server/am/BatteryStatsService.java
index 0ea78b3..f1f8bb2 100644
--- a/services/core/java/com/android/server/am/BatteryStatsService.java
+++ b/services/core/java/com/android/server/am/BatteryStatsService.java
@@ -991,7 +991,8 @@
@Override
public void setBatteryState(final int status, final int health, final int plugType,
- final int level, final int temp, final int volt, final int chargeUAh) {
+ final int level, final int temp, final int volt, final int chargeUAh,
+ final int chargeFullUAh) {
enforceCallingPermission();
// BatteryService calls us here and we may update external state. It would be wrong
@@ -1005,7 +1006,7 @@
// The battery state has not changed, so we don't need to sync external
// stats immediately.
mStats.setBatteryStateLocked(status, health, plugType, level, temp, volt,
- chargeUAh);
+ chargeUAh, chargeFullUAh);
return;
}
}
@@ -1015,7 +1016,7 @@
updateExternalStatsSync("battery-state", BatteryStatsImpl.ExternalStatsSync.UPDATE_ALL);
synchronized (mStats) {
mStats.setBatteryStateLocked(status, health, plugType, level, temp, volt,
- chargeUAh);
+ chargeUAh, chargeFullUAh);
}
}
});
diff --git a/services/core/java/com/android/server/am/TaskChangeNotificationController.java b/services/core/java/com/android/server/am/TaskChangeNotificationController.java
index b6e35d2..fd248c6 100644
--- a/services/core/java/com/android/server/am/TaskChangeNotificationController.java
+++ b/services/core/java/com/android/server/am/TaskChangeNotificationController.java
@@ -90,6 +90,7 @@
case NOTIFY_ACTIVITY_REQUESTED_ORIENTATION_CHANGED_LISTENERS:
forAllListeners((listener) -> listener.onActivityRequestedOrientationChanged(
msg.arg1, msg.arg2));
+ break;
case NOTIFY_TASK_REMOVAL_STARTED_LISTENERS:
forAllListeners((listener) -> listener.onTaskRemovalStarted(msg.arg1));
break;
diff --git a/services/core/java/com/android/server/am/TaskRecord.java b/services/core/java/com/android/server/am/TaskRecord.java
index 9e28068..a17cf3b 100644
--- a/services/core/java/com/android/server/am/TaskRecord.java
+++ b/services/core/java/com/android/server/am/TaskRecord.java
@@ -849,6 +849,11 @@
if (r.isPersistable()) {
mService.notifyTaskPersisterLocked(this, false);
}
+
+ // Sync. with window manager
+ updateOverrideConfigurationFromLaunchBounds();
+ r.positionWindowContainerAt(index);
+ r.onOverrideConfigurationSent();
}
/** @return true if this was the last activity in the task */
diff --git a/services/core/java/com/android/server/am/UserController.java b/services/core/java/com/android/server/am/UserController.java
index a0a04bb..45e06b0 100644
--- a/services/core/java/com/android/server/am/UserController.java
+++ b/services/core/java/com/android/server/am/UserController.java
@@ -442,6 +442,19 @@
}
}
+ int restartUser(final int userId, final boolean foreground) {
+ return stopUser(userId, /* force */ true, new IStopUserCallback.Stub() {
+ @Override
+ public void userStopped(final int userId) {
+ // Post to the same handler that this callback is called from to ensure the user
+ // cleanup is complete before restarting.
+ mHandler.post(() -> startUser(userId, foreground));
+ }
+ @Override
+ public void userStopAborted(final int userId) {}
+ });
+ }
+
int stopUser(final int userId, final boolean force, final IStopUserCallback callback) {
if (mInjector.checkCallingPermission(INTERACT_ACROSS_USERS_FULL)
!= PackageManager.PERMISSION_GRANTED) {
@@ -634,6 +647,12 @@
}
if (stopped) {
+ // Evict the user's credential encryption key
+ try {
+ getStorageManager().lockUserKey(userId);
+ } catch (RemoteException re) {
+ throw re.rethrowAsRuntimeException();
+ }
mInjector.systemServiceManagerCleanupUser(userId);
synchronized (mLock) {
mInjector.stackSupervisorRemoveUserLocked(userId);
diff --git a/services/core/java/com/android/server/audio/AudioService.java b/services/core/java/com/android/server/audio/AudioService.java
index 788a28c..0f3f9ce 100644
--- a/services/core/java/com/android/server/audio/AudioService.java
+++ b/services/core/java/com/android/server/audio/AudioService.java
@@ -191,7 +191,6 @@
/** The controller for the volume UI. */
private final VolumeController mVolumeController = new VolumeController();
- private final ControllerService mControllerService = new ControllerService();
// sendMsg() flags
/** If the msg is already queued, replace it with this one. */
@@ -232,6 +231,7 @@
private static final int MSG_SET_WIRED_DEVICE_CONNECTION_STATE = 100;
private static final int MSG_SET_A2DP_SRC_CONNECTION_STATE = 101;
private static final int MSG_SET_A2DP_SINK_CONNECTION_STATE = 102;
+ private static final int MSG_A2DP_DEVICE_CONFIG_CHANGE = 103;
// end of messages handled under wakelock
private static final int BTA2DP_DOCK_TIMEOUT_MILLIS = 8000;
@@ -781,7 +781,6 @@
SAFE_VOLUME_CONFIGURE_TIMEOUT_MS);
initA11yMonitoring(mContext);
- mControllerService.init();
onIndicateSystemReady();
}
@@ -3183,7 +3182,7 @@
queueMsgUnderWakeLock(mAudioHandler,
MSG_SET_A2DP_SINK_CONNECTION_STATE,
state,
- 0,
+ 0 /* arg2 unused */,
btDevice,
delay);
}
@@ -3200,7 +3199,7 @@
queueMsgUnderWakeLock(mAudioHandler,
MSG_SET_A2DP_SRC_CONNECTION_STATE,
state,
- 0,
+ 0 /* arg2 unused */,
btDevice,
0 /* delay */);
}
@@ -3848,8 +3847,8 @@
int delay = checkSendBecomingNoisyIntent(type, state);
queueMsgUnderWakeLock(mAudioHandler,
MSG_SET_WIRED_DEVICE_CONNECTION_STATE,
- 0,
- 0,
+ 0 /* arg1 unused */,
+ 0 /* arg2 unused */,
new WiredDeviceConnectionState(type, state, address, name, caller),
delay);
}
@@ -3872,13 +3871,25 @@
(profile == BluetoothProfile.A2DP ?
MSG_SET_A2DP_SINK_CONNECTION_STATE : MSG_SET_A2DP_SRC_CONNECTION_STATE),
state,
- 0,
+ 0 /* arg2 unused */,
device,
delay);
}
return delay;
}
+ public void handleBluetoothA2dpDeviceConfigChange(BluetoothDevice device)
+ {
+ synchronized (mConnectedDevices) {
+ queueMsgUnderWakeLock(mAudioHandler,
+ MSG_A2DP_DEVICE_CONFIG_CHANGE,
+ 0 /* arg1 unused */,
+ 0 /* arg1 unused */,
+ device,
+ 0 /* delay */);
+ }
+ }
+
///////////////////////////////////////////////////////////////////////////
// Inner classes
///////////////////////////////////////////////////////////////////////////
@@ -4691,6 +4702,11 @@
mAudioEventWakeLock.release();
break;
+ case MSG_A2DP_DEVICE_CONFIG_CHANGE:
+ onBluetoothA2dpDeviceConfigChange((BluetoothDevice)msg.obj);
+ mAudioEventWakeLock.release();
+ break;
+
case MSG_REPORT_NEW_ROUTES: {
int N = mRoutesObservers.beginBroadcast();
if (N > 0) {
@@ -4913,7 +4929,7 @@
private void onSetA2dpSinkConnectionState(BluetoothDevice btDevice, int state)
{
if (DEBUG_VOL) {
- Log.d(TAG, "onSetA2dpSinkConnectionState btDevice="+btDevice+"state="+state);
+ Log.d(TAG, "onSetA2dpSinkConnectionState btDevice=" + btDevice+"state=" + state);
}
if (btDevice == null) {
return;
@@ -4924,9 +4940,9 @@
}
synchronized (mConnectedDevices) {
- String key = makeDeviceListKey(AudioSystem.DEVICE_OUT_BLUETOOTH_A2DP,
- btDevice.getAddress());
- DeviceListSpec deviceSpec = mConnectedDevices.get(key);
+ final String key = makeDeviceListKey(AudioSystem.DEVICE_OUT_BLUETOOTH_A2DP,
+ btDevice.getAddress());
+ final DeviceListSpec deviceSpec = mConnectedDevices.get(key);
boolean isConnected = deviceSpec != null;
if (isConnected && state != BluetoothProfile.STATE_CONNECTED) {
@@ -4977,7 +4993,7 @@
private void onSetA2dpSourceConnectionState(BluetoothDevice btDevice, int state)
{
if (DEBUG_VOL) {
- Log.d(TAG, "onSetA2dpSourceConnectionState btDevice="+btDevice+" state="+state);
+ Log.d(TAG, "onSetA2dpSourceConnectionState btDevice=" + btDevice + " state=" + state);
}
if (btDevice == null) {
return;
@@ -4988,8 +5004,8 @@
}
synchronized (mConnectedDevices) {
- String key = makeDeviceListKey(AudioSystem.DEVICE_IN_BLUETOOTH_A2DP, address);
- DeviceListSpec deviceSpec = mConnectedDevices.get(key);
+ final String key = makeDeviceListKey(AudioSystem.DEVICE_IN_BLUETOOTH_A2DP, address);
+ final DeviceListSpec deviceSpec = mConnectedDevices.get(key);
boolean isConnected = deviceSpec != null;
if (isConnected && state != BluetoothProfile.STATE_CONNECTED) {
@@ -5000,6 +5016,31 @@
}
}
+ private void onBluetoothA2dpDeviceConfigChange(BluetoothDevice btDevice)
+ {
+ if (DEBUG_VOL) {
+ Log.d(TAG, "onBluetoothA2dpDeviceConfigChange btDevice=" + btDevice);
+ }
+ if (btDevice == null) {
+ return;
+ }
+ String address = btDevice.getAddress();
+ if (!BluetoothAdapter.checkBluetoothAddress(address)) {
+ address = "";
+ }
+
+ int device = AudioSystem.DEVICE_OUT_BLUETOOTH_A2DP;
+ synchronized (mConnectedDevices) {
+ final String key = makeDeviceListKey(device, address);
+ final DeviceListSpec deviceSpec = mConnectedDevices.get(key);
+ if (deviceSpec != null) {
+ // Device is connected
+ AudioSystem.handleDeviceConfigChange(device, address,
+ btDevice.getName());
+ }
+ }
+ }
+
public void avrcpSupportsAbsoluteVolume(String address, boolean support) {
// address is not used for now, but may be used when multiple a2dp devices are supported
synchronized (mA2dpAvrcpLock) {
@@ -6022,7 +6063,6 @@
pw.print(" mMcc="); pw.println(mMcc);
pw.print(" mCameraSoundForced="); pw.println(mCameraSoundForced);
pw.print(" mHasVibrator="); pw.println(mHasVibrator);
- pw.print(" mControllerService="); pw.println(mControllerService);
pw.print(" mVolumePolicy="); pw.println(mVolumePolicy);
dumpAudioPolicies(pw);
@@ -6050,9 +6090,6 @@
}
private void enforceVolumeController(String action) {
- if (mControllerService.mUid != 0 && Binder.getCallingUid() == mControllerService.mUid) {
- return;
- }
mContext.enforceCallingOrSelfPermission(android.Manifest.permission.STATUS_BAR_SERVICE,
"Only SystemUI can " + action);
}
@@ -6283,11 +6320,6 @@
}
@Override
- public int getVolumeControllerUid() {
- return mControllerService.mUid;
- }
-
- @Override
public void updateRingerModeAffectedStreamsInternal() {
synchronized (mSettingsLock) {
if (updateRingerModeAffectedStreams()) {
@@ -6448,12 +6480,12 @@
}
//======================
- // Audio policy callbacks from players for playback configuration updates
+ // Audio playback notification
//======================
private final PlaybackActivityMonitor mPlaybackMonitor = new PlaybackActivityMonitor();
public void registerPlaybackCallback(IPlaybackConfigDispatcher pcdb) {
- final boolean isPrivileged =
+ final boolean isPrivileged =
(PackageManager.PERMISSION_GRANTED == mContext.checkCallingPermission(
android.Manifest.permission.MODIFY_AUDIO_ROUTING));
mPlaybackMonitor.registerPlaybackCallback(pcdb, isPrivileged);
@@ -6464,23 +6496,26 @@
}
public List<AudioPlaybackConfiguration> getActivePlaybackConfigurations() {
- return mPlaybackMonitor.getActivePlaybackConfigurations();
+ final boolean isPrivileged =
+ (PackageManager.PERMISSION_GRANTED == mContext.checkCallingPermission(
+ android.Manifest.permission.MODIFY_AUDIO_ROUTING));
+ return mPlaybackMonitor.getActivePlaybackConfigurations(isPrivileged);
}
- public void trackPlayer(PlayerBase.PlayerIdCard pic) {
- mPlaybackMonitor.trackPlayer(pic);
+ public int trackPlayer(PlayerBase.PlayerIdCard pic) {
+ return mPlaybackMonitor.trackPlayer(pic);
}
public void playerAttributes(int piid, AudioAttributes attr) {
- mPlaybackMonitor.playerAttributes(piid, attr);
+ mPlaybackMonitor.playerAttributes(piid, attr, Binder.getCallingUid());
}
public void playerEvent(int piid, int event) {
- mPlaybackMonitor.playerEvent(piid, event);
+ mPlaybackMonitor.playerEvent(piid, event, Binder.getCallingUid());
}
public void releasePlayer(int piid) {
- mPlaybackMonitor.releasePlayer(piid);
+ mPlaybackMonitor.releasePlayer(piid, Binder.getCallingUid());
}
//======================
@@ -6545,42 +6580,4 @@
private HashMap<IBinder, AudioPolicyProxy> mAudioPolicies =
new HashMap<IBinder, AudioPolicyProxy>();
private int mAudioPolicyCounter = 0; // always accessed synchronized on mAudioPolicies
-
- private class ControllerService extends ContentObserver {
- private int mUid;
- private ComponentName mComponent;
-
- public ControllerService() {
- super(null);
- }
-
- @Override
- public String toString() {
- return String.format("{mUid=%d,mComponent=%s}", mUid, mComponent);
- }
-
- public void init() {
- onChange(true);
- mContentResolver.registerContentObserver(Settings.Secure.getUriFor(
- Settings.Secure.VOLUME_CONTROLLER_SERVICE_COMPONENT), false, this);
- }
-
- @Override
- public void onChange(boolean selfChange) {
- mUid = 0;
- mComponent = null;
- final String setting = Settings.Secure.getString(mContentResolver,
- Settings.Secure.VOLUME_CONTROLLER_SERVICE_COMPONENT);
- if (setting == null) return;
- try {
- mComponent = ComponentName.unflattenFromString(setting);
- if (mComponent == null) return;
- mUid = mContext.getPackageManager()
- .getApplicationInfo(mComponent.getPackageName(), 0).uid;
- } catch (Exception e) {
- Log.w(TAG, "Error loading controller service", e);
- }
- if (DEBUG_VOL) Log.d(TAG, "Reloaded controller service: " + this);
- }
- }
}
diff --git a/services/core/java/com/android/server/audio/PlaybackActivityMonitor.java b/services/core/java/com/android/server/audio/PlaybackActivityMonitor.java
index b99e4e9..d6b4bee 100644
--- a/services/core/java/com/android/server/audio/PlaybackActivityMonitor.java
+++ b/services/core/java/com/android/server/audio/PlaybackActivityMonitor.java
@@ -25,6 +25,7 @@
import android.media.IPlaybackConfigDispatcher;
import android.media.MediaRecorder;
import android.media.PlayerBase;
+import android.os.Binder;
import android.os.IBinder;
import android.os.RemoteException;
import android.util.Log;
@@ -61,27 +62,31 @@
//=================================================================
// Track players and their states
- // methods trackPlayer, playerAttributes, playerEvent, releasePlayer are all oneway calls
+ // methods playerAttributes, playerEvent, releasePlayer are all oneway calls
// into AudioService. They trigger synchronous dispatchPlaybackChange() which updates
// all listeners as oneway calls.
- public void trackPlayer(PlayerBase.PlayerIdCard pic) {
- if (DEBUG) { Log.v(TAG, "trackPlayer() for piid=" + pic.mPIId); }
- final AudioPlaybackConfiguration apc = new AudioPlaybackConfiguration(pic);
+ public int trackPlayer(PlayerBase.PlayerIdCard pic) {
+ final int newPiid = AudioSystem.newAudioPlayerId();
+ if (DEBUG) { Log.v(TAG, "trackPlayer() new piid=" + newPiid); }
+ final AudioPlaybackConfiguration apc =
+ new AudioPlaybackConfiguration(pic, newPiid,
+ Binder.getCallingUid(), Binder.getCallingPid());
synchronized(mPlayerLock) {
- mPlayers.put(pic.mPIId, apc);
+ mPlayers.put(newPiid, apc);
}
+ return newPiid;
}
- public void playerAttributes(int piid, @NonNull AudioAttributes attr) {
+ public void playerAttributes(int piid, @NonNull AudioAttributes attr, int binderUid) {
final boolean change;
synchronized(mPlayerLock) {
final AudioPlaybackConfiguration apc = mPlayers.get(new Integer(piid));
- if (apc == null) {
- Log.e(TAG, "Unknown player " + piid + " for audio attributes change");
- change = false;
- } else {
+ if (checkConfigurationCaller(piid, apc, binderUid)) {
change = apc.handleAudioAttributesEvent(attr);
+ } else {
+ Log.e(TAG, "Error updating audio attributes");
+ change = false;
}
}
if (change) {
@@ -89,17 +94,17 @@
}
}
- public void playerEvent(int piid, int event) {
- if (DEBUG) { Log.v(TAG, String.format("trackPlayer(piid=%d, event=%d)", piid, event)); }
+ public void playerEvent(int piid, int event, int binderUid) {
+ if (DEBUG) { Log.v(TAG, String.format("playerEvent(piid=%d, event=%d)", piid, event)); }
final boolean change;
synchronized(mPlayerLock) {
final AudioPlaybackConfiguration apc = mPlayers.get(new Integer(piid));
- if (apc == null) {
- Log.e(TAG, "Unknown player " + piid + " for event " + event);
- change = false;
- } else {
+ if (checkConfigurationCaller(piid, apc, binderUid)) {
//TODO add generation counter to only update to the latest state
change = apc.handleStateEvent(event);
+ } else {
+ Log.e(TAG, "Error handling event " + event);
+ change = false;
}
}
if (change) {
@@ -107,13 +112,14 @@
}
}
- public void releasePlayer(int piid) {
+ public void releasePlayer(int piid, int binderUid) {
if (DEBUG) { Log.v(TAG, "releasePlayer() for piid=" + piid); }
synchronized(mPlayerLock) {
- if (!mPlayers.containsKey(new Integer(piid))) {
- Log.e(TAG, "Unknown player " + piid + " for release");
- } else {
+ final AudioPlaybackConfiguration apc = mPlayers.get(new Integer(piid));
+ if (checkConfigurationCaller(piid, apc, binderUid)) {
mPlayers.remove(new Integer(piid));
+ } else {
+ Log.e(TAG, "Error releasing player " + piid);
}
}
}
@@ -128,6 +134,25 @@
}
}
+ /**
+ * Check that piid and uid are valid for the given configuration.
+ * @param piid the piid of the player.
+ * @param apc the configuration found for this piid.
+ * @param binderUid actual uid of client trying to signal a player state/event/attributes.
+ * @return true if the call is valid and the change should proceed, false otherwise.
+ */
+ private static boolean checkConfigurationCaller(int piid,
+ final AudioPlaybackConfiguration apc, int binderUid) {
+ if (apc == null) {
+ Log.e(TAG, "Invalid operation: unknown player " + piid);
+ return false;
+ } else if ((binderUid != 0) && (apc.getClientUid() != binderUid)) {
+ Log.e(TAG, "Forbidden operation from uid " + binderUid + " for player " + piid);
+ return false;
+ }
+ return true;
+ }
+
private void dispatchPlaybackChange() {
synchronized (mClients) {
// typical use case, nobody is listening, don't do any work
@@ -228,9 +253,18 @@
}
}
- List<AudioPlaybackConfiguration> getActivePlaybackConfigurations() {
+ List<AudioPlaybackConfiguration> getActivePlaybackConfigurations(boolean isPrivileged) {
synchronized(mPlayers) {
- return new ArrayList<AudioPlaybackConfiguration>(mPlayers.values());
+ if (isPrivileged) {
+ return new ArrayList<AudioPlaybackConfiguration>(mPlayers.values());
+ } else {
+ final List<AudioPlaybackConfiguration> configsPublic;
+ synchronized (mPlayerLock) {
+ configsPublic = anonymizeForPublicConsumption(
+ new ArrayList<AudioPlaybackConfiguration>(mPlayers.values()));
+ }
+ return configsPublic;
+ }
}
}
diff --git a/services/core/java/com/android/server/fingerprint/FingerprintService.java b/services/core/java/com/android/server/fingerprint/FingerprintService.java
index 3f0ebf2..b0f67a8 100644
--- a/services/core/java/com/android/server/fingerprint/FingerprintService.java
+++ b/services/core/java/com/android/server/fingerprint/FingerprintService.java
@@ -54,7 +54,7 @@
import com.android.internal.annotations.GuardedBy;
import com.android.internal.logging.MetricsLogger;
-import com.android.server.FgThread;
+import com.android.server.SystemServerInitThreadPool;
import com.android.server.SystemService;
import org.json.JSONArray;
@@ -1077,7 +1077,7 @@
@Override
public void onStart() {
publishBinderService(Context.FINGERPRINT_SERVICE, new FingerprintServiceWrapper());
- FgThread.getHandler().post(() -> getFingerprintDaemon());
+ SystemServerInitThreadPool.get().submit(this::getFingerprintDaemon, TAG + ".onStart");
listenForUserSwitches();
}
diff --git a/services/core/java/com/android/server/location/ContextHubService.java b/services/core/java/com/android/server/location/ContextHubService.java
index 1262737..a4c0fa8 100644
--- a/services/core/java/com/android/server/location/ContextHubService.java
+++ b/services/core/java/com/android/server/location/ContextHubService.java
@@ -29,9 +29,6 @@
import android.hardware.location.NanoAppInstanceInfo;
import android.os.RemoteCallbackList;
import android.os.RemoteException;
-import android.os.ServiceManager;
-import android.service.vr.IVrManager;
-import android.service.vr.IVrStateCallbacks;
import android.util.Log;
import java.io.FileDescriptor;
@@ -51,7 +48,6 @@
private static final String ENFORCE_HW_PERMISSION_MESSAGE = "Permission '"
+ HARDWARE_PERMISSION + "' not granted to access ContextHub Hardware";
-
public static final int ANY_HUB = -1;
public static final int MSG_LOAD_NANO_APP = 3;
public static final int MSG_UNLOAD_NANO_APP = 4;
@@ -73,8 +69,6 @@
private static final int OS_APP_INSTANCE = -1;
- private static final long APP_ID_ACTIVITY_RECOGNITION = 0x476f6f676c001000L;
-
private final Context mContext;
private final ConcurrentHashMap<Integer, NanoAppInstanceInfo> mNanoAppHash =
new ConcurrentHashMap<>();
@@ -85,18 +79,6 @@
private native int nativeSendMessage(int[] header, byte[] data);
private native ContextHubInfo[] nativeInitialize();
- private final IVrStateCallbacks mVrStateCallbacks = new IVrStateCallbacks.Stub() {
- @Override
- public void onVrStateChanged(boolean enabled) {
- for (NanoAppInstanceInfo app : mNanoAppHash.values()) {
- if (app.getAppId() == APP_ID_ACTIVITY_RECOGNITION) {
- sendVrStateChangeMessageToApp(app, enabled);
- break;
- }
- }
- }
- };
-
public ContextHubService(Context context) {
mContext = context;
mContextHubInfo = nativeInitialize();
@@ -105,18 +87,6 @@
Log.d(TAG, "ContextHub[" + i + "] id: " + mContextHubInfo[i].getId()
+ ", name: " + mContextHubInfo[i].getName());
}
-
- if (context.getPackageManager().hasSystemFeature(PackageManager.FEATURE_VR_MODE)) {
- IVrManager vrManager =
- IVrManager.Stub.asInterface(ServiceManager.getService("vrmanager"));
- if (vrManager != null) {
- try {
- vrManager.registerListener(mVrStateCallbacks);
- } catch (RemoteException e) {
- Log.e(TAG, "VR state listener registration failed", e);
- }
- }
- }
}
@Override
@@ -394,19 +364,4 @@
return 0;
}
-
- private void sendVrStateChangeMessageToApp(NanoAppInstanceInfo app, boolean vrModeEnabled) {
- int[] msgHeader = new int[MSG_HEADER_SIZE];
- msgHeader[HEADER_FIELD_MSG_TYPE] = 0;
- msgHeader[HEADER_FIELD_MSG_VERSION] = 0;
- msgHeader[HEADER_FIELD_HUB_HANDLE] = ANY_HUB;
- msgHeader[HEADER_FIELD_APP_INSTANCE] = app.getHandle();
-
- byte[] data = new byte[1];
- data[0] = (byte) ((vrModeEnabled) ? 1 : 0);
- int ret = nativeSendMessage(msgHeader, data);
- if (ret != 0) {
- Log.e(TAG, "Couldn't send VR state change notification (" + ret + ")!");
- }
- }
}
diff --git a/services/core/java/com/android/server/media/MediaSessionService.java b/services/core/java/com/android/server/media/MediaSessionService.java
index 4c58ffd..9b37f12 100644
--- a/services/core/java/com/android/server/media/MediaSessionService.java
+++ b/services/core/java/com/android/server/media/MediaSessionService.java
@@ -351,7 +351,7 @@
*/
private void enforceMediaPermissions(ComponentName compName, int pid, int uid,
int resolvedUserId) {
- if (isCurrentVolumeController(uid)) return;
+ if (isCurrentVolumeController(uid, pid)) return;
if (getContext()
.checkPermission(android.Manifest.permission.MEDIA_CONTENT_CONTROL, pid, uid)
!= PackageManager.PERMISSION_GRANTED
@@ -361,20 +361,13 @@
}
}
- private boolean isCurrentVolumeController(int uid) {
- if (mAudioManagerInternal != null) {
- final int vcuid = mAudioManagerInternal.getVolumeControllerUid();
- if (vcuid > 0 && uid == vcuid) {
- return true;
- }
- }
- return false;
+ private boolean isCurrentVolumeController(int uid, int pid) {
+ return getContext().checkPermission(android.Manifest.permission.STATUS_BAR_SERVICE,
+ pid, uid) == PackageManager.PERMISSION_GRANTED;
}
private void enforceSystemUiPermission(String action, int pid, int uid) {
- if (isCurrentVolumeController(uid)) return;
- if (getContext().checkPermission(android.Manifest.permission.STATUS_BAR_SERVICE,
- pid, uid) != PackageManager.PERMISSION_GRANTED) {
+ if (!isCurrentVolumeController(uid, pid)) {
throw new SecurityException("Only system ui may " + action);
}
}
diff --git a/services/core/java/com/android/server/notification/CalendarTracker.java b/services/core/java/com/android/server/notification/CalendarTracker.java
index 5d50f3b..d42c7c1 100644
--- a/services/core/java/com/android/server/notification/CalendarTracker.java
+++ b/services/core/java/com/android/server/notification/CalendarTracker.java
@@ -180,12 +180,12 @@
final Cursor cursor = mUserContext.getContentResolver().query(Attendees.CONTENT_URI,
ATTENDEE_PROJECTION, selection, selectionArgs, null);
try {
- if (cursor.getCount() == 0) {
+ if (cursor == null || cursor.getCount() == 0) {
if (DEBUG) Log.d(TAG, "No attendees found");
return true;
}
boolean rt = false;
- while (cursor.moveToNext()) {
+ while (cursor != null && cursor.moveToNext()) {
final long rowEventId = cursor.getLong(0);
final String rowEmail = cursor.getString(1);
final int status = cursor.getInt(2);
@@ -200,7 +200,9 @@
}
return rt;
} finally {
- cursor.close();
+ if (cursor != null) {
+ cursor.close();
+ }
if (DEBUG) Log.d(TAG, "meetsAttendee took " + (System.currentTimeMillis() - start));
}
}
diff --git a/services/core/java/com/android/server/notification/NotificationManagerService.java b/services/core/java/com/android/server/notification/NotificationManagerService.java
index 039fc50..ded8a1b 100644
--- a/services/core/java/com/android/server/notification/NotificationManagerService.java
+++ b/services/core/java/com/android/server/notification/NotificationManagerService.java
@@ -55,7 +55,6 @@
import android.app.AutomaticZenRule;
import android.app.backup.BackupManager;
import android.app.IActivityManager;
-import android.app.IOnNotificationChannelCreatedListener;
import android.app.INotificationManager;
import android.app.ITransientNotification;
import android.app.Notification;
@@ -170,6 +169,7 @@
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
+import java.util.Objects;
import java.util.concurrent.TimeUnit;
/** {@hide} */
@@ -225,6 +225,8 @@
private static final int EVENTLOG_ENQUEUE_STATUS_IGNORED = 2;
private static final long MIN_PACKAGE_OVERRATE_LOG_INTERVAL = 5000; // milliseconds
+ private static final long DELAY_FOR_ASSISTANT_TIME = 100;
+
private IActivityManager mAm;
private IPackageManager mPackageManager;
AudioManager mAudioManager;
@@ -270,6 +272,7 @@
new ArrayList<NotificationRecord>();
final ArrayMap<String, NotificationRecord> mNotificationsByKey =
new ArrayMap<String, NotificationRecord>();
+ final ArrayList<NotificationRecord> mEnqueuedNotifications = new ArrayList<>();
final ArrayMap<Integer, ArrayMap<String, String>> mAutobundledSummaries = new ArrayMap<>();
final ArrayList<ToastRecord> mToastQueue = new ArrayList<ToastRecord>();
final ArrayMap<String, NotificationRecord> mSummaryByGroupKey = new ArrayMap<>();
@@ -940,22 +943,16 @@
mPackageManager = packageManager;
}
- // TODO: This probably should not be mocked, it's an implementation detail.
+ // TODO: Tests should call onStart instead once the methods above are removed.
@VisibleForTesting
- void setRankingHelper(RankingHelper rankingHelper) {
- mRankingHelper = rankingHelper;
- }
-
- @Override
- public void onStart() {
+ void init(IPackageManager packageManager, LightsManager lightsManager) {
Resources resources = getContext().getResources();
-
mMaxPackageEnqueueRate = Settings.Global.getFloat(getContext().getContentResolver(),
Settings.Global.MAX_NOTIFICATION_ENQUEUE_RATE,
DEFAULT_MAX_NOTIFICATION_ENQUEUE_RATE);
mAm = ActivityManager.getService();
- mPackageManager = AppGlobals.getPackageManager();
+ mPackageManager = packageManager;
mAppOps = (AppOpsManager) getContext().getSystemService(Context.APP_OPS_SERVICE);
mVibrator = (Vibrator) getContext().getSystemService(Context.VIBRATOR_SERVICE);
mAppUsageStats = LocalServices.getService(UsageStatsManagerInternal.class);
@@ -1061,9 +1058,8 @@
mStatusBar.setNotificationDelegate(mNotificationDelegate);
}
- final LightsManager lights = getLocalService(LightsManager.class);
- mNotificationLight = lights.getLight(LightsManager.LIGHT_ID_NOTIFICATIONS);
- mAttentionLight = lights.getLight(LightsManager.LIGHT_ID_ATTENTION);
+ mNotificationLight = lightsManager.getLight(LightsManager.LIGHT_ID_NOTIFICATIONS);
+ mAttentionLight = lightsManager.getLight(LightsManager.LIGHT_ID_ATTENTION);
mDefaultNotificationColor = resources.getColor(
R.color.config_defaultNotificationColor);
@@ -1130,7 +1126,11 @@
mArchive = new Archive(resources.getInteger(
R.integer.config_notificationServiceArchiveSize));
+ }
+ @Override
+ public void onStart() {
+ init(AppGlobals.getPackageManager(), getLocalService(LightsManager.class));
publishBinderService(Context.NOTIFICATION_SERVICE, mService);
publishLocalService(NotificationManagerInternal.class, mInternalService);
}
@@ -1510,13 +1510,18 @@
}
@Override
- public void createNotificationChannel(String pkg, NotificationChannel channel,
- IOnNotificationChannelCreatedListener listener) throws RemoteException {
+ public void createNotificationChannels(String pkg,
+ ParceledListSlice channelsList) throws RemoteException {
checkCallerIsSystemOrSameApp(pkg);
- mRankingHelper.createNotificationChannel(pkg, Binder.getCallingUid(), channel,
- true /* fromTargetApp */);
+ List<NotificationChannel> channels = channelsList.getList();
+ final int channelsSize = channels.size();
+ for (int i = 0; i < channelsSize; i++) {
+ final NotificationChannel channel = channels.get(i);
+ Preconditions.checkNotNull(channel, "channel in list is null");
+ mRankingHelper.createNotificationChannel(pkg, Binder.getCallingUid(), channel,
+ true /* fromTargetApp */);
+ }
savePolicyFile();
- listener.onNotificationChannelCreated(channel);
}
@Override
@@ -1548,7 +1553,7 @@
public void updateNotificationChannelForPackage(String pkg, int uid,
NotificationChannel channel) {
enforceSystemOrSystemUI("Caller not system or systemui");
- if (!channel.isAllowed()) {
+ if (channel.getImportance() == NotificationManager.IMPORTANCE_NONE) {
// cancel
cancelAllNotificationsInt(MY_UID, MY_PID, pkg, channel.getId(), 0, 0, true,
UserHandle.getUserId(Binder.getCallingUid()), REASON_CHANNEL_BANNED,
@@ -1614,35 +1619,60 @@
int userId = ActivityManager.handleIncomingUser(Binder.getCallingPid(),
Binder.getCallingUid(), incomingUserId, true, false,
"getAppActiveNotifications", pkg);
-
- final ArrayList<StatusBarNotification> list
- = new ArrayList<StatusBarNotification>(mNotificationList.size());
+ final ArrayMap<String, StatusBarNotification> map
+ = new ArrayMap<>(mNotificationList.size() + mEnqueuedNotifications.size());
synchronized (mNotificationList) {
final int N = mNotificationList.size();
for (int i = 0; i < N; i++) {
- final StatusBarNotification sbn = mNotificationList.get(i).sbn;
- if (sbn.getPackageName().equals(pkg) && sbn.getUserId() == userId
- && (sbn.getNotification().flags
- & Notification.FLAG_AUTOGROUP_SUMMARY) == 0) {
- // We could pass back a cloneLight() but clients might get confused and
- // try to send this thing back to notify() again, which would not work
- // very well.
- final StatusBarNotification sbnOut = new StatusBarNotification(
- sbn.getPackageName(),
- sbn.getOpPkg(),
- sbn.getNotificationChannel(),
- sbn.getId(), sbn.getTag(), sbn.getUid(), sbn.getInitialPid(),
- sbn.getNotification().clone(),
- sbn.getUser(), sbn.getOverrideGroupKey(), sbn.getPostTime());
- list.add(sbnOut);
+ StatusBarNotification sbn = sanitizeSbn(pkg, userId,
+ mNotificationList.get(i).sbn);
+ if (sbn != null) {
+ map.put(sbn.getKey(), sbn);
+ }
+ }
+ for(NotificationRecord snoozed: mSnoozeHelper.getSnoozed(userId, pkg)) {
+ StatusBarNotification sbn = sanitizeSbn(pkg, userId, snoozed.sbn);
+ if (sbn != null) {
+ map.put(sbn.getKey(), sbn);
+ }
+ }
+ }
+ synchronized (mEnqueuedNotifications) {
+ final int N = mEnqueuedNotifications.size();
+ for (int i = 0; i < N; i++) {
+ StatusBarNotification sbn = sanitizeSbn(pkg, userId,
+ mEnqueuedNotifications.get(i).sbn);
+ if (sbn != null) {
+ map.put(sbn.getKey(), sbn); // pending update overwrites existing post here
}
}
}
+ final ArrayList<StatusBarNotification> list = new ArrayList<>(map.size());
+ list.addAll(map.values());
return new ParceledListSlice<StatusBarNotification>(list);
}
+ private StatusBarNotification sanitizeSbn(String pkg, int userId,
+ StatusBarNotification sbn) {
+ if (sbn.getPackageName().equals(pkg) && sbn.getUserId() == userId
+ && (sbn.getNotification().flags
+ & Notification.FLAG_AUTOGROUP_SUMMARY) == 0) {
+ // We could pass back a cloneLight() but clients might get confused and
+ // try to send this thing back to notify() again, which would not work
+ // very well.
+ return new StatusBarNotification(
+ sbn.getPackageName(),
+ sbn.getOpPkg(),
+ sbn.getNotificationChannel(),
+ sbn.getId(), sbn.getTag(), sbn.getUid(), sbn.getInitialPid(),
+ sbn.getNotification().clone(),
+ sbn.getUser(), sbn.getOverrideGroupKey(), sbn.getPostTime());
+ }
+ return null;
+ }
+
/**
* System-only API for getting a list of recent (cleared, no longer shown) notifications.
*
@@ -1992,13 +2022,13 @@
@Override
public ZenModeConfig getZenModeConfig() {
- enforceSystemOrSystemUIOrVolume("INotificationManager.getZenModeConfig");
+ enforceSystemOrSystemUI("INotificationManager.getZenModeConfig");
return mZenModeHelper.getConfig();
}
@Override
public void setZenMode(int mode, Uri conditionId, String reason) throws RemoteException {
- enforceSystemOrSystemUIOrVolume("INotificationManager.setZenMode");
+ enforceSystemOrSystemUI("INotificationManager.setZenMode");
final long identity = Binder.clearCallingIdentity();
try {
mZenModeHelper.setManualZenMode(mode, conditionId, null, reason);
@@ -2120,16 +2150,6 @@
}
}
- private void enforceSystemOrSystemUIOrVolume(String message) {
- if (mAudioManagerInternal != null) {
- final int vcuid = mAudioManagerInternal.getVolumeControllerUid();
- if (vcuid > 0 && Binder.getCallingUid() == vcuid) {
- return;
- }
- }
- enforceSystemOrSystemUI(message);
- }
-
private void enforceSystemOrSystemUI(String message) {
if (isCallerSystem()) return;
getContext().enforceCallingPermission(android.Manifest.permission.STATUS_BAR_SERVICE,
@@ -2232,7 +2252,7 @@
@Override
public boolean isSystemConditionProviderEnabled(String path) {
- enforceSystemOrSystemUIOrVolume("INotificationManager.isSystemConditionProviderEnabled");
+ enforceSystemOrSystemUI("INotificationManager.isSystemConditionProviderEnabled");
return mConditionProviders.isSystemProviderEnabled(path);
}
@@ -2338,13 +2358,36 @@
}
@Override
+ public void applyEnqueuedAdjustmentFromAssistant(INotificationListener token,
+ Adjustment adjustment) throws RemoteException {
+ final long identity = Binder.clearCallingIdentity();
+ try {
+ synchronized (mEnqueuedNotifications) {
+ mNotificationAssistants.checkServiceTokenLocked(token);
+ int N = mEnqueuedNotifications.size();
+ for (int i = 0; i < N; i++) {
+ final NotificationRecord n = mEnqueuedNotifications.get(i);
+ if (Objects.equals(adjustment.getKey(), n.getKey())
+ && Objects.equals(adjustment.getUser(), n.getUserId())) {
+ applyAdjustment(n, adjustment);
+ break;
+ }
+ }
+ }
+ } finally {
+ Binder.restoreCallingIdentity(identity);
+ }
+ }
+
+ @Override
public void applyAdjustmentFromAssistant(INotificationListener token,
Adjustment adjustment) throws RemoteException {
final long identity = Binder.clearCallingIdentity();
try {
synchronized (mNotificationList) {
mNotificationAssistants.checkServiceTokenLocked(token);
- applyAdjustmentLocked(adjustment);
+ NotificationRecord n = mNotificationsByKey.get(adjustment.getKey());
+ applyAdjustment(n, adjustment);
}
mRankingHandler.requestSort(true);
} finally {
@@ -2361,7 +2404,8 @@
synchronized (mNotificationList) {
mNotificationAssistants.checkServiceTokenLocked(token);
for (Adjustment adjustment : adjustments) {
- applyAdjustmentLocked(adjustment);
+ NotificationRecord n = mNotificationsByKey.get(adjustment.getKey());
+ applyAdjustment(n, adjustment);
}
}
mRankingHandler.requestSort(true);
@@ -2398,7 +2442,7 @@
public void updateNotificationChannelFromAssistant(INotificationListener token, String pkg,
NotificationChannel channel) throws RemoteException {
ManagedServiceInfo info = mNotificationAssistants.checkServiceTokenLocked(token);
- if (!channel.isAllowed()) {
+ if (channel.getImportance() == NotificationManager.IMPORTANCE_NONE) {
// cancel
cancelAllNotificationsInt(MY_UID, MY_PID, pkg, channel.getId(), 0, 0, true,
info.userid, REASON_CHANNEL_BANNED, null);
@@ -2418,8 +2462,7 @@
}
};
- private void applyAdjustmentLocked(Adjustment adjustment) {
- NotificationRecord n = mNotificationsByKey.get(adjustment.getKey());
+ private void applyAdjustment(NotificationRecord n, Adjustment adjustment) {
if (n == null) {
return;
}
@@ -2627,6 +2670,21 @@
}
}
+ synchronized (mEnqueuedNotifications) {
+ if (!zenOnly) {
+ N = mEnqueuedNotifications.size();
+ if (N > 0) {
+ pw.println(" Enqueued Notification List:");
+ for (int i = 0; i < N; i++) {
+ final NotificationRecord nr = mEnqueuedNotifications.get(i);
+ if (filter.filtered && !filter.matches(nr.sbn)) continue;
+ nr.dump(pw, " ", getContext(), filter.redact);
+ }
+ pw.println(" ");
+ }
+ }
+ }
+
if (!zenOnly) {
pw.println("\n Usage Stats:");
mUsageStats.dump(pw, " ", filter);
@@ -2835,6 +2893,9 @@
// setup local book-keeping
final NotificationRecord r = new NotificationRecord(getContext(), n);
+ synchronized (mEnqueuedNotifications) {
+ mEnqueuedNotifications.add(r);
+ }
mHandler.post(new EnqueueNotificationRunnable(userId, r));
idOut[0] = id;
@@ -2851,7 +2912,6 @@
@Override
public void run() {
-
synchronized (mNotificationList) {
if (mSnoozeHelper.isSnoozed(userId, r.sbn.getPackageName(), r.getKey())) {
// TODO: log to event log
@@ -2877,8 +2937,6 @@
final String pkg = n.getPackageName();
final int id = n.getId();
final String tag = n.getTag();
- final boolean isSystemNotification = isUidSystem(callingUid) ||
- ("android".equals(pkg));
// Handle grouped notifications and bail out early if we
// can to avoid extracting signals.
@@ -2907,65 +2965,11 @@
// tell the assistant service about the notification
if (mNotificationAssistants.isEnabled()) {
mNotificationAssistants.onNotificationEnqueued(r);
- // TODO delay the code below here for 100ms or until there is an answer
- }
-
-
- int index = indexOfNotificationLocked(n.getKey());
- if (index < 0) {
- mNotificationList.add(r);
- mUsageStats.registerPostedByApp(r);
+ mHandler.postDelayed(new PostNotificationRunnable(userId, r.getKey()),
+ DELAY_FOR_ASSISTANT_TIME);
} else {
- old = mNotificationList.get(index);
- mNotificationList.set(index, r);
- mUsageStats.registerUpdatedByApp(r, old);
- // Make sure we don't lose the foreground service state.
- notification.flags |=
- old.getNotification().flags & Notification.FLAG_FOREGROUND_SERVICE;
- r.isUpdate = true;
+ mHandler.post(new PostNotificationRunnable(userId, r.getKey()));
}
-
- mNotificationsByKey.put(n.getKey(), r);
-
- // Ensure if this is a foreground service that the proper additional
- // flags are set.
- if ((notification.flags & Notification.FLAG_FOREGROUND_SERVICE) != 0) {
- notification.flags |= Notification.FLAG_ONGOING_EVENT
- | Notification.FLAG_NO_CLEAR;
- }
-
- applyZenModeLocked(r);
- mRankingHelper.sort(mNotificationList);
-
- if (notification.getSmallIcon() != null) {
- StatusBarNotification oldSbn = (old != null) ? old.sbn : null;
- mListeners.notifyPostedLocked(n, oldSbn);
- mHandler.post(new Runnable() {
- @Override
- public void run() {
- mGroupHelper.onNotificationPosted(n);
- }
- });
- } else {
- Slog.e(TAG, "Not posting notification without small icon: " + notification);
- if (old != null && !old.isCanceled) {
- mListeners.notifyRemovedLocked(n,
- NotificationListenerService.REASON_DELEGATE_ERROR);
- mHandler.post(new Runnable() {
- @Override
- public void run() {
- mGroupHelper.onNotificationRemoved(n);
- }
- });
- }
- // ATTENTION: in a future release we will bail out here
- // so that we do not play sounds, show lights, etc. for invalid
- // notifications
- Slog.e(TAG, "WARNING: In a future release this will crash the app: "
- + n.getPackageName());
- }
-
- buzzBeepBlinkLocked(r);
}
}
@@ -2982,7 +2986,7 @@
}
final boolean isBlocked = r.getImportance() == NotificationManager.IMPORTANCE_NONE
- || !r.getChannel().isAllowed()
+ || r.getChannel().getImportance() == NotificationManager.IMPORTANCE_NONE
|| !noteNotificationOp(pkg, callingUid);
if (isBlocked) {
Slog.e(TAG, "Suppressing notification from package by user request.");
@@ -2992,6 +2996,108 @@
}
}
+ protected class PostNotificationRunnable implements Runnable {
+ private final String key;
+ private final int userId;
+
+ PostNotificationRunnable(int userId, String key) {
+ this.userId = userId;
+ this.key = key;
+ }
+
+ @Override
+ public void run() {
+ try {
+ NotificationRecord r = null;
+ synchronized (mEnqueuedNotifications) {
+ int N = mEnqueuedNotifications.size();
+ for (int i = 0; i < N; i++) {
+ final NotificationRecord enqueued = mEnqueuedNotifications.get(i);
+ if (Objects.equals(key, enqueued.getKey())) {
+ r = enqueued;
+ break;
+ }
+ }
+ }
+ if (r == null) {
+ Slog.e(TAG, "Cannot find enqueued record for key: " + key);
+ return;
+ }
+ synchronized (mNotificationList) {
+ NotificationRecord old = mNotificationsByKey.get(key);
+ final StatusBarNotification n = r.sbn;
+ final Notification notification = n.getNotification();
+ int index = indexOfNotificationLocked(n.getKey());
+ if (index < 0) {
+ mNotificationList.add(r);
+ mUsageStats.registerPostedByApp(r);
+ } else {
+ old = mNotificationList.get(index);
+ mNotificationList.set(index, r);
+ mUsageStats.registerUpdatedByApp(r, old);
+ // Make sure we don't lose the foreground service state.
+ notification.flags |=
+ old.getNotification().flags & Notification.FLAG_FOREGROUND_SERVICE;
+ r.isUpdate = true;
+ }
+
+ mNotificationsByKey.put(n.getKey(), r);
+
+ // Ensure if this is a foreground service that the proper additional
+ // flags are set.
+ if ((notification.flags & Notification.FLAG_FOREGROUND_SERVICE) != 0) {
+ notification.flags |= Notification.FLAG_ONGOING_EVENT
+ | Notification.FLAG_NO_CLEAR;
+ }
+
+ applyZenModeLocked(r);
+ mRankingHelper.sort(mNotificationList);
+
+ if (notification.getSmallIcon() != null) {
+ StatusBarNotification oldSbn = (old != null) ? old.sbn : null;
+ mListeners.notifyPostedLocked(n, oldSbn);
+ mHandler.post(new Runnable() {
+ @Override
+ public void run() {
+ mGroupHelper.onNotificationPosted(n);
+ }
+ });
+ } else {
+ Slog.e(TAG, "Not posting notification without small icon: " + notification);
+ if (old != null && !old.isCanceled) {
+ mListeners.notifyRemovedLocked(n,
+ NotificationListenerService.REASON_DELEGATE_ERROR);
+ mHandler.post(new Runnable() {
+ @Override
+ public void run() {
+ mGroupHelper.onNotificationRemoved(n);
+ }
+ });
+ }
+ // ATTENTION: in a future release we will bail out here
+ // so that we do not play sounds, show lights, etc. for invalid
+ // notifications
+ Slog.e(TAG, "WARNING: In a future release this will crash the app: "
+ + n.getPackageName());
+ }
+
+ buzzBeepBlinkLocked(r);
+ }
+ } finally {
+ synchronized (mEnqueuedNotifications) {
+ int N = mEnqueuedNotifications.size();
+ for (int i = 0; i < N; i++) {
+ final NotificationRecord enqueued = mEnqueuedNotifications.get(i);
+ if (Objects.equals(key, enqueued.getKey())) {
+ mEnqueuedNotifications.remove(i);
+ break;
+ }
+ }
+ }
+ }
+ }
+ }
+
/**
* Ensures that grouped notification receive their special treatment.
*
diff --git a/services/core/java/com/android/server/notification/NotificationRecord.java b/services/core/java/com/android/server/notification/NotificationRecord.java
index dbd719b..e8c3d97 100644
--- a/services/core/java/com/android/server/notification/NotificationRecord.java
+++ b/services/core/java/com/android/server/notification/NotificationRecord.java
@@ -39,6 +39,7 @@
import android.service.notification.NotificationListenerService;
import android.service.notification.SnoozeCriterion;
import android.service.notification.StatusBarNotification;
+import android.text.TextUtils;
import android.util.Log;
import android.util.Slog;
@@ -318,7 +319,7 @@
if (notification.actions != null && notification.actions.length > 0) {
pw.println(prefix + " actions={");
final int N = notification.actions.length;
- for (int i=0; i<N; i++) {
+ for (int i = 0; i < N; i++) {
final Notification.Action action = notification.actions[i];
if (action != null) {
pw.println(String.format("%s [%d] \"%s\" -> %s",
@@ -350,7 +351,7 @@
final int N = Array.getLength(val);
pw.print(" (" + N + ")");
if (!redact) {
- for (int j=0; j<N; j++) {
+ for (int j = 0; j < N; j++) {
pw.println();
pw.print(String.format("%s [%d] %s",
prefix, j, String.valueOf(Array.get(val, j))));
@@ -385,6 +386,13 @@
pw.println(prefix + " mSound= " + mSound);
pw.println(prefix + " mVibration= " + mVibration);
pw.println(prefix + " mAttributes= " + mAttributes);
+ pw.println(prefix + " overrideChannel=" + getChannel());
+ if (getPeopleOverride() != null) {
+ pw.println(prefix + " overridePeople= " + TextUtils.join(",", getPeopleOverride()));
+ }
+ if (getSnoozeCriteria() != null) {
+ pw.println(prefix + " snoozeCriteria=" + TextUtils.join(",", getSnoozeCriteria()));
+ }
}
diff --git a/services/core/java/com/android/server/notification/RankingHelper.java b/services/core/java/com/android/server/notification/RankingHelper.java
index 6474613..3fcce3c 100644
--- a/services/core/java/com/android/server/notification/RankingHelper.java
+++ b/services/core/java/com/android/server/notification/RankingHelper.java
@@ -434,7 +434,8 @@
}
if (r.channels.containsKey(channel.getId()) || channel.getName().equals(
mContext.getString(R.string.default_notification_channel_label))) {
- throw new IllegalArgumentException("Channel already exists");
+ // Channel already exists, no-op.
+ return;
}
if (channel.getImportance() < NotificationManager.IMPORTANCE_NONE
|| channel.getImportance() > NotificationManager.IMPORTANCE_MAX) {
@@ -442,11 +443,9 @@
}
// Reset fields that apps aren't allowed to set.
if (fromTargetApp) {
- channel.setShowBadge(false);
channel.setBypassDnd(r.priority == Notification.PRIORITY_MAX);
channel.setLockscreenVisibility(r.visibility);
}
- channel.setAllowed(true);
clearLockedFields(channel);
if (channel.getLockscreenVisibility() == Notification.VISIBILITY_PUBLIC) {
channel.setLockscreenVisibility(Ranking.VISIBILITY_NO_OVERRIDE);
@@ -517,9 +516,6 @@
channel.setLockscreenVisibility(updatedChannel.getLockscreenVisibility());
}
}
- if ((channel.getUserLockedFields() & NotificationChannel.USER_LOCKED_ALLOWED) == 0) {
- channel.setAllowed(updatedChannel.isAllowed());
- }
if ((channel.getUserLockedFields() & NotificationChannel.USER_LOCKED_SHOW_BADGE) == 0) {
channel.setShowBadge(updatedChannel.canShowBadge());
}
diff --git a/services/core/java/com/android/server/notification/SnoozeHelper.java b/services/core/java/com/android/server/notification/SnoozeHelper.java
index 409eef4..733ff67 100644
--- a/services/core/java/com/android/server/notification/SnoozeHelper.java
+++ b/services/core/java/com/android/server/notification/SnoozeHelper.java
@@ -36,6 +36,9 @@
import java.io.IOException;
import java.io.PrintWriter;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
import java.util.Date;
import java.util.Map;
import java.util.Objects;
@@ -84,6 +87,14 @@
&& mSnoozedNotifications.get(userId).get(pkg).containsKey(key);
}
+ protected Collection<NotificationRecord> getSnoozed(int userId, String pkg) {
+ if (mSnoozedNotifications.containsKey(userId)
+ && mSnoozedNotifications.get(userId).containsKey(pkg)) {
+ mSnoozedNotifications.get(userId).get(pkg).values();
+ }
+ return Collections.EMPTY_LIST;
+ }
+
/**
* Snoozes a notification and schedules an alarm to repost at that time.
*/
diff --git a/services/core/java/com/android/server/pm/BackgroundDexOptService.java b/services/core/java/com/android/server/pm/BackgroundDexOptService.java
index cec1058..601a219 100644
--- a/services/core/java/com/android/server/pm/BackgroundDexOptService.java
+++ b/services/core/java/com/android/server/pm/BackgroundDexOptService.java
@@ -42,12 +42,18 @@
* {@hide}
*/
public class BackgroundDexOptService extends JobService {
- static final String TAG = "BackgroundDexOptService";
+ private static final String TAG = "BackgroundDexOptService";
- static final long RETRY_LATENCY = 4 * AlarmManager.INTERVAL_HOUR;
+ private static final boolean DEBUG = false;
- static final int JOB_IDLE_OPTIMIZE = 800;
- static final int JOB_POST_BOOT_UPDATE = 801;
+ private static final long RETRY_LATENCY = 4 * AlarmManager.INTERVAL_HOUR;
+
+ private static final int JOB_IDLE_OPTIMIZE = 800;
+ private static final int JOB_POST_BOOT_UPDATE = 801;
+
+ private static final long IDLE_OPTIMIZATION_PERIOD = DEBUG
+ ? TimeUnit.MINUTES.toMillis(1)
+ : TimeUnit.DAYS.toMillis(1);
private static ComponentName sDexoptServiceName = new ComponentName(
"android",
@@ -69,7 +75,7 @@
*/
final AtomicBoolean mExitPostBootUpdate = new AtomicBoolean(false);
- private final File dataDir = Environment.getDataDirectory();
+ private final File mDataDir = Environment.getDataDirectory();
public static void schedule(Context context) {
JobScheduler js = (JobScheduler) context.getSystemService(Context.JOB_SCHEDULER_SERVICE);
@@ -86,7 +92,7 @@
js.schedule(new JobInfo.Builder(JOB_IDLE_OPTIMIZE, sDexoptServiceName)
.setRequiresDeviceIdle(true)
.setRequiresCharging(true)
- .setPeriodic(TimeUnit.DAYS.toMillis(1))
+ .setPeriodic(IDLE_OPTIMIZATION_PERIOD)
.build());
if (DEBUG_DEXOPT) {
@@ -120,7 +126,7 @@
private long getLowStorageThreshold() {
@SuppressWarnings("deprecation")
- final long lowThreshold = StorageManager.from(this).getStorageLowBytes(dataDir);
+ final long lowThreshold = StorageManager.from(this).getStorageLowBytes(mDataDir);
if (lowThreshold == 0) {
Log.e(TAG, "Invalid low storage threshold");
}
@@ -134,114 +140,127 @@
// This job has already been superseded. Do not start it.
return false;
}
-
- // Load low battery threshold from the system config. This is a 0-100 integer.
- final int lowBatteryThreshold = getResources().getInteger(
- com.android.internal.R.integer.config_lowBatteryWarningLevel);
-
- final long lowThreshold = getLowStorageThreshold();
-
- mAbortPostBootUpdate.set(false);
new Thread("BackgroundDexOptService_PostBootUpdate") {
@Override
public void run() {
- for (String pkg : pkgs) {
- if (mAbortPostBootUpdate.get()) {
- // JobScheduler requested an early abort.
- return;
- }
- if (mExitPostBootUpdate.get()) {
- // Different job, which supersedes this one, is running.
- break;
- }
- if (getBatteryLevel() < lowBatteryThreshold) {
- // Rather bail than completely drain the battery.
- break;
- }
- long usableSpace = dataDir.getUsableSpace();
- if (usableSpace < lowThreshold) {
- // Rather bail than completely fill up the disk.
- Log.w(TAG, "Aborting background dex opt job due to low storage: " +
- usableSpace);
- break;
- }
+ postBootUpdate(jobParams, pm, pkgs);
+ }
- if (DEBUG_DEXOPT) {
- Log.i(TAG, "Updating package " + pkg);
- }
+ }.start();
+ return true;
+ }
- // Update package if needed. Note that there can be no race between concurrent
- // jobs because PackageDexOptimizer.performDexOpt is synchronized.
+ private void postBootUpdate(JobParameters jobParams, PackageManagerService pm,
+ ArraySet<String> pkgs) {
+ // Load low battery threshold from the system config. This is a 0-100 integer.
+ final int lowBatteryThreshold = getResources().getInteger(
+ com.android.internal.R.integer.config_lowBatteryWarningLevel);
+ final long lowThreshold = getLowStorageThreshold();
- // checkProfiles is false to avoid merging profiles during boot which
- // might interfere with background compilation (b/28612421).
- // Unfortunately this will also means that "pm.dexopt.boot=speed-profile" will
- // behave differently than "pm.dexopt.bg-dexopt=speed-profile" but that's a
- // trade-off worth doing to save boot time work.
- pm.performDexOpt(pkg,
- /* checkProfiles */ false,
- PackageManagerService.REASON_BOOT,
- /* force */ false);
- }
- // Ran to completion, so we abandon our timeslice and do not reschedule.
- jobFinished(jobParams, /* reschedule */ false);
+ mAbortPostBootUpdate.set(false);
+
+ for (String pkg : pkgs) {
+ if (mAbortPostBootUpdate.get()) {
+ // JobScheduler requested an early abort.
+ return;
+ }
+ if (mExitPostBootUpdate.get()) {
+ // Different job, which supersedes this one, is running.
+ break;
+ }
+ if (getBatteryLevel() < lowBatteryThreshold) {
+ // Rather bail than completely drain the battery.
+ break;
+ }
+ long usableSpace = mDataDir.getUsableSpace();
+ if (usableSpace < lowThreshold) {
+ // Rather bail than completely fill up the disk.
+ Log.w(TAG, "Aborting background dex opt job due to low storage: " +
+ usableSpace);
+ break;
+ }
+
+ if (DEBUG_DEXOPT) {
+ Log.i(TAG, "Updating package " + pkg);
+ }
+
+ // Update package if needed. Note that there can be no race between concurrent
+ // jobs because PackageDexOptimizer.performDexOpt is synchronized.
+
+ // checkProfiles is false to avoid merging profiles during boot which
+ // might interfere with background compilation (b/28612421).
+ // Unfortunately this will also means that "pm.dexopt.boot=speed-profile" will
+ // behave differently than "pm.dexopt.bg-dexopt=speed-profile" but that's a
+ // trade-off worth doing to save boot time work.
+ pm.performDexOpt(pkg,
+ /* checkProfiles */ false,
+ PackageManagerService.REASON_BOOT,
+ /* force */ false);
+ }
+ // Ran to completion, so we abandon our timeslice and do not reschedule.
+ jobFinished(jobParams, /* reschedule */ false);
+ }
+
+ private boolean runIdleOptimization(final JobParameters jobParams,
+ final PackageManagerService pm, final ArraySet<String> pkgs) {
+ new Thread("BackgroundDexOptService_IdleOptimization") {
+ @Override
+ public void run() {
+ idleOptimization(jobParams, pm, pkgs);
}
}.start();
return true;
}
- private boolean runIdleOptimization(final JobParameters jobParams,
- final PackageManagerService pm, final ArraySet<String> pkgs) {
+ private void idleOptimization(JobParameters jobParams, PackageManagerService pm,
+ ArraySet<String> pkgs) {
+ Log.i(TAG, "Performing idle optimizations");
// If post-boot update is still running, request that it exits early.
mExitPostBootUpdate.set(true);
mAbortIdleOptimization.set(false);
final long lowThreshold = getLowStorageThreshold();
-
- new Thread("BackgroundDexOptService_IdleOptimization") {
- @Override
- public void run() {
- for (String pkg : pkgs) {
- if (mAbortIdleOptimization.get()) {
- // JobScheduler requested an early abort.
- return;
- }
- if (sFailedPackageNames.contains(pkg)) {
- // Skip previously failing package
- continue;
- }
-
- long usableSpace = dataDir.getUsableSpace();
- if (usableSpace < lowThreshold) {
- // Rather bail than completely fill up the disk.
- Log.w(TAG, "Aborting background dex opt job due to low storage: " +
- usableSpace);
- break;
- }
-
- // Conservatively add package to the list of failing ones in case performDexOpt
- // never returns.
- synchronized (sFailedPackageNames) {
- sFailedPackageNames.add(pkg);
- }
- // Optimize package if needed. Note that there can be no race between
- // concurrent jobs because PackageDexOptimizer.performDexOpt is synchronized.
- if (pm.performDexOpt(pkg,
- /* checkProfiles */ true,
- PackageManagerService.REASON_BACKGROUND_DEXOPT,
- /* force */ false)) {
- // Dexopt succeeded, remove package from the list of failing ones.
- synchronized (sFailedPackageNames) {
- sFailedPackageNames.remove(pkg);
- }
- }
- }
- // Ran to completion, so we abandon our timeslice and do not reschedule.
- jobFinished(jobParams, /* reschedule */ false);
+ for (String pkg : pkgs) {
+ if (mAbortIdleOptimization.get()) {
+ // JobScheduler requested an early abort.
+ return;
}
- }.start();
- return true;
+
+ synchronized (sFailedPackageNames) {
+ if (sFailedPackageNames.contains(pkg)) {
+ // Skip previously failing package
+ continue;
+ }
+ }
+
+ long usableSpace = mDataDir.getUsableSpace();
+ if (usableSpace < lowThreshold) {
+ // Rather bail than completely fill up the disk.
+ Log.w(TAG, "Aborting background dex opt job due to low storage: " +
+ usableSpace);
+ break;
+ }
+
+ // Conservatively add package to the list of failing ones in case performDexOpt
+ // never returns.
+ synchronized (sFailedPackageNames) {
+ sFailedPackageNames.add(pkg);
+ }
+ // Optimize package if needed. Note that there can be no race between
+ // concurrent jobs because PackageDexOptimizer.performDexOpt is synchronized.
+ if (pm.performDexOpt(pkg,
+ /* checkProfiles */ true,
+ PackageManagerService.REASON_BACKGROUND_DEXOPT,
+ /* force */ false)) {
+ // Dexopt succeeded, remove package from the list of failing ones.
+ synchronized (sFailedPackageNames) {
+ sFailedPackageNames.remove(pkg);
+ }
+ }
+ }
+ // Ran to completion, so we abandon our timeslice and do not reschedule.
+ jobFinished(jobParams, /* reschedule */ false);
}
@Override
diff --git a/services/core/java/com/android/server/pm/DefaultPermissionGrantPolicy.java b/services/core/java/com/android/server/pm/DefaultPermissionGrantPolicy.java
index 00e45fd..95023da 100644
--- a/services/core/java/com/android/server/pm/DefaultPermissionGrantPolicy.java
+++ b/services/core/java/com/android/server/pm/DefaultPermissionGrantPolicy.java
@@ -1000,7 +1000,7 @@
permissions.clear();
}
permissions.add(permissionGrant.name);
- grantRuntimePermissionsLPw(pkg, permissions, false,
+ grantRuntimePermissionsLPw(pkg, permissions,
permissionGrant.fixed, userId);
}
}
diff --git a/services/core/java/com/android/server/pm/Installer.java b/services/core/java/com/android/server/pm/Installer.java
index 1f83d9e..98249dd1 100644
--- a/services/core/java/com/android/server/pm/Installer.java
+++ b/services/core/java/com/android/server/pm/Installer.java
@@ -54,6 +54,7 @@
// NOTE: keep in sync with installd
public static final int FLAG_CLEAR_CACHE_ONLY = 1 << 8;
public static final int FLAG_CLEAR_CODE_CACHE_ONLY = 1 << 9;
+ public static final int FLAG_USE_QUOTA = 1 << 12;
private final boolean mIsolated;
@@ -198,15 +199,44 @@
}
}
- public void getAppSize(String uuid, String packageName, int userId, int flags, long ceDataInode,
- String codePath, PackageStats stats) throws InstallerException {
+ public void getAppSize(String uuid, String[] packageNames, int userId, int flags, int appId,
+ long[] ceDataInodes, String[] codePaths, PackageStats stats)
+ throws InstallerException {
if (!checkBeforeRemote()) return;
try {
- final long[] res = mInstalld.getAppSize(uuid, packageName, userId, flags, ceDataInode,
- codePath);
+ final long[] res = mInstalld.getAppSize(uuid, packageNames, userId, flags,
+ appId, ceDataInodes, codePaths);
stats.codeSize += res[0];
stats.dataSize += res[1];
stats.cacheSize += res[2];
+ stats.externalCodeSize += res[3];
+ stats.externalDataSize += res[4];
+ stats.externalCacheSize += res[5];
+ } catch (Exception e) {
+ throw InstallerException.from(e);
+ }
+ }
+
+ public void getUserSize(String uuid, int userId, int flags, int[] appIds, PackageStats stats)
+ throws InstallerException {
+ if (!checkBeforeRemote()) return;
+ try {
+ final long[] res = mInstalld.getUserSize(uuid, userId, flags, appIds);
+ stats.codeSize += res[0];
+ stats.dataSize += res[1];
+ stats.cacheSize += res[2];
+ stats.externalCodeSize += res[3];
+ stats.externalDataSize += res[4];
+ stats.externalCacheSize += res[5];
+ } catch (Exception e) {
+ throw InstallerException.from(e);
+ }
+ }
+
+ public long[] getExternalSize(String uuid, int userId, int flags) throws InstallerException {
+ if (!checkBeforeRemote()) return new long[4];
+ try {
+ return mInstalld.getExternalSize(uuid, userId, flags);
} catch (Exception e) {
throw InstallerException.from(e);
}
diff --git a/services/core/java/com/android/server/pm/PackageInstallerSession.java b/services/core/java/com/android/server/pm/PackageInstallerSession.java
index c85e1d8..d1aed3e 100644
--- a/services/core/java/com/android/server/pm/PackageInstallerSession.java
+++ b/services/core/java/com/android/server/pm/PackageInstallerSession.java
@@ -703,8 +703,11 @@
for (File addedFile : addedFiles) {
final ApkLite apk;
try {
- apk = PackageParser.parseApkLite(
- addedFile, PackageParser.PARSE_COLLECT_CERTIFICATES);
+ int flags = PackageParser.PARSE_COLLECT_CERTIFICATES;
+ if ((params.installFlags & PackageManager.INSTALL_EPHEMERAL) != 0) {
+ flags |= PackageParser.PARSE_IS_EPHEMERAL;
+ }
+ apk = PackageParser.parseApkLite(addedFile, flags);
} catch (PackageParserException e) {
throw PackageManagerException.from(e);
}
diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java
index 88c5a17..76ae57e 100644
--- a/services/core/java/com/android/server/pm/PackageManagerService.java
+++ b/services/core/java/com/android/server/pm/PackageManagerService.java
@@ -102,7 +102,6 @@
import android.Manifest;
import android.annotation.NonNull;
import android.annotation.Nullable;
-import android.annotation.UserIdInt;
import android.app.ActivityManager;
import android.app.AppOpsManager;
import android.app.IActivityManager;
@@ -381,6 +380,9 @@
private static final boolean DISABLE_EPHEMERAL_APPS = false;
private static final boolean HIDE_EPHEMERAL_APIS = true;
+ private static final boolean ENABLE_QUOTA =
+ SystemProperties.getBoolean("persist.fw.quota", false);
+
private static final int RADIO_UID = Process.PHONE_UID;
private static final int LOG_UID = Process.LOG_UID;
private static final int NFC_UID = Process.NFC_UID;
@@ -563,6 +565,18 @@
Manifest.permission.WRITE_EXTERNAL_STORAGE,
Manifest.permission.READ_PHONE_NUMBER);
+
+ /**
+ * Version number for the package parser cache. Increment this whenever the format or
+ * extent of cached data changes. See {@code PackageParser#setCacheDir}.
+ */
+ private static final String PACKAGE_PARSER_CACHE_VERSION = "1";
+
+ /**
+ * Whether the package parser cache is enabled.
+ */
+ private static final boolean DEFAULT_PACKAGE_PARSER_CACHE_ENABLED = true;
+
final ServiceThread mHandlerThread;
final PackageHandler mHandler;
@@ -801,6 +815,8 @@
private UserManagerInternal mUserManagerInternal;
+ private File mCacheDir;
+
private static class IFVerificationParams {
PackageParser.Package pkg;
boolean replacing;
@@ -2350,6 +2366,8 @@
}
}
+ mCacheDir = preparePackageParserCache(mIsUpgrade);
+
// Set flag to monitor and not change apk file paths when
// scanning install directories.
int scanFlags = SCAN_BOOTING | SCAN_INITIAL;
@@ -2622,19 +2640,6 @@
mPackageUsage.read(mPackages);
mCompilerStats.read();
- // Read and update the usage of dex files.
- // At this point we know the code paths of the packages, so we can validate
- // the disk file and build the internal cache.
- // The usage file is expected to be small so loading and verifying it
- // should take a fairly small time compare to the other activities (e.g. package
- // scanning).
- final Map<Integer, List<PackageInfo>> userPackages = new HashMap<>();
- final int[] currentUserIds = UserManagerService.getInstance().getUserIds();
- for (int userId : currentUserIds) {
- userPackages.put(userId, getInstalledPackages(/*flags*/ 0, userId).getList());
- }
- mDexManager.load(userPackages);
-
EventLog.writeEvent(EventLogTags.BOOT_PROGRESS_PMS_SCAN_END,
SystemClock.uptimeMillis());
Slog.i(TAG, "Time to scan packages: "
@@ -2792,6 +2797,21 @@
}
mEphemeralApplicationRegistry = new EphemeralApplicationRegistry(this);
+
+ // Read and update the usage of dex files.
+ // Do this at the end of PM init so that all the packages have their
+ // data directory reconciled.
+ // At this point we know the code paths of the packages, so we can validate
+ // the disk file and build the internal cache.
+ // The usage file is expected to be small so loading and verifying it
+ // should take a fairly small time compare to the other activities (e.g. package
+ // scanning).
+ final Map<Integer, List<PackageInfo>> userPackages = new HashMap<>();
+ final int[] currentUserIds = UserManagerService.getInstance().getUserIds();
+ for (int userId : currentUserIds) {
+ userPackages.put(userId, getInstalledPackages(/*flags*/ 0, userId).getList());
+ }
+ mDexManager.load(userPackages);
} // synchronized (mPackages)
} // synchronized (mInstallLock)
@@ -2812,6 +2832,35 @@
Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER);
}
+ private static File preparePackageParserCache(boolean isUpgrade) {
+ if (!DEFAULT_PACKAGE_PARSER_CACHE_ENABLED) {
+ return null;
+ }
+
+ if (SystemProperties.getBoolean("ro.boot.disable_package_cache", false)) {
+ Slog.i(TAG, "Disabling package parser cache due to system property.");
+ return null;
+ }
+
+ // The base directory for the package parser cache lives under /data/system/.
+ final File cacheBaseDir = FileUtils.createDir(Environment.getDataSystemDirectory(),
+ "package_cache");
+ if (cacheBaseDir == null) {
+ return null;
+ }
+
+ // If this is a system upgrade scenario, delete the contents of the package cache dir.
+ // This also serves to "GC" unused entries when the package cache version changes (which
+ // can only happen during upgrades).
+ if (isUpgrade) {
+ FileUtils.deleteContents(cacheBaseDir);
+ }
+
+ // Return the versioned package cache directory. This is something like
+ // "/data/system/package_cache/1"
+ return FileUtils.createDir(cacheBaseDir, PACKAGE_PARSER_CACHE_VERSION);
+ }
+
@Override
public boolean isFirstBoot() {
return mFirstBoot;
@@ -6935,7 +6984,7 @@
+ " flags=0x" + Integer.toHexString(parseFlags));
}
ParallelPackageParser parallelPackageParser = new ParallelPackageParser(
- mSeparateProcesses, mOnlyCore, mMetrics);
+ mSeparateProcesses, mOnlyCore, mMetrics, mCacheDir);
// Submit files for parsing in parallel
int fileCount = 0;
@@ -17401,20 +17450,28 @@
return false;
}
}
+
+ final String[] packageNames = { packageName };
+ final long[] ceDataInodes = { ps.getCeDataInode(userId) };
+ final String[] codePaths = { ps.codePathString };
+
try {
- mInstaller.getAppSize(ps.volumeUuid, packageName, userId,
- StorageManager.FLAG_STORAGE_DE | StorageManager.FLAG_STORAGE_CE,
- ps.getCeDataInode(userId), ps.codePathString, stats);
+ mInstaller.getAppSize(ps.volumeUuid, packageNames, userId, 0,
+ ps.appId, ceDataInodes, codePaths, stats);
+
+ // For now, ignore code size of packages on system partition
+ if (isSystemApp(ps) && !isUpdatedSystemApp(ps)) {
+ stats.codeSize = 0;
+ }
+
+ // External clients expect these to be tracked separately
+ stats.dataSize -= stats.cacheSize;
+
} catch (InstallerException e) {
Slog.w(TAG, String.valueOf(e));
return false;
}
- // For now, ignore code size of packages on system partition
- if (isSystemApp(ps) && !isUpdatedSystemApp(ps)) {
- stats.codeSize = 0;
- }
-
return true;
}
diff --git a/services/core/java/com/android/server/pm/ParallelPackageParser.java b/services/core/java/com/android/server/pm/ParallelPackageParser.java
index 158cfc94..6033855 100644
--- a/services/core/java/com/android/server/pm/ParallelPackageParser.java
+++ b/services/core/java/com/android/server/pm/ParallelPackageParser.java
@@ -22,15 +22,13 @@
import android.util.DisplayMetrics;
import com.android.internal.annotations.VisibleForTesting;
+import com.android.internal.util.ConcurrentUtils;
import java.io.File;
import java.util.List;
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.ExecutorService;
-import java.util.concurrent.Executors;
-import java.util.concurrent.ThreadFactory;
-import java.util.concurrent.atomic.AtomicInteger;
import static android.os.Trace.TRACE_TAG_PACKAGE_MANAGER;
@@ -47,31 +45,20 @@
private final String[] mSeparateProcesses;
private final boolean mOnlyCore;
private final DisplayMetrics mMetrics;
+ private final File mCacheDir;
private volatile String mInterruptedInThread;
private final BlockingQueue<ParseResult> mQueue = new ArrayBlockingQueue<>(QUEUE_CAPACITY);
- private final ExecutorService mService = Executors.newFixedThreadPool(MAX_THREADS,
- new ThreadFactory() {
- private final AtomicInteger threadNum = new AtomicInteger(0);
-
- @Override
- public Thread newThread(final Runnable r) {
- return new Thread("package-parsing-thread" + threadNum.incrementAndGet()) {
- @Override
- public void run() {
- Process.setThreadPriority(Process.THREAD_PRIORITY_FOREGROUND);
- r.run();
- }
- };
- }
- });
+ private final ExecutorService mService = ConcurrentUtils.newFixedThreadPool(MAX_THREADS,
+ "package-parsing-thread", Process.THREAD_PRIORITY_FOREGROUND);
ParallelPackageParser(String[] separateProcesses, boolean onlyCoreApps,
- DisplayMetrics metrics) {
+ DisplayMetrics metrics, File cacheDir) {
mSeparateProcesses = separateProcesses;
mOnlyCore = onlyCoreApps;
mMetrics = metrics;
+ mCacheDir = cacheDir;
}
static class ParseResult {
@@ -122,6 +109,7 @@
pp.setSeparateProcesses(mSeparateProcesses);
pp.setOnlyCoreApps(mOnlyCore);
pp.setDisplayMetrics(mMetrics);
+ pp.setCacheDir(mCacheDir);
pr.scanFile = scanFile;
pr.pkg = parsePackage(pp, scanFile, parseFlags);
} catch (Throwable e) {
@@ -144,7 +132,7 @@
@VisibleForTesting
protected PackageParser.Package parsePackage(PackageParser packageParser, File scanFile,
int parseFlags) throws PackageParser.PackageParserException {
- return packageParser.parsePackage(scanFile, parseFlags);
+ return packageParser.parsePackage(scanFile, parseFlags, true /* useCaches */);
}
@Override
diff --git a/services/core/java/com/android/server/pm/ShortcutPackage.java b/services/core/java/com/android/server/pm/ShortcutPackage.java
index b745062..ddbc5fa 100644
--- a/services/core/java/com/android/server/pm/ShortcutPackage.java
+++ b/services/core/java/com/android/server/pm/ShortcutPackage.java
@@ -259,11 +259,6 @@
for (int i = mShortcuts.size() - 1; i >= 0; i--) {
final ShortcutInfo si = mShortcuts.valueAt(i);
- if (si.isFloating()) {
- si.setRank(0);
- si.setActivity(null);
- }
-
if (si.isAlive()) continue;
if (removeList == null) {
@@ -293,7 +288,6 @@
si.setTimestamp(now);
si.clearFlags(ShortcutInfo.FLAG_DYNAMIC);
si.setRank(0); // It may still be pinned, so clear the rank.
- si.setActivity(null);
}
}
if (changed) {
@@ -361,7 +355,6 @@
if (oldShortcut.isPinned()) {
oldShortcut.setRank(0);
- oldShortcut.setActivity(null);
oldShortcut.clearFlags(ShortcutInfo.FLAG_DYNAMIC | ShortcutInfo.FLAG_MANIFEST);
if (disable) {
oldShortcut.addFlags(ShortcutInfo.FLAG_DISABLED);
@@ -602,10 +595,6 @@
for (int i = mShortcuts.size() - 1; i >= 0; i--) {
final ShortcutInfo si = mShortcuts.valueAt(i);
-
- if (si.isFloating()) {
- continue; // Ignore floating shortcuts, which are not tied to any activities.
- }
final ComponentName activity = si.getActivity();
if (checked.contains(activity)) {
@@ -1368,10 +1357,6 @@
case TAG_SHORTCUT:
final ShortcutInfo si = parseShortcut(parser, packageName,
shortcutUser.getUserId());
- // Floating shortcut used to have target activities, but not anymore.
- if (si.isFloating()) { // Not really needed by just in case.
- si.setActivity(null);
- }
// Don't use addShortcut(), we don't need to save the icon.
ret.mShortcuts.put(si.getId(), si);
@@ -1478,6 +1463,7 @@
intents.clear();
intents.add(intentLegacy);
}
+
return new ShortcutInfo(
userId, id, packageName, activityComponent, /* icon =*/ null,
title, titleResId, titleResName, text, textResId, textResName,
@@ -1568,17 +1554,12 @@
Log.e(TAG_VERIFY, "Package " + getPackageName() + ": shortcut " + si.getId()
+ " is both dynamic and manifest at the same time.");
}
- if (!si.isFloating() && si.getActivity() == null) {
+ if (si.getActivity() == null) {
failed = true;
Log.e(TAG_VERIFY, "Package " + getPackageName() + ": shortcut " + si.getId()
- + " is not floating, but has null activity.");
+ + " has null activity.");
}
- if (si.isFloating() && si.getActivity() != null) {
- failed = true;
- Log.e(TAG_VERIFY, "Package " + getPackageName() + ": shortcut " + si.getId()
- + " is floating, but has non-null activity.");
- }
- if (!si.isFloating() && !si.isEnabled()) {
+ if ((si.isDynamic() || si.isManifestShortcut()) && !si.isEnabled()) {
failed = true;
Log.e(TAG_VERIFY, "Package " + getPackageName() + ": shortcut " + si.getId()
+ " is not floating, but is disabled.");
@@ -1601,7 +1582,7 @@
}
if (failed) {
- mShortcutUser.mService.verifyError();
+ throw new IllegalStateException("See logcat for errors");
}
}
diff --git a/services/core/java/com/android/server/pm/ShortcutRequestPinProcessor.java b/services/core/java/com/android/server/pm/ShortcutRequestPinProcessor.java
index cdb69ce..e815f0a 100644
--- a/services/core/java/com/android/server/pm/ShortcutRequestPinProcessor.java
+++ b/services/core/java/com/android/server/pm/ShortcutRequestPinProcessor.java
@@ -16,6 +16,8 @@
package com.android.server.pm;
import android.annotation.Nullable;
+import android.app.PendingIntent;
+import android.appwidget.AppWidgetProviderInfo;
import android.content.ComponentName;
import android.content.Intent;
import android.content.IntentSender;
@@ -46,37 +48,17 @@
/**
* Internal for {@link android.content.pm.LauncherApps.PinItemRequest} which receives callbacks.
*/
- private static class PinShortcutRequestInner extends IPinItemRequest.Stub {
- private final ShortcutRequestPinProcessor mProcessor;
- /** Original shortcut passed by the app. */
- public final ShortcutInfo shortcutOriginal;
-
- /**
- * Cloned shortcut that's passed to the launcher. The notable difference from
- * {@link #shortcutOriginal} is it must not have the intent.
- */
- public final ShortcutInfo shortcutForLauncher;
-
+ private static class PinItemRequestInner extends IPinItemRequest.Stub {
+ protected final ShortcutRequestPinProcessor mProcessor;
private final IntentSender mResultIntent;
- public final String launcherPackage;
- public final int launcherUserId;
- public final boolean preExisting;
-
@GuardedBy("this")
private boolean mAccepted;
- private PinShortcutRequestInner(ShortcutRequestPinProcessor processor,
- ShortcutInfo shortcutOriginal, ShortcutInfo shortcutForLauncher,
- IntentSender resultIntent,
- String launcherPackage, int launcherUserId, boolean preExisting) {
+ private PinItemRequestInner(ShortcutRequestPinProcessor processor,
+ IntentSender resultIntent) {
mProcessor = processor;
- this.shortcutOriginal = shortcutOriginal;
- this.shortcutForLauncher = shortcutForLauncher;
mResultIntent = resultIntent;
- this.launcherPackage = launcherPackage;
- this.launcherUserId = launcherUserId;
- this.preExisting = preExisting;
}
@Override
@@ -95,9 +77,11 @@
public boolean accept(Bundle options) {
// Make sure the options are unparcellable by the FW. (e.g. not containing unknown
// classes.)
+ Intent extras = null;
if (options != null) {
try {
options.size();
+ extras = new Intent().putExtras(options);
} catch (RuntimeException e) {
throw new IllegalArgumentException("options cannot be unparceled", e);
}
@@ -108,20 +92,58 @@
}
mAccepted = true;
}
- if (DEBUG) {
- Slog.d(TAG, "Launcher accepted shortcut. ID=" + shortcutOriginal.getId()
- + " package=" + shortcutOriginal.getPackage()
- + " options=" + options);
- }
// Pin it and send the result intent.
- if (mProcessor.directPinShortcut(this)) {
- mProcessor.sendResultIntent(mResultIntent);
+ if (tryAccept()) {
+ mProcessor.sendResultIntent(mResultIntent, extras);
return true;
} else {
return false;
}
}
+
+ protected boolean tryAccept() {
+ return true;
+ }
+ }
+
+ /**
+ * Internal for {@link android.content.pm.LauncherApps.PinItemRequest} which receives callbacks.
+ */
+ private static class PinShortcutRequestInner extends PinItemRequestInner {
+ /** Original shortcut passed by the app. */
+ public final ShortcutInfo shortcutOriginal;
+
+ /**
+ * Cloned shortcut that's passed to the launcher. The notable difference from
+ * {@link #shortcutOriginal} is it must not have the intent.
+ */
+ public final ShortcutInfo shortcutForLauncher;
+
+ public final String launcherPackage;
+ public final int launcherUserId;
+ public final boolean preExisting;
+
+ private PinShortcutRequestInner(ShortcutRequestPinProcessor processor,
+ ShortcutInfo shortcutOriginal, ShortcutInfo shortcutForLauncher,
+ IntentSender resultIntent,
+ String launcherPackage, int launcherUserId, boolean preExisting) {
+ super(processor, resultIntent);
+ this.shortcutOriginal = shortcutOriginal;
+ this.shortcutForLauncher = shortcutForLauncher;
+ this.launcherPackage = launcherPackage;
+ this.launcherUserId = launcherUserId;
+ this.preExisting = preExisting;
+ }
+
+ @Override
+ protected boolean tryAccept() {
+ if (DEBUG) {
+ Slog.d(TAG, "Launcher accepted shortcut. ID=" + shortcutOriginal.getId()
+ + " package=" + shortcutOriginal.getPackage());
+ }
+ return mProcessor.directPinShortcut(this);
+ }
}
public ShortcutRequestPinProcessor(ShortcutService service, Object lock) {
@@ -134,15 +156,19 @@
}
/**
- * Handle {@link android.content.pm.ShortcutManager#requestPinShortcut)}.
+ * Handle {@link android.content.pm.ShortcutManager#requestPinShortcut)} and
+ * {@link android.appwidget.AppWidgetManager#requestPinAppWidget}.
+ * One of {@param inShortcut} and {@param inAppWidget} is always non-null and the other is
+ * always null.
*/
- public boolean requestPinShortcutLocked(ShortcutInfo inShortcut, IntentSender resultIntent) {
+ public boolean requestPinItemLocked(ShortcutInfo inShortcut, AppWidgetProviderInfo inAppWidget,
+ int userId, IntentSender resultIntent) {
// First, make sure the launcher supports it.
// Find the confirmation activity in the default launcher.
final Pair<ComponentName, Integer> confirmActivity =
- getRequestPinShortcutConfirmationActivity(inShortcut.getUserId());
+ getRequestPinShortcutConfirmationActivity(userId);
// If the launcher doesn't support it, just return a rejected result and finish.
if (confirmActivity == null) {
@@ -150,8 +176,6 @@
return false;
}
- final ComponentName launcherComponent = confirmActivity.first;
- final String launcherPackage = confirmActivity.first.getPackageName();
final int launcherUserId = confirmActivity.second;
// Make sure the launcher user is unlocked. (it's always the parent profile, so should
@@ -159,7 +183,25 @@
mService.throwIfUserLockedL(launcherUserId);
// Next, validate the incoming shortcut, etc.
+ final PinItemRequest request;
+ if (inShortcut != null) {
+ request = requestPinShortcutLocked(inShortcut, resultIntent, confirmActivity);
+ } else {
+ request = new PinItemRequest(inAppWidget, new PinItemRequestInner(this, resultIntent));
+ }
+ if (request == null) {
+ sendResultIntent(resultIntent, null);
+ return true;
+ }
+ return startRequestConfirmActivity(confirmActivity.first, launcherUserId, request);
+ }
+
+ /**
+ * Handle {@link android.content.pm.ShortcutManager#requestPinShortcut)}.
+ */
+ private PinItemRequest requestPinShortcutLocked(ShortcutInfo inShortcut,
+ IntentSender resultIntent, Pair<ComponentName, Integer> confirmActivity) {
final ShortcutPackage ps = mService.getPackageShortcutsForPublisherLocked(
inShortcut.getPackage(), inShortcut.getUserId());
@@ -174,6 +216,8 @@
// This is the shortcut that'll be sent to the launcher.
final ShortcutInfo shortcutForLauncher;
+ final String launcherPackage = confirmActivity.first.getPackageName();
+ final int launcherUserId = confirmActivity.second;
if (existsAlready) {
validateExistingShortcut(existing);
@@ -183,8 +227,7 @@
launcherPackage, existing.getUserId(), launcherUserId).hasPinned(existing)) {
Log.i(TAG, "Launcher's already pinning shortcut " + existing.getId()
+ " for package " + existing.getPackage());
- sendResultIntent(resultIntent);
- return true;
+ return null;
}
// Pass a clone, not the original.
@@ -213,10 +256,7 @@
new PinShortcutRequestInner(this, inShortcut, shortcutForLauncher, resultIntent,
launcherPackage, launcherUserId, existsAlready);
- final PinItemRequest outer = new PinItemRequest(PinItemRequest.REQUEST_TYPE_SHORTCUT,
- shortcutForLauncher, inner);
-
- return startRequestConfirmActivity(launcherComponent, launcherUserId, outer);
+ return new PinItemRequest(shortcutForLauncher, inner);
}
private void validateExistingShortcut(ShortcutInfo shortcutInfo) {
@@ -270,11 +310,11 @@
return (activity == null) ? null : Pair.create(activity, launcherUserId);
}
- public void sendResultIntent(@Nullable IntentSender intent) {
+ public void sendResultIntent(@Nullable IntentSender intent, @Nullable Intent extras) {
if (DEBUG) {
Slog.d(TAG, "Sending result intent.");
}
- mService.injectSendIntentSender(intent);
+ mService.injectSendIntentSender(intent, extras);
}
/**
diff --git a/services/core/java/com/android/server/pm/ShortcutService.java b/services/core/java/com/android/server/pm/ShortcutService.java
index 436a53c..c02ce6e 100644
--- a/services/core/java/com/android/server/pm/ShortcutService.java
+++ b/services/core/java/com/android/server/pm/ShortcutService.java
@@ -24,6 +24,7 @@
import android.app.AppGlobals;
import android.app.IUidObserver;
import android.app.usage.UsageStatsManagerInternal;
+import android.appwidget.AppWidgetProviderInfo;
import android.content.BroadcastReceiver;
import android.content.ComponentName;
import android.content.Context;
@@ -128,7 +129,6 @@
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
-import java.util.Objects;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.function.Consumer;
import java.util.function.Predicate;
@@ -412,9 +412,6 @@
@VisibleForTesting
ShortcutService(Context context, Looper looper, boolean onlyForPackageManagerApis) {
- if (DEBUG) {
- Binder.LOG_RUNTIME_EXCEPTION = true;
- }
mContext = Preconditions.checkNotNull(context);
LocalServices.addService(ShortcutServiceInternal.class, new LocalService());
mHandler = new Handler(looper);
@@ -1777,9 +1774,6 @@
// Note copyNonNullFieldsFrom() does the "updatable with?" check too.
target.copyNonNullFieldsFrom(source);
- if (target.isFloating()) {
- target.setActivity(null);
- }
target.setTimestamp(injectCurrentTimeMillis());
if (replacingIcon) {
@@ -1857,21 +1851,32 @@
@Override
public boolean requestPinShortcut(String packageName, ShortcutInfo shortcut,
IntentSender resultIntent, int userId) {
- verifyCaller(packageName, userId);
Preconditions.checkNotNull(shortcut);
Preconditions.checkArgument(shortcut.isEnabled(), "Shortcut must be enabled");
+ return requestPinItem(packageName, userId, shortcut, null, resultIntent);
+ }
+
+ /**
+ * Handles {@link #requestPinShortcut} and {@link ShortcutServiceInternal#requestPinAppWidget}.
+ * After validating the caller, it passes the request to {@link #mShortcutRequestPinProcessor}.
+ * Either {@param shortcut} or {@param appWidget} should be non-null.
+ */
+ private boolean requestPinItem(String packageName, int userId,
+ ShortcutInfo shortcut, AppWidgetProviderInfo appWidget, IntentSender resultIntent) {
+ verifyCaller(packageName, userId);
final boolean ret;
synchronized (mLock) {
throwIfUserLockedL(userId);
Preconditions.checkState(isUidForegroundLocked(injectBinderCallingUid()),
- "Calling application must have a foreground activity or a foreground service");
+ "Calling application must have a foreground activity or a foreground service");
// TODO Cancel all pending requests from the caller.
// Send request to the launcher, if supported.
- ret = mShortcutRequestPinProcessor.requestPinShortcutLocked(shortcut, resultIntent);
+ ret = mShortcutRequestPinProcessor.requestPinItemLocked(shortcut, appWidget, userId,
+ resultIntent);
}
verifyStates();
@@ -2402,7 +2407,8 @@
return false;
}
if (componentName != null) {
- if (!Objects.equals(componentName, si.getActivity())) {
+ if (si.getActivity() != null
+ && !si.getActivity().equals(componentName)) {
return false;
}
}
@@ -2591,6 +2597,14 @@
@NonNull String callingPackage) {
return ShortcutService.this.hasShortcutHostPermission(callingPackage, launcherUserId);
}
+
+ @Override
+ public boolean requestPinAppWidget(@NonNull String callingPackage,
+ @NonNull AppWidgetProviderInfo appWidget, @Nullable IntentSender resultIntent,
+ int userId) {
+ Preconditions.checkNotNull(appWidget);
+ return requestPinItem(callingPackage, userId, null, appWidget, resultIntent);
+ }
}
final BroadcastReceiver mReceiver = new BroadcastReceiver() {
@@ -3253,12 +3267,12 @@
}
}
- void injectSendIntentSender(IntentSender intentSender) {
+ void injectSendIntentSender(IntentSender intentSender, Intent extras) {
if (intentSender == null) {
return;
}
try {
- intentSender.sendIntent(mContext, /* code= */ 0, /* intent= */ null,
+ intentSender.sendIntent(mContext, /* code= */ 0, extras,
/* onFinished=*/ null, /* handler= */ null);
} catch (SendIntentException e) {
Slog.w(TAG, "sendIntent failed().", e);
@@ -3914,8 +3928,4 @@
forEachLoadedUserLocked(u -> u.forAllPackageItems(ShortcutPackageItem::verifyStates));
}
}
-
- void verifyError() {
- Slog.e(TAG, "See logcat for errors");
- }
}
diff --git a/services/core/java/com/android/server/pm/UserManagerService.java b/services/core/java/com/android/server/pm/UserManagerService.java
index 05228ec..9b47beb 100644
--- a/services/core/java/com/android/server/pm/UserManagerService.java
+++ b/services/core/java/com/android/server/pm/UserManagerService.java
@@ -26,6 +26,7 @@
import android.app.Activity;
import android.app.ActivityManager;
import android.app.ActivityManagerInternal;
+import android.app.ActivityManagerNative;
import android.app.AppGlobals;
import android.app.IActivityManager;
import android.app.IStopUserCallback;
@@ -857,6 +858,25 @@
}
}
+ /**
+ * Evicts a user's CE key by stopping and restarting the user.
+ *
+ * The key is evicted automatically by the user controller when the user has stopped.
+ */
+ @Override
+ public void evictCredentialEncryptionKey(@UserIdInt int userId) {
+ checkManageUsersPermission("evict CE key");
+ final IActivityManager am = ActivityManagerNative.getDefault();
+ final long identity = Binder.clearCallingIdentity();
+ try {
+ am.restartUserInBackground(userId);
+ } catch (RemoteException re) {
+ throw re.rethrowAsRuntimeException();
+ } finally {
+ Binder.restoreCallingIdentity(identity);
+ }
+ }
+
@Override
public UserInfo getUserInfo(int userId) {
checkManageOrCreateUsersPermission("query user");
diff --git a/services/core/java/com/android/server/pm/UserRestrictionsUtils.java b/services/core/java/com/android/server/pm/UserRestrictionsUtils.java
index e91cce1..f5b8669 100644
--- a/services/core/java/com/android/server/pm/UserRestrictionsUtils.java
+++ b/services/core/java/com/android/server/pm/UserRestrictionsUtils.java
@@ -126,8 +126,6 @@
UserManager.DISALLOW_NETWORK_RESET,
UserManager.DISALLOW_FACTORY_RESET,
UserManager.DISALLOW_ADD_USER,
- UserManager.DISALLOW_ADD_MANAGED_PROFILE,
- UserManager.DISALLOW_REMOVE_MANAGED_PROFILE,
UserManager.DISALLOW_CONFIG_CELL_BROADCASTS,
UserManager.DISALLOW_CONFIG_MOBILE_NETWORKS,
UserManager.DISALLOW_MOUNT_PHYSICAL_MEDIA,
@@ -261,6 +259,7 @@
/**
* Returns the user restrictions that default to {@code true} for device owners.
+ * These user restrictions are local, though. ie only for the device owner's user id.
*/
public static @NonNull Set<String> getDefaultEnabledForDeviceOwner() {
return DEFAULT_ENABLED_FOR_DEVICE_OWNERS;
diff --git a/services/core/java/com/android/server/pm/dex/DexManager.java b/services/core/java/com/android/server/pm/dex/DexManager.java
index a1060dc..6d06838 100644
--- a/services/core/java/com/android/server/pm/dex/DexManager.java
+++ b/services/core/java/com/android/server/pm/dex/DexManager.java
@@ -265,19 +265,6 @@
public void mergeAppDataDirs(ApplicationInfo ai, int userId) {
Set<String> dataDirs = putIfAbsent(mAppDataDirs, userId, new HashSet<>());
dataDirs.add(ai.dataDir);
-
- // Compute and cache the real path as well since data dir may be a symlink.
- // e.g. /data/data/ -> /data/user/0/
- try {
- dataDirs.add(PackageManagerServiceUtils.realpath(new File(ai.dataDir)));
- } catch (IOException e) {
- if (DEBUG) {
- // Verify why we're getting spam at boot for some devices.
- // b/33807524
- Slog.w(TAG, "Error to get realpath of " + ai.dataDir, e);
- }
- }
-
}
public int searchDex(String dexPath, int userId) {
@@ -302,6 +289,20 @@
return DEX_SEARCH_FOUND_SECONDARY;
}
}
+
+ // TODO(calin): What if we get a symlink? e.g. data dir may be a symlink,
+ // /data/data/ -> /data/user/0/.
+ if (DEBUG) {
+ try {
+ String dexPathReal = PackageManagerServiceUtils.realpath(new File(dexPath));
+ if (dexPathReal != dexPath) {
+ Slog.d(TAG, "Dex loaded with symlink. dexPath=" +
+ dexPath + " dexPathReal=" + dexPathReal);
+ }
+ } catch (IOException e) {
+ // Ignore
+ }
+ }
return DEX_SEARCH_NOT_FOUND;
}
}
diff --git a/services/core/java/com/android/server/trust/TrustManagerService.java b/services/core/java/com/android/server/trust/TrustManagerService.java
index cca8cc8..c69b87c 100644
--- a/services/core/java/com/android/server/trust/TrustManagerService.java
+++ b/services/core/java/com/android/server/trust/TrustManagerService.java
@@ -25,6 +25,7 @@
import org.xmlpull.v1.XmlPullParserException;
import android.Manifest;
+import android.annotation.UserIdInt;
import android.app.ActivityManager;
import android.app.admin.DevicePolicyManager;
import android.app.trust.ITrustListener;
@@ -103,6 +104,7 @@
private static final int MSG_SWITCH_USER = 9;
private static final int MSG_FLUSH_TRUST_USUALLY_MANAGED = 10;
private static final int MSG_UNLOCK_USER = 11;
+ private static final int MSG_STOP_USER = 12;
private static final int TRUST_USUALLY_MANAGED_FLUSH_DELAY = 2 * 60 * 1000;
@@ -414,15 +416,18 @@
}
}
boolean deviceLocked = secure && showingKeyguard && !trusted;
+ setDeviceLockedForUser(id, deviceLocked);
+ }
+ }
- boolean changed;
- synchronized (mDeviceLockedForUser) {
- changed = isDeviceLockedInner(id) != deviceLocked;
- mDeviceLockedForUser.put(id, deviceLocked);
- }
- if (changed) {
- dispatchDeviceLocked(id, deviceLocked);
- }
+ private void setDeviceLockedForUser(@UserIdInt int userId, boolean locked) {
+ final boolean changed;
+ synchronized (mDeviceLockedForUser) {
+ changed = isDeviceLockedInner(userId) != locked;
+ mDeviceLockedForUser.put(userId, locked);
+ }
+ if (changed) {
+ dispatchDeviceLocked(userId, locked);
}
}
@@ -724,6 +729,11 @@
mHandler.obtainMessage(MSG_UNLOCK_USER, userId, 0, null).sendToTarget();
}
+ @Override
+ public void onStopUser(@UserIdInt int userId) {
+ mHandler.obtainMessage(MSG_STOP_USER, userId, 0, null).sendToTarget();
+ }
+
// Plumbing
private final IBinder mService = new ITrustManager.Stub() {
@@ -982,6 +992,9 @@
mCurrentUser = msg.arg1;
refreshDeviceLockedForUser(UserHandle.USER_ALL);
break;
+ case MSG_STOP_USER:
+ setDeviceLockedForUser(msg.arg1, true);
+ break;
case MSG_FLUSH_TRUST_USUALLY_MANAGED:
SparseBooleanArray usuallyManaged;
synchronized (mTrustUsuallyManagedForUser) {
diff --git a/services/core/java/com/android/server/vr/VrManagerService.java b/services/core/java/com/android/server/vr/VrManagerService.java
index 1083e0a..84cf0c6 100644
--- a/services/core/java/com/android/server/vr/VrManagerService.java
+++ b/services/core/java/com/android/server/vr/VrManagerService.java
@@ -320,7 +320,6 @@
public void onEnabledComponentChanged() {
synchronized (mLock) {
int currentUser = ActivityManager.getCurrentUser();
-
// Update listeners
ArraySet<ComponentName> enabledListeners = mComponentObserver.getEnabled(currentUser);
@@ -338,7 +337,7 @@
}
// If there is a pending state change, we'd better deal with that first
- consumeAndApplyPendingStateLocked();
+ consumeAndApplyPendingStateLocked(false);
if (mCurrentVrService == null) {
return; // No active services
@@ -606,8 +605,9 @@
if (!goingIntoVrMode) {
// Not going into VR mode, unbind whatever is running
if (mCurrentVrService != null) {
- Slog.i(TAG, "Disconnecting " + mCurrentVrService.getComponent() + " for user " +
- mCurrentVrService.getUserId());
+ Slog.i(TAG, "Leaving VR mode, disconnecting "
+ + mCurrentVrService.getComponent() + " for user "
+ + mCurrentVrService.getUserId());
mCurrentVrService.disconnect();
mCurrentVrService = null;
} else {
@@ -619,8 +619,9 @@
// Unbind any running service that doesn't match the latest component/user
// selection.
if (mCurrentVrService.disconnectIfNotMatching(component, userId)) {
- Slog.i(TAG, "Disconnecting " + mCurrentVrService.getComponent() +
- " for user " + mCurrentVrService.getUserId());
+ Slog.i(TAG, "VR mode component changed to " + component
+ + ", disconnecting " + mCurrentVrService.getComponent()
+ + " for user " + mCurrentVrService.getUserId());
createAndConnectService(component, userId);
sendUpdatedCaller = true;
} else {
@@ -868,16 +869,30 @@
sBinderChecker);
}
+ /**
+ * Apply the pending VR state. If no state is pending, disconnect any currently bound
+ * VR listener service.
+ */
private void consumeAndApplyPendingStateLocked() {
+ consumeAndApplyPendingStateLocked(true);
+ }
+
+ /**
+ * Apply the pending VR state.
+ *
+ * @param disconnectIfNoPendingState if {@code true}, then any currently bound VR listener
+ * service will be disconnected if no state is pending. If this is {@code false} then the
+ * nothing will be changed when there is no pending state.
+ */
+ private void consumeAndApplyPendingStateLocked(boolean disconnectIfNoPendingState) {
if (mPendingState != null) {
updateCurrentVrServiceLocked(mPendingState.enabled,
mPendingState.targetPackageName, mPendingState.userId,
mPendingState.callingPackage);
mPendingState = null;
- } else {
+ } else if (disconnectIfNoPendingState) {
updateCurrentVrServiceLocked(false, null, 0, null);
}
-
}
private void logStateLocked() {
diff --git a/services/core/java/com/android/server/wm/AppWindowContainerController.java b/services/core/java/com/android/server/wm/AppWindowContainerController.java
new file mode 100644
index 0000000..35004c2
--- /dev/null
+++ b/services/core/java/com/android/server/wm/AppWindowContainerController.java
@@ -0,0 +1,526 @@
+/*
+ * Copyright (C) 2016 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.wm;
+
+import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED;
+import static android.view.WindowManager.LayoutParams.FLAG_SHOW_WALLPAPER;
+import static com.android.server.wm.AppTransition.TRANSIT_UNSET;
+import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_ADD_REMOVE;
+import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_APP_TRANSITIONS;
+import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_ORIENTATION;
+import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_SCREENSHOT;
+import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_STARTING_WINDOW;
+import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_TOKEN_MOVEMENT;
+import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_VISIBILITY;
+import static com.android.server.wm.WindowManagerDebugConfig.TAG_WM;
+import static com.android.server.wm.WindowManagerService.H.ADD_STARTING;
+
+import android.graphics.Bitmap;
+import android.os.Trace;
+import com.android.server.AttributeCache;
+
+import android.content.res.CompatibilityInfo;
+import android.content.res.Configuration;
+import android.os.Binder;
+import android.os.Debug;
+import android.os.IBinder;
+import android.os.Message;
+import android.util.Slog;
+import android.view.IApplicationToken;
+
+/**
+ * Controller for the app window token container. This is created by activity manager to link
+ * activity records to the app window token container they use in window manager.
+ *
+ * Test class: {@link AppWindowContainerControllerTests}
+ */
+public class AppWindowContainerController
+ extends WindowContainerController<AppWindowToken, AppWindowContainerListener> {
+
+ private final IApplicationToken mToken;
+
+ private final Runnable mOnWindowsDrawn = () -> {
+ if (mListener == null) {
+ return;
+ }
+ if (DEBUG_VISIBILITY) Slog.v(TAG_WM, "Reporting drawn in "
+ + AppWindowContainerController.this.mToken);
+ mListener.onWindowsDrawn();
+ };
+
+ private final Runnable mOnWindowsVisible = () -> {
+ if (mListener == null) {
+ return;
+ }
+ if (DEBUG_VISIBILITY) Slog.v(TAG_WM, "Reporting visible in "
+ + AppWindowContainerController.this.mToken);
+ mListener.onWindowsVisible();
+ };
+
+ private final Runnable mOnWindowsGone = () -> {
+ if (mListener == null) {
+ return;
+ }
+ if (DEBUG_VISIBILITY) Slog.v(TAG_WM, "Reporting gone in "
+ + AppWindowContainerController.this.mToken);
+ mListener.onWindowsGone();
+ };
+
+ public AppWindowContainerController(IApplicationToken token,
+ AppWindowContainerListener listener, int taskId, int index, int requestedOrientation,
+ boolean fullscreen, boolean showForAllUsers, int configChanges,
+ boolean voiceInteraction, boolean launchTaskBehind, boolean alwaysFocusable,
+ int targetSdkVersion, int rotationAnimationHint, long inputDispatchingTimeoutNanos) {
+ this(token, listener, taskId, index, requestedOrientation, fullscreen, showForAllUsers,
+ configChanges, voiceInteraction, launchTaskBehind, alwaysFocusable,
+ targetSdkVersion, rotationAnimationHint, inputDispatchingTimeoutNanos,
+ WindowManagerService.getInstance());
+ }
+
+ public AppWindowContainerController(IApplicationToken token,
+ AppWindowContainerListener listener, int taskId, int index, int requestedOrientation,
+ boolean fullscreen, boolean showForAllUsers, int configChanges,
+ boolean voiceInteraction, boolean launchTaskBehind, boolean alwaysFocusable,
+ int targetSdkVersion, int rotationAnimationHint, long inputDispatchingTimeoutNanos,
+ WindowManagerService service) {
+ super(listener, service);
+ mToken = token;
+ synchronized(mWindowMap) {
+ AppWindowToken atoken = mRoot.getAppWindowToken(mToken.asBinder());
+ if (atoken != null) {
+ // TODO: Should this throw an exception instead?
+ Slog.w(TAG_WM, "Attempted to add existing app token: " + mToken);
+ return;
+ }
+
+ // TODO: Have the controller for the task passed in when task are changed to use
+ // controller.
+ final Task task = mService.mTaskIdToTask.get(taskId);
+ if (task == null) {
+ throw new IllegalArgumentException("addAppToken: invalid taskId=" + taskId);
+ }
+
+ atoken = new AppWindowToken(mService, token, voiceInteraction, task.getDisplayContent(),
+ inputDispatchingTimeoutNanos, fullscreen, showForAllUsers, targetSdkVersion,
+ requestedOrientation, rotationAnimationHint, configChanges, launchTaskBehind,
+ alwaysFocusable, this);
+ if (DEBUG_TOKEN_MOVEMENT || DEBUG_ADD_REMOVE) Slog.v(TAG_WM, "addAppToken: " + atoken
+ + " task=" + taskId + " at " + index);
+ task.addChild(atoken, index);
+ }
+ }
+
+ public void removeContainer(int displayId) {
+ final long origId = Binder.clearCallingIdentity();
+ try {
+ synchronized(mWindowMap) {
+ final DisplayContent dc = mRoot.getDisplayContent(displayId);
+ if (dc == null) {
+ Slog.w(TAG_WM, "removeAppToken: Attempted to remove binder token: "
+ + mToken + " from non-existing displayId=" + displayId);
+ return;
+ }
+ dc.removeAppToken(mToken.asBinder());
+ super.removeContainer();
+ }
+ } finally {
+ Binder.restoreCallingIdentity(origId);
+ }
+ }
+
+ // TODO: Move to task window controller when that is created and rename to positionChildAt()
+ public void positionAt(int taskId, int index) {
+ synchronized(mService.mWindowMap) {
+ if (mContainer == null) {
+ Slog.w(TAG_WM,
+ "Attempted to position of non-existing app token: " + mToken);
+ return;
+ }
+
+ // TODO: Should get the window container from this owner when the task owner stuff is
+ // hooked-up.
+ final Task task = mService.mTaskIdToTask.get(taskId);
+ if (task == null) {
+ throw new IllegalArgumentException("positionChildAt: invalid taskId=" + taskId);
+ }
+ task.addChild(mContainer, index);
+ }
+
+ }
+
+ public Configuration setOrientation(int requestedOrientation, int displayId,
+ Configuration displayConfig, boolean freezeScreenIfNeeded) {
+ synchronized(mWindowMap) {
+ if (mContainer == null) {
+ Slog.w(TAG_WM,
+ "Attempted to set orientation of non-existing app token: " + mToken);
+ return null;
+ }
+
+ mContainer.setOrientation(requestedOrientation);
+
+ final IBinder binder = freezeScreenIfNeeded ? mToken.asBinder() : null;
+ return mService.updateOrientationFromAppTokens(displayConfig, binder, displayId);
+
+ }
+ }
+
+ public int getOrientation() {
+ synchronized(mWindowMap) {
+ if (mContainer == null) {
+ return SCREEN_ORIENTATION_UNSPECIFIED;
+ }
+
+ return mContainer.getOrientationIgnoreVisibility();
+ }
+ }
+
+ public void setVisibility(boolean visible) {
+ synchronized(mWindowMap) {
+ if (mContainer == null) {
+ Slog.w(TAG_WM, "Attempted to set visibility of non-existing app token: "
+ + mToken);
+ return;
+ }
+
+ final AppWindowToken wtoken = mContainer;
+
+ if (DEBUG_APP_TRANSITIONS || DEBUG_ORIENTATION) Slog.v(TAG_WM, "setAppVisibility("
+ + mToken + ", visible=" + visible + "): " + mService.mAppTransition
+ + " hidden=" + wtoken.hidden + " hiddenRequested="
+ + wtoken.hiddenRequested + " Callers=" + Debug.getCallers(6));
+
+ mService.mOpeningApps.remove(wtoken);
+ mService.mClosingApps.remove(wtoken);
+ wtoken.waitingToShow = false;
+ wtoken.hiddenRequested = !visible;
+
+ if (!visible) {
+ // If the app is dead while it was visible, we kept its dead window on screen.
+ // Now that the app is going invisible, we can remove it. It will be restarted
+ // if made visible again.
+ wtoken.removeDeadWindows();
+ wtoken.setVisibleBeforeClientHidden();
+ } else {
+ if (!mService.mAppTransition.isTransitionSet()
+ && mService.mAppTransition.isReady()) {
+ // Add the app mOpeningApps if transition is unset but ready. This means
+ // we're doing a screen freeze, and the unfreeze will wait for all opening
+ // apps to be ready.
+ mService.mOpeningApps.add(wtoken);
+ }
+ wtoken.startingMoved = false;
+ // If the token is currently hidden (should be the common case), or has been
+ // stopped, then we need to set up to wait for its windows to be ready.
+ if (wtoken.hidden || wtoken.mAppStopped) {
+ wtoken.clearAllDrawn();
+
+ // If the app was already visible, don't reset the waitingToShow state.
+ if (wtoken.hidden) {
+ wtoken.waitingToShow = true;
+ }
+
+ if (wtoken.clientHidden) {
+ // In the case where we are making an app visible
+ // but holding off for a transition, we still need
+ // to tell the client to make its windows visible so
+ // they get drawn. Otherwise, we will wait on
+ // performing the transition until all windows have
+ // been drawn, they never will be, and we are sad.
+ wtoken.clientHidden = false;
+ wtoken.sendAppVisibilityToClients();
+ }
+ }
+ wtoken.requestUpdateWallpaperIfNeeded();
+
+ if (DEBUG_ADD_REMOVE) Slog.v(TAG_WM, "No longer Stopped: " + wtoken);
+ wtoken.mAppStopped = false;
+ }
+
+ // If we are preparing an app transition, then delay changing
+ // the visibility of this token until we execute that transition.
+ if (mService.okToDisplay() && mService.mAppTransition.isTransitionSet()) {
+ // A dummy animation is a placeholder animation which informs others that an
+ // animation is going on (in this case an application transition). If the animation
+ // was transferred from another application/animator, no dummy animator should be
+ // created since an animation is already in progress.
+ if (wtoken.mAppAnimator.usingTransferredAnimation
+ && wtoken.mAppAnimator.animation == null) {
+ Slog.wtf(TAG_WM, "Will NOT set dummy animation on: " + wtoken
+ + ", using null transferred animation!");
+ }
+ if (!wtoken.mAppAnimator.usingTransferredAnimation &&
+ (!wtoken.startingDisplayed || mService.mSkipAppTransitionAnimation)) {
+ if (DEBUG_APP_TRANSITIONS) Slog.v(
+ TAG_WM, "Setting dummy animation on: " + wtoken);
+ wtoken.mAppAnimator.setDummyAnimation();
+ }
+ wtoken.inPendingTransaction = true;
+ if (visible) {
+ mService.mOpeningApps.add(wtoken);
+ wtoken.mEnteringAnimation = true;
+ } else {
+ mService.mClosingApps.add(wtoken);
+ wtoken.mEnteringAnimation = false;
+ }
+ if (mService.mAppTransition.getAppTransition()
+ == AppTransition.TRANSIT_TASK_OPEN_BEHIND) {
+ // We're launchingBehind, add the launching activity to mOpeningApps.
+ final WindowState win =
+ mService.getDefaultDisplayContentLocked().findFocusedWindow();
+ if (win != null) {
+ final AppWindowToken focusedToken = win.mAppToken;
+ if (focusedToken != null) {
+ if (DEBUG_APP_TRANSITIONS) Slog.d(TAG_WM, "TRANSIT_TASK_OPEN_BEHIND, "
+ + " adding " + focusedToken + " to mOpeningApps");
+ // Force animation to be loaded.
+ focusedToken.hidden = true;
+ mService.mOpeningApps.add(focusedToken);
+ }
+ }
+ }
+ return;
+ }
+
+ wtoken.setVisibility(null, visible, TRANSIT_UNSET, true, wtoken.mVoiceInteraction);
+ wtoken.updateReportedVisibilityLocked();
+ }
+ }
+
+ /**
+ * Notifies that we launched an app that might be visible or not visible depending on what kind
+ * of Keyguard flags it's going to set on its windows.
+ */
+ public void notifyUnknownVisibilityLaunched() {
+ synchronized(mWindowMap) {
+ if (mContainer != null) {
+ mService.mUnknownAppVisibilityController.notifyLaunched(mContainer);
+ }
+ }
+ }
+
+ public boolean addStartingWindow(String pkg, int theme, CompatibilityInfo compatInfo,
+ CharSequence nonLocalizedLabel, int labelRes, int icon, int logo, int windowFlags,
+ IBinder transferFrom, boolean createIfNeeded) {
+ synchronized(mWindowMap) {
+ if (DEBUG_STARTING_WINDOW) Slog.v(TAG_WM, "setAppStartingWindow: token=" + mToken
+ + " pkg=" + pkg + " transferFrom=" + transferFrom);
+
+ if (mContainer == null) {
+ Slog.w(TAG_WM, "Attempted to set icon of non-existing app token: " + mToken);
+ return false;
+ }
+
+ // If the display is frozen, we won't do anything until the actual window is
+ // displayed so there is no reason to put in the starting window.
+ if (!mService.okToDisplay()) {
+ return false;
+ }
+
+ if (mContainer.startingData != null) {
+ return false;
+ }
+
+ // If this is a translucent window, then don't show a starting window -- the current
+ // effect (a full-screen opaque starting window that fades away to the real contents
+ // when it is ready) does not work for this.
+ if (DEBUG_STARTING_WINDOW) Slog.v(TAG_WM, "Checking theme of starting window: 0x"
+ + Integer.toHexString(theme));
+ if (theme != 0) {
+ AttributeCache.Entry ent = AttributeCache.instance().get(pkg, theme,
+ com.android.internal.R.styleable.Window, mService.mCurrentUserId);
+ if (ent == null) {
+ // Whoops! App doesn't exist. Um. Okay. We'll just pretend like we didn't
+ // see that.
+ return false;
+ }
+ final boolean windowIsTranslucent = ent.array.getBoolean(
+ com.android.internal.R.styleable.Window_windowIsTranslucent, false);
+ final boolean windowIsFloating = ent.array.getBoolean(
+ com.android.internal.R.styleable.Window_windowIsFloating, false);
+ final boolean windowShowWallpaper = ent.array.getBoolean(
+ com.android.internal.R.styleable.Window_windowShowWallpaper, false);
+ final boolean windowDisableStarting = ent.array.getBoolean(
+ com.android.internal.R.styleable.Window_windowDisablePreview, false);
+ if (DEBUG_STARTING_WINDOW) Slog.v(TAG_WM, "Translucent=" + windowIsTranslucent
+ + " Floating=" + windowIsFloating
+ + " ShowWallpaper=" + windowShowWallpaper);
+ if (windowIsTranslucent) {
+ return false;
+ }
+ if (windowIsFloating || windowDisableStarting) {
+ return false;
+ }
+ if (windowShowWallpaper) {
+ if (mContainer.getDisplayContent().mWallpaperController.getWallpaperTarget()
+ == null) {
+ // If this theme is requesting a wallpaper, and the wallpaper
+ // is not currently visible, then this effectively serves as
+ // an opaque window and our starting window transition animation
+ // can still work. We just need to make sure the starting window
+ // is also showing the wallpaper.
+ windowFlags |= FLAG_SHOW_WALLPAPER;
+ } else {
+ return false;
+ }
+ }
+ }
+
+ if (mContainer.transferStartingWindow(transferFrom)) {
+ return true;
+ }
+
+ // There is no existing starting window, and the caller doesn't
+ // want us to create one, so that's it!
+ if (!createIfNeeded) {
+ return false;
+ }
+
+ if (DEBUG_STARTING_WINDOW) Slog.v(TAG_WM, "Creating StartingData");
+ mContainer.startingData = new StartingData(pkg, theme, compatInfo, nonLocalizedLabel,
+ labelRes, icon, logo, windowFlags);
+ final Message m = mService.mH.obtainMessage(ADD_STARTING, mContainer);
+ // Note: we really want to do sendMessageAtFrontOfQueue() because we
+ // want to process the message ASAP, before any other queued
+ // messages.
+ if (DEBUG_STARTING_WINDOW) Slog.v(TAG_WM, "Enqueueing ADD_STARTING");
+ mService.mH.sendMessageAtFrontOfQueue(m);
+ }
+ return true;
+ }
+
+ public void removeStartingWindow() {
+ synchronized (mWindowMap) {
+ mService.scheduleRemoveStartingWindowLocked(mContainer);
+ }
+ }
+
+ public void pauseKeyDispatching() {
+ synchronized (mWindowMap) {
+ if (mContainer != null) {
+ mService.mInputMonitor.pauseDispatchingLw(mContainer);
+ }
+ }
+ }
+
+ public void resumeKeyDispatching() {
+ synchronized (mWindowMap) {
+ if (mContainer != null) {
+ mService.mInputMonitor.resumeDispatchingLw(mContainer);
+ }
+ }
+ }
+
+ public void notifyAppResumed(boolean wasStopped, boolean allowSavedSurface) {
+ synchronized(mWindowMap) {
+ if (mContainer == null) {
+ Slog.w(TAG_WM, "Attempted to notify resumed of non-existing app token: " + mToken);
+ return;
+ }
+ mContainer.notifyAppResumed(wasStopped, allowSavedSurface);
+ }
+ }
+
+ public void notifyAppStopped() {
+ synchronized(mWindowMap) {
+ if (mContainer == null) {
+ Slog.w(TAG_WM, "Attempted to notify stopped of non-existing app token: "
+ + mToken);
+ return;
+ }
+ mContainer.notifyAppStopped();
+ }
+ }
+
+ public void startFreezingScreen(int configChanges) {
+ synchronized(mWindowMap) {
+ if (configChanges == 0 && mService.okToDisplay()) {
+ if (DEBUG_ORIENTATION) Slog.v(TAG_WM, "Skipping set freeze of " + mToken);
+ return;
+ }
+
+ if (mContainer == null) {
+ Slog.w(TAG_WM,
+ "Attempted to freeze screen with non-existing app token: " + mContainer);
+ return;
+ }
+ final long origId = Binder.clearCallingIdentity();
+ mContainer.startFreezingScreen();
+ Binder.restoreCallingIdentity(origId);
+ }
+ }
+
+ public void stopFreezingScreen(boolean force) {
+ synchronized(mWindowMap) {
+ if (mContainer == null) {
+ return;
+ }
+ final long origId = Binder.clearCallingIdentity();
+ if (DEBUG_ORIENTATION) Slog.v(TAG_WM, "Clear freezing of " + mToken + ": hidden="
+ + mContainer.hidden + " freezing=" + mContainer.mAppAnimator.freezingScreen);
+ mContainer.stopFreezingScreen(true, force);
+ Binder.restoreCallingIdentity(origId);
+ }
+ }
+
+ /**
+ * Takes a snapshot of the screen. In landscape mode this grabs the whole screen.
+ * In portrait mode, it grabs the full screenshot.
+ *
+ * @param displayId the Display to take a screenshot of.
+ * @param width the width of the target bitmap
+ * @param height the height of the target bitmap
+ * @param frameScale the scale to apply to the frame, only used when width = -1 and height = -1
+ */
+ public Bitmap screenshotApplications(int displayId, int width, int height, float frameScale) {
+ try {
+ Trace.traceBegin(Trace.TRACE_TAG_WINDOW_MANAGER, "screenshotApplications");
+ final DisplayContent dc;
+ synchronized(mWindowMap) {
+ dc = mRoot.getDisplayContentOrCreate(displayId);
+ if (dc == null) {
+ if (DEBUG_SCREENSHOT) Slog.i(TAG_WM, "Screenshot of " + mToken
+ + ": returning null. No Display for displayId=" + displayId);
+ return null;
+ }
+ }
+ return dc.screenshotApplications(mToken.asBinder(), width, height,
+ false /* includeFullDisplay */, frameScale, Bitmap.Config.RGB_565,
+ false /* wallpaperOnly */);
+ } finally {
+ Trace.traceEnd(Trace.TRACE_TAG_WINDOW_MANAGER);
+ }
+ }
+
+
+ void reportWindowsDrawn() {
+ mService.mH.post(mOnWindowsDrawn);
+ }
+
+ void reportWindowsVisible() {
+ mService.mH.post(mOnWindowsVisible);
+ }
+
+ void reportWindowsGone() {
+ mService.mH.post(mOnWindowsGone);
+ }
+
+ /** Calls directly into activity manager so window manager lock shouldn't held. */
+ boolean keyDispatchingTimedOut(String reason) {
+ return mListener != null && mListener.keyDispatchingTimedOut(reason);
+ }
+}
diff --git a/services/core/java/com/android/server/wm/AppWindowContainerListener.java b/services/core/java/com/android/server/wm/AppWindowContainerListener.java
new file mode 100644
index 0000000..12d4b2f
--- /dev/null
+++ b/services/core/java/com/android/server/wm/AppWindowContainerListener.java
@@ -0,0 +1,32 @@
+/*
+ * Copyright (C) 2016 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.wm;
+
+/** Interface used by the creator of the controller to listen to changes with the container. */
+public interface AppWindowContainerListener extends WindowContainerListener {
+ /** Called when the windows associated app window container are drawn. */
+ void onWindowsDrawn();
+ /** Called when the windows associated app window container are visible. */
+ void onWindowsVisible();
+ /** Called when the windows associated app window container are no longer visible. */
+ void onWindowsGone();
+ /**
+ * Called when the key dispatching to a window associated with the app window container
+ * timed-out.
+ */
+ boolean keyDispatchingTimedOut(String reason);
+}
diff --git a/services/core/java/com/android/server/wm/AppWindowToken.java b/services/core/java/com/android/server/wm/AppWindowToken.java
index 6147885..0a48758 100644
--- a/services/core/java/com/android/server/wm/AppWindowToken.java
+++ b/services/core/java/com/android/server/wm/AppWindowToken.java
@@ -47,7 +47,6 @@
import static com.android.server.wm.WindowManagerService.UPDATE_FOCUS_WILL_PLACE_SURFACES;
import static com.android.server.wm.WindowManagerService.logWithStack;
-import android.content.pm.ActivityInfo;
import android.os.Debug;
import com.android.internal.util.ToBooleanFunction;
import com.android.server.input.InputApplicationHandle;
@@ -173,8 +172,10 @@
AppWindowToken(WindowManagerService service, IApplicationToken token, boolean voiceInteraction,
DisplayContent dc, long inputDispatchingTimeoutNanos, boolean fullscreen,
boolean showForAllUsers, int targetSdk, int orientation, int rotationAnimationHint,
- int configChanges, boolean launchTaskBehind, boolean alwaysFocusable) {
+ int configChanges, boolean launchTaskBehind, boolean alwaysFocusable,
+ AppWindowContainerController controller) {
this(service, token, voiceInteraction, dc);
+ setController(controller);
mInputDispatchingTimeoutNanos = inputDispatchingTimeoutNanos;
mFillsParent = fullscreen;
mShowForAllUsers = showForAllUsers;
@@ -251,9 +252,12 @@
}
if (DEBUG_VISIBILITY) Slog.v(TAG, "VIS " + this + ": interesting="
+ numInteresting + " visible=" + numVisible);
+ final AppWindowContainerController controller = getController();
if (nowDrawn != reportedDrawn) {
if (nowDrawn) {
- mService.mH.obtainMessage(H.REPORT_APPLICATION_TOKEN_DRAWN, this).sendToTarget();
+ if (controller != null) {
+ controller.reportWindowsDrawn();
+ }
}
reportedDrawn = nowDrawn;
}
@@ -261,8 +265,13 @@
if (DEBUG_VISIBILITY) Slog.v(TAG,
"Visibility changed in " + this + ": vis=" + nowVisible);
reportedVisible = nowVisible;
- mService.mH.obtainMessage(H.REPORT_APPLICATION_TOKEN_WINDOWS,
- nowVisible ? 1 : 0, nowGone ? 1 : 0, this).sendToTarget();
+ if (controller != null) {
+ if (nowVisible) {
+ controller.reportWindowsVisible();
+ } else {
+ controller.reportWindowsGone();
+ }
+ }
}
}
@@ -399,6 +408,11 @@
return StackId.canReceiveKeys(mTask.mStack.mStackId) || mAlwaysFocusable;
}
+ AppWindowContainerController getController() {
+ final WindowContainerController controller = super.getController();
+ return controller != null ? (AppWindowContainerController) controller : null;
+ }
+
@Override
boolean isVisible() {
// If the app token isn't hidden then it is considered visible and there is no need to check
diff --git a/services/core/java/com/android/server/wm/DimLayerController.java b/services/core/java/com/android/server/wm/DimLayerController.java
index da2c6a7..04ae72f 100644
--- a/services/core/java/com/android/server/wm/DimLayerController.java
+++ b/services/core/java/com/android/server/wm/DimLayerController.java
@@ -11,6 +11,7 @@
import android.util.Slog;
import android.util.TypedValue;
+import com.android.internal.annotations.VisibleForTesting;
import com.android.server.wm.DimLayer.DimLayerUser;
import java.io.PrintWriter;
@@ -310,6 +311,11 @@
}
}
+ @VisibleForTesting
+ boolean hasDimLayerUser(DimLayer.DimLayerUser dimLayerUser) {
+ return mState.containsKey(dimLayerUser);
+ }
+
void applyDimBehind(DimLayer.DimLayerUser dimLayerUser, WindowStateAnimator animator) {
applyDim(dimLayerUser, animator, false /* aboveApp */);
}
diff --git a/services/core/java/com/android/server/wm/DisplayContent.java b/services/core/java/com/android/server/wm/DisplayContent.java
index ff841b1..d86c4da 100644
--- a/services/core/java/com/android/server/wm/DisplayContent.java
+++ b/services/core/java/com/android/server/wm/DisplayContent.java
@@ -2498,19 +2498,8 @@
}
private void addChild(TaskStack stack, boolean toTop) {
- int addIndex = toTop ? mChildren.size() : 0;
-
- if (toTop
- && mService.isStackVisibleLocked(PINNED_STACK_ID)
- && stack.mStackId != PINNED_STACK_ID) {
- // The pinned stack is always the top most stack (always-on-top) when it is visible.
- // So, stack is moved just below the pinned stack.
- addIndex--;
- TaskStack topStack = mChildren.get(addIndex);
- if (topStack.mStackId != PINNED_STACK_ID) {
- throw new IllegalStateException("Pinned stack isn't top stack??? " + mChildren);
- }
- }
+ final int addIndex = findPositionForStack(toTop ? mChildren.size() : 0, stack,
+ true /* adding */);
addChild(stack, addIndex);
setLayoutNeeded();
}
@@ -2528,7 +2517,45 @@
return;
}
- super.positionChildAt(position, child, includingParents);
+ final int targetPosition = findPositionForStack(position, child, false /* adding */);
+ super.positionChildAt(targetPosition, child, includingParents);
+
+ setLayoutNeeded();
+ }
+
+ /**
+ * When stack is added or repositioned, find a proper position for it.
+ * This will make sure that pinned stack always stays on top.
+ * @param requestedPosition Position requested by caller.
+ * @param stack Stack to be added or positioned.
+ * @param adding Flag indicates whether we're adding a new stack or positioning an existing.
+ * @return The proper position for the stack.
+ */
+ private int findPositionForStack(int requestedPosition, TaskStack stack, boolean adding) {
+ final int topChildPosition = mChildren.size() - 1;
+ boolean toTop = requestedPosition == POSITION_TOP;
+ toTop |= adding ? requestedPosition >= topChildPosition + 1
+ : requestedPosition >= topChildPosition;
+ int targetPosition = requestedPosition;
+
+ if (toTop
+ && mService.isStackVisibleLocked(PINNED_STACK_ID)
+ && stack.mStackId != PINNED_STACK_ID) {
+ // The pinned stack is always the top most stack (always-on-top) when it is visible.
+ TaskStack topStack = mChildren.get(topChildPosition);
+ if (topStack.mStackId != PINNED_STACK_ID) {
+ throw new IllegalStateException("Pinned stack isn't top stack??? " + mChildren);
+ }
+
+ // So, stack is moved just below the pinned stack.
+ // When we're adding a new stack the target is the current pinned stack position.
+ // When we're positioning an existing stack the target is the position below pinned
+ // stack, because WindowContainer#positionAt() first removes element and then adds it
+ // to specified place.
+ targetPosition = adding ? topChildPosition : topChildPosition - 1;
+ }
+
+ return targetPosition;
}
@Override
diff --git a/services/core/java/com/android/server/wm/InputMonitor.java b/services/core/java/com/android/server/wm/InputMonitor.java
index 3fbe36f..f754775 100644
--- a/services/core/java/com/android/server/wm/InputMonitor.java
+++ b/services/core/java/com/android/server/wm/InputMonitor.java
@@ -251,16 +251,14 @@
}
if (appWindowToken != null && appWindowToken.appToken != null) {
- try {
- // Notify the activity manager about the timeout and let it decide whether
- // to abort dispatching or keep waiting.
- boolean abort = appWindowToken.appToken.keyDispatchingTimedOut(reason);
- if (! abort) {
- // The activity manager declined to abort dispatching.
- // Wait a bit longer and timeout again later.
- return appWindowToken.mInputDispatchingTimeoutNanos;
- }
- } catch (RemoteException ex) {
+ // Notify the activity manager about the timeout and let it decide whether
+ // to abort dispatching or keep waiting.
+ final AppWindowContainerController controller = appWindowToken.getController();
+ final boolean abort = controller != null && controller.keyDispatchingTimedOut(reason);
+ if (!abort) {
+ // The activity manager declined to abort dispatching.
+ // Wait a bit longer and timeout again later.
+ return appWindowToken.mInputDispatchingTimeoutNanos;
}
} else if (windowState != null) {
try {
diff --git a/services/core/java/com/android/server/wm/RootWindowContainer.java b/services/core/java/com/android/server/wm/RootWindowContainer.java
index 349740b..dc06d12 100644
--- a/services/core/java/com/android/server/wm/RootWindowContainer.java
+++ b/services/core/java/com/android/server/wm/RootWindowContainer.java
@@ -166,6 +166,19 @@
}
/**
+ * Get an array with display ids ordered by focus priority - last items should be given
+ * focus first. Sparse array just maps position to displayId.
+ */
+ void getDisplaysInFocusOrder(SparseIntArray displaysInFocusOrder) {
+ displaysInFocusOrder.clear();
+
+ final int size = mChildren.size();
+ for (int i = 0; i < size; ++i) {
+ displaysInFocusOrder.put(i, mChildren.get(i).getDisplayId());
+ }
+ }
+
+ /**
* Retrieve the DisplayContent for the specified displayId. Will create a new DisplayContent if
* there is a Display for the displayId.
*
diff --git a/services/core/java/com/android/server/wm/Task.java b/services/core/java/com/android/server/wm/Task.java
index 6005a99..a468598 100644
--- a/services/core/java/com/android/server/wm/Task.java
+++ b/services/core/java/com/android/server/wm/Task.java
@@ -144,14 +144,22 @@
mDeferRemoval = true;
return;
}
+ removeImmediately();
+ }
+
+ @Override
+ void removeImmediately() {
if (DEBUG_STACK) Slog.i(TAG, "removeTask: removing taskId=" + mTaskId);
EventLog.writeEvent(EventLogTags.WM_TASK_REMOVED, mTaskId, "removeTask");
mDeferRemoval = false;
+
+ // Make sure to remove dim layer user first before removing task its from parent.
DisplayContent content = getDisplayContent();
if (content != null) {
content.mDimLayerController.removeDimLayerUser(this);
}
- removeImmediately();
+
+ super.removeImmediately();
mService.mTaskIdToTask.delete(mTaskId);
}
@@ -170,7 +178,12 @@
/** @see com.android.server.am.ActivityManagerService#positionTaskInStack(int, int, int). */
void positionTaskInStack(TaskStack stack, int position, Rect bounds,
Configuration overrideConfig) {
- if (mStack != null && stack != mStack) {
+ if (mStack == null) {
+ // There is an assumption that task already has a stack at this point, so lets make
+ // sure we comply with it.
+ throw new IllegalStateException("Trying to position task that has no parent.");
+ }
+ if (stack != mStack) {
// Task is already attached to a different stack. First we need to remove it from there
// and add to top of the target stack. We will move it proper position afterwards.
if (DEBUG_STACK) Slog.i(TAG, "positionTaskInStack: removing taskId=" + mTaskId
diff --git a/services/core/java/com/android/server/wm/WindowContainer.java b/services/core/java/com/android/server/wm/WindowContainer.java
index 984cf55..0e6ecde 100644
--- a/services/core/java/com/android/server/wm/WindowContainer.java
+++ b/services/core/java/com/android/server/wm/WindowContainer.java
@@ -75,6 +75,9 @@
private final Pools.SynchronizedPool<ForAllWindowsConsumerWrapper> mConsumerWrapperPool =
new Pools.SynchronizedPool<>(3);
+ // The owner/creator for this container. No controller if null.
+ private WindowContainerController mController;
+
final protected WindowContainer getParent() {
return mParent;
}
@@ -188,6 +191,10 @@
if (mParent != null) {
mParent.removeChild(this);
}
+
+ if (mController != null) {
+ setController(null);
+ }
}
/**
@@ -434,7 +441,7 @@
// TODO: Will this be more correct if it checks the visibility of its parents?
// It depends...For example, Tasks and Stacks are only visible if there children are visible
// but, WindowState are not visible if there parent are not visible. Maybe have the
- // container specify which direction to treverse for for visibility?
+ // container specify which direction to traverse for visibility?
for (int i = mChildren.size() - 1; i >= 0; --i) {
final WindowContainer wc = mChildren.get(i);
if (wc.isVisible()) {
@@ -662,6 +669,23 @@
} while (current != null);
}
+ WindowContainerController getController() {
+ return mController;
+ }
+
+ void setController(WindowContainerController controller) {
+ if (mController != null && controller != null) {
+ throw new IllegalArgumentException("Can't set controller=" + mController
+ + " for container=" + this + " Already set to=" + mController);
+ }
+ if (controller != null) {
+ controller.setContainer(this);
+ } else if (mController != null) {
+ mController.setContainer(null);
+ }
+ mController = controller;
+ }
+
/**
* Dumps the names of this container children in the input print writer indenting each
* level with the input prefix.
diff --git a/services/core/java/com/android/server/wm/WindowContainerController.java b/services/core/java/com/android/server/wm/WindowContainerController.java
new file mode 100644
index 0000000..84ffc35
--- /dev/null
+++ b/services/core/java/com/android/server/wm/WindowContainerController.java
@@ -0,0 +1,70 @@
+/*
+ * Copyright (C) 2016 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.wm;
+
+import android.os.IBinder;
+
+import java.util.HashMap;
+
+/**
+ * Class that allows the owner/creator of a {@link WindowContainer} to communicate directly with the
+ * container and make changes.
+ * Note that public calls (mostly in sub-classes) into this class are assumed to be originating from
+ * outside the window manager so the window manager lock is held and appropriate permissions are
+ * checked before calls are allowed to proceed.
+ *
+ * Test class: {@link WindowContainerControllerTests}
+ */
+class WindowContainerController<E extends WindowContainer, I extends WindowContainerListener> {
+
+ final WindowManagerService mService;
+ final RootWindowContainer mRoot;
+ final HashMap<IBinder, WindowState> mWindowMap;
+
+ // The window container this controller owns.
+ E mContainer;
+ // Interface for communicating changes back to the owner.
+ final I mListener;
+
+ WindowContainerController(I listener, WindowManagerService service) {
+ mListener = listener;
+ mService = service;
+ mRoot = mService != null ? mService.mRoot : null;
+ mWindowMap = mService != null ? mService.mWindowMap : null;
+ }
+
+ void setContainer(E container) {
+ if (mContainer != null && container != null) {
+ throw new IllegalArgumentException("Can't set container=" + container
+ + " for controller=" + this + " Already set to=" + mContainer);
+ }
+ mContainer = container;
+ }
+
+ void removeContainer() {
+ // TODO: See if most uses cases should support removeIfPossible here.
+ //mContainer.removeIfPossible();
+ if (mContainer != null) {
+ mContainer.setController(null);
+ mContainer = null;
+ }
+ }
+
+ boolean checkCallingPermission(String permission, String func) {
+ return mService.checkCallingPermission(permission, func);
+ }
+}
diff --git a/wifi/java/android/net/wifi/aware/WifiAwareCharacteristics.aidl b/services/core/java/com/android/server/wm/WindowContainerListener.java
similarity index 69%
copy from wifi/java/android/net/wifi/aware/WifiAwareCharacteristics.aidl
copy to services/core/java/com/android/server/wm/WindowContainerListener.java
index a35e71d..ab9d71a 100644
--- a/wifi/java/android/net/wifi/aware/WifiAwareCharacteristics.aidl
+++ b/services/core/java/com/android/server/wm/WindowContainerListener.java
@@ -11,9 +11,15 @@
* 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.
+ * limitations under the License
*/
-package android.net.wifi.aware;
+package com.android.server.wm;
-parcelable WifiAwareCharacteristics;
+/**
+ * Interface used by the owner/creator of the container to listen to changes with the container.
+ * @see WindowContainerController
+ */
+public interface WindowContainerListener {
+
+}
diff --git a/services/core/java/com/android/server/wm/WindowManagerService.java b/services/core/java/com/android/server/wm/WindowManagerService.java
index 2ade924..38cb543 100644
--- a/services/core/java/com/android/server/wm/WindowManagerService.java
+++ b/services/core/java/com/android/server/wm/WindowManagerService.java
@@ -90,7 +90,6 @@
import android.view.Gravity;
import android.view.PointerIcon;
import android.view.IAppTransitionAnimationSpecsFuture;
-import android.view.IApplicationToken;
import android.view.IDockedStackListener;
import android.view.IInputFilter;
import android.view.IOnKeyguardExitResult;
@@ -133,7 +132,6 @@
import com.android.internal.view.IInputMethodClient;
import com.android.internal.view.IInputMethodManager;
import com.android.internal.view.WindowManagerPolicyThread;
-import com.android.server.AttributeCache;
import com.android.server.DisplayThread;
import com.android.server.EventLogTags;
import com.android.server.FgThread;
@@ -228,7 +226,6 @@
import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_STACK;
import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_STARTING_WINDOW;
import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_TASK_POSITIONING;
-import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_TOKEN_MOVEMENT;
import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_VISIBILITY;
import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_WALLPAPER_LIGHT;
import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_WINDOW_MOVEMENT;
@@ -240,7 +237,6 @@
import static com.android.server.wm.WindowManagerDebugConfig.TAG_KEEP_SCREEN_ON;
import static com.android.server.wm.WindowManagerDebugConfig.TAG_WITH_CLASS_NAME;
import static com.android.server.wm.WindowManagerDebugConfig.TAG_WM;
-import static java.lang.Integer.MAX_VALUE;
/** {@hide} */
public class WindowManagerService extends IWindowManager.Stub
@@ -915,16 +911,19 @@
void onAppFreezeTimeout();
}
- public static WindowManagerService main(final Context context,
- final InputManagerService im,
- final boolean haveInputMethods, final boolean showBootMsgs,
- final boolean onlyCore, WindowManagerPolicy policy) {
- final WindowManagerService[] holder = new WindowManagerService[1];
- DisplayThread.getHandler().runWithScissors(() -> {
- holder[0] = new WindowManagerService(context, im, haveInputMethods, showBootMsgs,
- onlyCore, policy);
- }, 0);
- return holder[0];
+ private static WindowManagerService sInstance;
+
+ static WindowManagerService getInstance() {
+ return sInstance;
+ }
+
+ public static WindowManagerService main(final Context context, final InputManagerService im,
+ final boolean haveInputMethods, final boolean showBootMsgs, final boolean onlyCore,
+ WindowManagerPolicy policy) {
+ DisplayThread.getHandler().runWithScissors(() ->
+ sInstance = new WindowManagerService(context, im, haveInputMethods, showBootMsgs,
+ onlyCore, policy), 0);
+ return sInstance;
}
private void initPolicy() {
@@ -2369,7 +2368,7 @@
return atoken.mAppAnimator.animation != null;
}
- private boolean checkCallingPermission(String permission, String func) {
+ boolean checkCallingPermission(String permission, String func) {
// Quick check: if the calling permission is me, it's all okay.
if (Binder.getCallingPid() == Process.myPid()) {
return true;
@@ -2442,73 +2441,6 @@
}
}
- @Override
- public void addAppToken(int addPos, IApplicationToken token, int taskId,
- int requestedOrientation, boolean fullscreen, boolean showForAllUsers,
- int configChanges, boolean voiceInteraction, boolean launchTaskBehind,
- boolean alwaysFocusable, int targetSdkVersion, int rotationAnimationHint) {
- if (!checkCallingPermission(MANAGE_APP_TOKENS, "addAppToken()")) {
- throw new SecurityException("Requires MANAGE_APP_TOKENS permission");
- }
-
- // Get the dispatching timeout here while we are not holding any locks so that it
- // can be cached by the AppWindowToken. The timeout value is used later by the
- // input dispatcher in code that does hold locks. If we did not cache the value
- // here we would run the chance of introducing a deadlock between the window manager
- // (which holds locks while updating the input dispatcher state) and the activity manager
- // (which holds locks while querying the application token).
- long inputDispatchingTimeoutNanos;
- try {
- inputDispatchingTimeoutNanos = token.getKeyDispatchingTimeout() * 1000000L;
- } catch (RemoteException ex) {
- Slog.w(TAG_WM, "Could not get dispatching timeout.", ex);
- inputDispatchingTimeoutNanos = DEFAULT_INPUT_DISPATCHING_TIMEOUT_NANOS;
- }
-
- synchronized(mWindowMap) {
- AppWindowToken atoken = mRoot.getAppWindowToken(token.asBinder());
- if (atoken != null) {
- Slog.w(TAG_WM, "Attempted to add existing app token: " + token);
- return;
- }
-
- Task task = mTaskIdToTask.get(taskId);
- if (task == null) {
- throw new IllegalArgumentException("addAppToken: invalid taskId=" + taskId);
- }
-
- atoken = new AppWindowToken(this, token, voiceInteraction, task.getDisplayContent(),
- inputDispatchingTimeoutNanos, fullscreen, showForAllUsers, targetSdkVersion,
- requestedOrientation, rotationAnimationHint, configChanges, launchTaskBehind,
- alwaysFocusable);
- if (DEBUG_TOKEN_MOVEMENT || DEBUG_ADD_REMOVE) Slog.v(TAG_WM, "addAppToken: " + atoken
- + " task=" + taskId + " at " + addPos);
-
- task.addChild(atoken, addPos);
- }
- }
-
- @Override
- public void addAppToTask(IBinder token, int taskId) {
- if (!checkCallingPermission(MANAGE_APP_TOKENS, "setAppTask()")) {
- throw new SecurityException("Requires MANAGE_APP_TOKENS permission");
- }
-
- synchronized(mWindowMap) {
- final AppWindowToken atoken = mRoot.getAppWindowToken(token);
- if (atoken == null) {
- Slog.w(TAG_WM, "Attempted to set task id of non-existing app token: " + token);
- return;
- }
-
- Task task = mTaskIdToTask.get(taskId);
- if (task == null) {
- throw new IllegalArgumentException("setAppTask: invalid taskId=" + taskId);
- }
- task.addChild(atoken, MAX_VALUE /* at top */);
- }
- }
-
public void addTask(int taskId, int stackId, int userId, Rect bounds,
Configuration overrideConfig, int resizeMode, boolean homeTask, boolean isOnTopLauncher,
boolean toTop, boolean showForAllUsers) {
@@ -2675,35 +2607,6 @@
}
}
- @Override
- public void setAppOrientation(IApplicationToken token, int requestedOrientation) {
- if (!checkCallingPermission(MANAGE_APP_TOKENS, "setAppOrientation()")) {
- throw new SecurityException("Requires MANAGE_APP_TOKENS permission");
- }
-
- synchronized(mWindowMap) {
- final AppWindowToken atoken = mRoot.getAppWindowToken(token.asBinder());
- if (atoken == null) {
- Slog.w(TAG_WM, "Attempted to set orientation of non-existing app token: " + token);
- return;
- }
-
- atoken.setOrientation(requestedOrientation);
- }
- }
-
- @Override
- public int getAppOrientation(IApplicationToken token) {
- synchronized(mWindowMap) {
- final AppWindowToken wtoken = mRoot.getAppWindowToken(token.asBinder());
- if (wtoken == null) {
- return SCREEN_ORIENTATION_UNSPECIFIED;
- }
-
- return wtoken.getOrientationIgnoreVisibility();
- }
- }
-
void setFocusTaskRegionLocked() {
final Task focusedTask = mFocusedApp != null ? mFocusedApp.mTask : null;
if (focusedTask != null) {
@@ -2912,113 +2815,6 @@
}
}
- @Override
- public boolean setAppStartingWindow(IBinder token, String pkg,
- int theme, CompatibilityInfo compatInfo,
- CharSequence nonLocalizedLabel, int labelRes, int icon, int logo,
- int windowFlags, IBinder transferFrom, boolean createIfNeeded) {
- if (!checkCallingPermission(MANAGE_APP_TOKENS, "setAppStartingWindow()")) {
- throw new SecurityException("Requires MANAGE_APP_TOKENS permission");
- }
-
- synchronized(mWindowMap) {
- if (DEBUG_STARTING_WINDOW) Slog.v(
- TAG_WM, "setAppStartingWindow: token=" + token + " pkg=" + pkg
- + " transferFrom=" + transferFrom);
-
- final AppWindowToken wtoken = mRoot.getAppWindowToken(token);
- if (wtoken == null) {
- Slog.w(TAG_WM, "Attempted to set icon of non-existing app token: " + token);
- return false;
- }
-
- // If the display is frozen, we won't do anything until the
- // actual window is displayed so there is no reason to put in
- // the starting window.
- if (!okToDisplay()) {
- return false;
- }
-
- if (wtoken.startingData != null) {
- return false;
- }
-
- // If this is a translucent window, then don't
- // show a starting window -- the current effect (a full-screen
- // opaque starting window that fades away to the real contents
- // when it is ready) does not work for this.
- if (DEBUG_STARTING_WINDOW) Slog.v(TAG_WM, "Checking theme of starting window: 0x"
- + Integer.toHexString(theme));
- if (theme != 0) {
- AttributeCache.Entry ent = AttributeCache.instance().get(pkg, theme,
- com.android.internal.R.styleable.Window, mCurrentUserId);
- if (ent == null) {
- // Whoops! App doesn't exist. Um. Okay. We'll just
- // pretend like we didn't see that.
- return false;
- }
- final boolean windowIsTranslucent = ent.array.getBoolean(
- com.android.internal.R.styleable.Window_windowIsTranslucent, false);
- final boolean windowIsFloating = ent.array.getBoolean(
- com.android.internal.R.styleable.Window_windowIsFloating, false);
- final boolean windowShowWallpaper = ent.array.getBoolean(
- com.android.internal.R.styleable.Window_windowShowWallpaper, false);
- final boolean windowDisableStarting = ent.array.getBoolean(
- com.android.internal.R.styleable.Window_windowDisablePreview, false);
- if (DEBUG_STARTING_WINDOW) Slog.v(TAG_WM, "Translucent=" + windowIsTranslucent
- + " Floating=" + windowIsFloating
- + " ShowWallpaper=" + windowShowWallpaper);
- if (windowIsTranslucent) {
- return false;
- }
- if (windowIsFloating || windowDisableStarting) {
- return false;
- }
- if (windowShowWallpaper) {
- if (wtoken.getDisplayContent().mWallpaperController.getWallpaperTarget()
- == null) {
- // If this theme is requesting a wallpaper, and the wallpaper
- // is not currently visible, then this effectively serves as
- // an opaque window and our starting window transition animation
- // can still work. We just need to make sure the starting window
- // is also showing the wallpaper.
- windowFlags |= FLAG_SHOW_WALLPAPER;
- } else {
- return false;
- }
- }
- }
-
- if (wtoken.transferStartingWindow(transferFrom)) {
- return true;
- }
-
- // There is no existing starting window, and the caller doesn't
- // want us to create one, so that's it!
- if (!createIfNeeded) {
- return false;
- }
-
- if (DEBUG_STARTING_WINDOW) Slog.v(TAG_WM, "Creating StartingData");
- wtoken.startingData = new StartingData(pkg, theme, compatInfo, nonLocalizedLabel,
- labelRes, icon, logo, windowFlags);
- Message m = mH.obtainMessage(H.ADD_STARTING, wtoken);
- // Note: we really want to do sendMessageAtFrontOfQueue() because we
- // want to process the message ASAP, before any other queued
- // messages.
- if (DEBUG_STARTING_WINDOW) Slog.v(TAG_WM, "Enqueueing ADD_STARTING");
- mH.sendMessageAtFrontOfQueue(m);
- }
- return true;
- }
-
- public void removeAppStartingWindow(IBinder token) {
- synchronized (mWindowMap) {
- final AppWindowToken wtoken = mRoot.getAppWindowToken(token);
- scheduleRemoveStartingWindowLocked(wtoken);
- }
- }
-
public void setAppFullscreen(IBinder token, boolean toOpaque) {
synchronized (mWindowMap) {
final AppWindowToken atoken = mRoot.getAppWindowToken(token);
@@ -3055,233 +2851,6 @@
}
}
- @Override
- public void notifyAppResumed(IBinder token, boolean wasStopped, boolean allowSavedSurface) {
- if (!checkCallingPermission(MANAGE_APP_TOKENS, "notifyAppResumed()")) {
- throw new SecurityException("Requires MANAGE_APP_TOKENS permission");
- }
-
- synchronized(mWindowMap) {
- final AppWindowToken wtoken = mRoot.getAppWindowToken(token);
- if (wtoken == null) {
- Slog.w(TAG_WM, "Attempted to notify resumed of non-existing app token: " + token);
- return;
- }
- wtoken.notifyAppResumed(wasStopped, allowSavedSurface);
- }
- }
-
- @Override
- public void notifyAppStopped(IBinder token) {
- if (!checkCallingPermission(MANAGE_APP_TOKENS, "notifyAppStopped()")) {
- throw new SecurityException("Requires MANAGE_APP_TOKENS permission");
- }
-
- synchronized(mWindowMap) {
- final AppWindowToken wtoken;
- wtoken = mRoot.getAppWindowToken(token);
- if (wtoken == null) {
- Slog.w(TAG_WM, "Attempted to notify stopped of non-existing app token: " + token);
- return;
- }
- wtoken.notifyAppStopped();
- }
- }
-
- @Override
- public void setAppVisibility(IBinder token, boolean visible) {
- if (!checkCallingPermission(MANAGE_APP_TOKENS, "setAppVisibility()")) {
- throw new SecurityException("Requires MANAGE_APP_TOKENS permission");
- }
-
- AppWindowToken wtoken;
-
- synchronized(mWindowMap) {
- wtoken = mRoot.getAppWindowToken(token);
- if (wtoken == null) {
- Slog.w(TAG_WM, "Attempted to set visibility of non-existing app token: " + token);
- return;
- }
-
- if (DEBUG_APP_TRANSITIONS || DEBUG_ORIENTATION) Slog.v(TAG_WM, "setAppVisibility(" +
- token + ", visible=" + visible + "): " + mAppTransition +
- " hidden=" + wtoken.hidden + " hiddenRequested=" +
- wtoken.hiddenRequested + " Callers=" + Debug.getCallers(6));
-
- mOpeningApps.remove(wtoken);
- mClosingApps.remove(wtoken);
- wtoken.waitingToShow = false;
- wtoken.hiddenRequested = !visible;
-
- if (!visible) {
- // If the app is dead while it was visible, we kept its dead window on screen.
- // Now that the app is going invisible, we can remove it. It will be restarted
- // if made visible again.
- wtoken.removeDeadWindows();
- wtoken.setVisibleBeforeClientHidden();
- } else if (visible) {
- if (!mAppTransition.isTransitionSet() && mAppTransition.isReady()) {
- // Add the app mOpeningApps if transition is unset but ready. This means
- // we're doing a screen freeze, and the unfreeze will wait for all opening
- // apps to be ready.
- mOpeningApps.add(wtoken);
- }
- wtoken.startingMoved = false;
- // If the token is currently hidden (should be the common case), or has been
- // stopped, then we need to set up to wait for its windows to be ready.
- if (wtoken.hidden || wtoken.mAppStopped) {
- wtoken.clearAllDrawn();
-
- // If the app was already visible, don't reset the waitingToShow state.
- if (wtoken.hidden) {
- wtoken.waitingToShow = true;
- }
-
- if (wtoken.clientHidden) {
- // In the case where we are making an app visible
- // but holding off for a transition, we still need
- // to tell the client to make its windows visible so
- // they get drawn. Otherwise, we will wait on
- // performing the transition until all windows have
- // been drawn, they never will be, and we are sad.
- wtoken.clientHidden = false;
- wtoken.sendAppVisibilityToClients();
- }
- }
- wtoken.requestUpdateWallpaperIfNeeded();
-
- if (DEBUG_ADD_REMOVE) Slog.v(
- TAG_WM, "No longer Stopped: " + wtoken);
- wtoken.mAppStopped = false;
- }
-
- // If we are preparing an app transition, then delay changing
- // the visibility of this token until we execute that transition.
- if (okToDisplay() && mAppTransition.isTransitionSet()) {
- // A dummy animation is a placeholder animation which informs others that an
- // animation is going on (in this case an application transition). If the animation
- // was transferred from another application/animator, no dummy animator should be
- // created since an animation is already in progress.
- if (wtoken.mAppAnimator.usingTransferredAnimation
- && wtoken.mAppAnimator.animation == null) {
- Slog.wtf(TAG_WM, "Will NOT set dummy animation on: " + wtoken
- + ", using null transfered animation!");
- }
- if (!wtoken.mAppAnimator.usingTransferredAnimation &&
- (!wtoken.startingDisplayed || mSkipAppTransitionAnimation)) {
- if (DEBUG_APP_TRANSITIONS) Slog.v(
- TAG_WM, "Setting dummy animation on: " + wtoken);
- wtoken.mAppAnimator.setDummyAnimation();
- }
- wtoken.inPendingTransaction = true;
- if (visible) {
- mOpeningApps.add(wtoken);
- wtoken.mEnteringAnimation = true;
- } else {
- mClosingApps.add(wtoken);
- wtoken.mEnteringAnimation = false;
- }
- if (mAppTransition.getAppTransition() == AppTransition.TRANSIT_TASK_OPEN_BEHIND) {
- // We're launchingBehind, add the launching activity to mOpeningApps.
- final WindowState win = getDefaultDisplayContentLocked().findFocusedWindow();
- if (win != null) {
- final AppWindowToken focusedToken = win.mAppToken;
- if (focusedToken != null) {
- if (DEBUG_APP_TRANSITIONS) Slog.d(TAG_WM, "TRANSIT_TASK_OPEN_BEHIND, " +
- " adding " + focusedToken + " to mOpeningApps");
- // Force animation to be loaded.
- focusedToken.hidden = true;
- mOpeningApps.add(focusedToken);
- }
- }
- }
- return;
- }
-
- final long origId = Binder.clearCallingIdentity();
- wtoken.setVisibility(null, visible, TRANSIT_UNSET, true, wtoken.mVoiceInteraction);
- wtoken.updateReportedVisibilityLocked();
- Binder.restoreCallingIdentity(origId);
- }
- }
-
- /**
- * Notifies that we launched an app that might be visible or not visible depending on what kind
- * of Keyguard flags it's going to set on its windows.
- */
- public void notifyUnknownAppVisibilityLaunched(IBinder token) {
- synchronized(mWindowMap) {
- AppWindowToken appWindow = mRoot.getAppWindowToken(token);
- if (appWindow != null) {
- mUnknownAppVisibilityController.notifyLaunched(appWindow);
- }
- }
- }
-
- @Override
- public void startAppFreezingScreen(IBinder token, int configChanges) {
- if (!checkCallingPermission(MANAGE_APP_TOKENS, "setAppFreezingScreen()")) {
- throw new SecurityException("Requires MANAGE_APP_TOKENS permission");
- }
-
- synchronized(mWindowMap) {
- if (configChanges == 0 && okToDisplay()) {
- if (DEBUG_ORIENTATION) Slog.v(TAG_WM, "Skipping set freeze of " + token);
- return;
- }
-
- final AppWindowToken wtoken = mRoot.getAppWindowToken(token);
- if (wtoken == null || wtoken.appToken == null) {
- Slog.w(TAG_WM, "Attempted to freeze screen with non-existing app token: " + wtoken);
- return;
- }
- final long origId = Binder.clearCallingIdentity();
- wtoken.startFreezingScreen();
- Binder.restoreCallingIdentity(origId);
- }
- }
-
- @Override
- public void stopAppFreezingScreen(IBinder token, boolean force) {
- if (!checkCallingPermission(MANAGE_APP_TOKENS, "setAppFreezingScreen()")) {
- throw new SecurityException("Requires MANAGE_APP_TOKENS permission");
- }
-
- synchronized(mWindowMap) {
- final AppWindowToken wtoken = mRoot.getAppWindowToken(token);
- if (wtoken == null || wtoken.appToken == null) {
- return;
- }
- final long origId = Binder.clearCallingIdentity();
- if (DEBUG_ORIENTATION) Slog.v(TAG_WM, "Clear freezing of " + token + ": hidden="
- + wtoken.hidden + " freezing=" + wtoken.mAppAnimator.freezingScreen);
- wtoken.stopFreezingScreen(true, force);
- Binder.restoreCallingIdentity(origId);
- }
- }
-
- @Override
- public void removeAppToken(IBinder binder, int displayId) {
- if (!checkCallingPermission(MANAGE_APP_TOKENS, "removeAppToken()")) {
- throw new SecurityException("Requires MANAGE_APP_TOKENS permission");
- }
-
- final long origId = Binder.clearCallingIdentity();
- try {
- synchronized(mWindowMap) {
- final DisplayContent dc = mRoot.getDisplayContent(displayId);
- if (dc == null) {
- Slog.w(TAG_WM, "removeAppToken: Attempted to remove binder token: " + binder
- + " from non-existing displayId=" + displayId);
- return;
- }
- dc.removeAppToken(binder);
- }
- } finally {
- Binder.restoreCallingIdentity(origId);
- }
- }
-
void scheduleRemoveStartingWindowLocked(AppWindowToken wtoken) {
if (wtoken == null) {
return;
@@ -3850,9 +3419,9 @@
return;
}
- // If this isn't coming from the current user, ignore it.
- if (Binder.getCallingUserHandle().getIdentifier() != mCurrentUserId) {
- Log.d(TAG_WM, "non-current user, ignore disableKeyguard");
+ // If this isn't coming from the current profiles, ignore it.
+ if (!isCurrentProfileLocked(UserHandle.getCallingUserId())) {
+ Log.d(TAG_WM, "non-current profiles, ignore disableKeyguard");
return;
}
@@ -4523,7 +4092,7 @@
}
try {
Trace.traceBegin(Trace.TRACE_TAG_WINDOW_MANAGER, "screenshotWallpaper");
- return screenshotApplicationsInner(null /* appToken */, DEFAULT_DISPLAY, -1 /* width */,
+ return screenshotApplications(null /* appToken */, DEFAULT_DISPLAY, -1 /* width */,
-1 /* height */, true /* includeFullDisplay */, 1f /* frameScale */,
Bitmap.Config.ARGB_8888, true /* wallpaperOnly */);
} finally {
@@ -4544,7 +4113,7 @@
}
FgThread.getHandler().post(() -> {
- Bitmap bm = screenshotApplicationsInner(null /* appToken */, DEFAULT_DISPLAY,
+ Bitmap bm = screenshotApplications(null /* appToken */, DEFAULT_DISPLAY,
-1 /* width */, -1 /* height */, true /* includeFullDisplay */,
1f /* frameScale */, Bitmap.Config.ARGB_8888, false /* wallpaperOnly */);
try {
@@ -4563,37 +4132,12 @@
* @param displayId the Display to take a screenshot of.
* @param width the width of the target bitmap
* @param height the height of the target bitmap
- * @param frameScale the scale to apply to the frame, only used when width = -1 and height = -1
- */
- @Override
- public Bitmap screenshotApplications(IBinder appToken, int displayId, int width, int height,
- float frameScale) {
- if (!checkCallingPermission(Manifest.permission.READ_FRAME_BUFFER,
- "screenshotApplications()")) {
- throw new SecurityException("Requires READ_FRAME_BUFFER permission");
- }
- try {
- Trace.traceBegin(Trace.TRACE_TAG_WINDOW_MANAGER, "screenshotApplications");
- return screenshotApplicationsInner(appToken, displayId, width, height, false,
- frameScale, Bitmap.Config.RGB_565, false);
- } finally {
- Trace.traceEnd(Trace.TRACE_TAG_WINDOW_MANAGER);
- }
- }
-
- /**
- * Takes a snapshot of the screen. In landscape mode this grabs the whole screen.
- * In portrait mode, it grabs the full screenshot.
- *
- * @param displayId the Display to take a screenshot of.
- * @param width the width of the target bitmap
- * @param height the height of the target bitmap
* @param includeFullDisplay true if the screen should not be cropped before capture
* @param frameScale the scale to apply to the frame, only used when width = -1 and height = -1
* @param config of the output bitmap
* @param wallpaperOnly true if only the wallpaper layer should be included in the screenshot
*/
- private Bitmap screenshotApplicationsInner(IBinder appToken, int displayId, int width,
+ private Bitmap screenshotApplications(IBinder appToken, int displayId, int width,
int height, boolean includeFullDisplay, float frameScale, Bitmap.Config config,
boolean wallpaperOnly) {
final DisplayContent displayContent;
@@ -5907,34 +5451,6 @@
private boolean mEventDispatchingEnabled;
@Override
- public void pauseKeyDispatching(IBinder binder) {
- if (!checkCallingPermission(MANAGE_APP_TOKENS, "pauseKeyDispatching()")) {
- throw new SecurityException("Requires MANAGE_APP_TOKENS permission");
- }
-
- synchronized (mWindowMap) {
- WindowToken token = mRoot.getAppWindowToken(binder);
- if (token != null) {
- mInputMonitor.pauseDispatchingLw(token);
- }
- }
- }
-
- @Override
- public void resumeKeyDispatching(IBinder binder) {
- if (!checkCallingPermission(MANAGE_APP_TOKENS, "resumeKeyDispatching()")) {
- throw new SecurityException("Requires MANAGE_APP_TOKENS permission");
- }
-
- synchronized (mWindowMap) {
- WindowToken token = mRoot.getAppWindowToken(binder);
- if (token != null) {
- mInputMonitor.resumeDispatchingLw(token);
- }
- }
- }
-
- @Override
public void setEventDispatching(boolean enabled) {
if (!checkCallingPermission(MANAGE_APP_TOKENS, "setEventDispatching()")) {
throw new SecurityException("Requires MANAGE_APP_TOKENS permission");
@@ -6065,8 +5581,6 @@
public static final int ADD_STARTING = 5;
public static final int REMOVE_STARTING = 6;
public static final int FINISHED_STARTING = 7;
- public static final int REPORT_APPLICATION_TOKEN_WINDOWS = 8;
- public static final int REPORT_APPLICATION_TOKEN_DRAWN = 9;
public static final int WINDOW_FREEZE_TIMEOUT = 11;
public static final int APP_TRANSITION_TIMEOUT = 13;
@@ -6328,37 +5842,6 @@
}
} break;
- case REPORT_APPLICATION_TOKEN_DRAWN: {
- final AppWindowToken wtoken = (AppWindowToken)msg.obj;
-
- try {
- if (DEBUG_VISIBILITY) Slog.v(
- TAG_WM, "Reporting drawn in " + wtoken);
- wtoken.appToken.windowsDrawn();
- } catch (RemoteException ex) {
- }
- } break;
-
- case REPORT_APPLICATION_TOKEN_WINDOWS: {
- final AppWindowToken wtoken = (AppWindowToken)msg.obj;
-
- boolean nowVisible = msg.arg1 != 0;
- boolean nowGone = msg.arg2 != 0;
-
- try {
- if (DEBUG_VISIBILITY) Slog.v(
- TAG_WM, "Reporting visible in " + wtoken
- + " visible=" + nowVisible
- + " gone=" + nowGone);
- if (nowVisible) {
- wtoken.appToken.windowsVisible();
- } else {
- wtoken.appToken.windowsGone();
- }
- } catch (RemoteException ex) {
- }
- } break;
-
case WINDOW_FREEZE_TIMEOUT: {
// TODO(multidisplay): Can non-default displays rotate?
synchronized (mWindowMap) {
@@ -7155,6 +6638,16 @@
displayInfo.overscanRight, displayInfo.overscanBottom);
}
+ /**
+ * Get an array with display ids ordered by focus priority - last items should be given
+ * focus first. Sparse array just maps position to displayId.
+ */
+ public void getDisplaysInFocusOrder(SparseIntArray displaysInFocusOrder) {
+ synchronized(mWindowMap) {
+ mRoot.getDisplaysInFocusOrder(displaysInFocusOrder);
+ }
+ }
+
@Override
public void setOverscan(int displayId, int left, int top, int right, int bottom) {
if (mContext.checkCallingOrSelfPermission(
diff --git a/services/core/jni/com_android_server_HardwarePropertiesManagerService.cpp b/services/core/jni/com_android_server_HardwarePropertiesManagerService.cpp
index c42141a..17a6c297 100644
--- a/services/core/jni/com_android_server_HardwarePropertiesManagerService.cpp
+++ b/services/core/jni/com_android_server_HardwarePropertiesManagerService.cpp
@@ -37,6 +37,8 @@
using hardware::thermal::V1_0::Temperature;
using hardware::thermal::V1_0::ThermalStatus;
using hardware::thermal::V1_0::ThermalStatusCode;
+template<typename T>
+using Return = hardware::Return<T>;
// ---------------------------------------------------------------------------
@@ -76,7 +78,7 @@
}
hidl_vec<CoolingDevice> list;
- Status status = gThermalModule->getCoolingDevices(
+ Return<void> ret = gThermalModule->getCoolingDevices(
[&list](ThermalStatus status, hidl_vec<CoolingDevice> devices) {
if (status.code == ThermalStatusCode::SUCCESS) {
list = std::move(devices);
@@ -84,10 +86,10 @@
ALOGE("Couldn't get fan speeds because of HAL error: %s",
status.debugMessage.c_str());
}
- }).getStatus();
+ });
- if (!status.isOk()) {
- ALOGE("getCoolingDevices failed status: %d", status.exceptionCode());
+ if (!ret.isOk()) {
+ ALOGE("getCoolingDevices failed status: %s", ret.description().c_str());
}
float values[list.size()];
@@ -106,7 +108,7 @@
return env->NewFloatArray(0);
}
hidl_vec<Temperature> list;
- Status status = gThermalModule->getTemperatures(
+ Return<void> ret = gThermalModule->getTemperatures(
[&list](ThermalStatus status, hidl_vec<Temperature> temperatures) {
if (status.code == ThermalStatusCode::SUCCESS) {
list = std::move(temperatures);
@@ -114,10 +116,10 @@
ALOGE("Couldn't get temperatures because of HAL error: %s",
status.debugMessage.c_str());
}
- }).getStatus();
+ });
- if (!status.isOk()) {
- ALOGE("getDeviceTemperatures failed status: %d", status.exceptionCode());
+ if (!ret.isOk()) {
+ ALOGE("getDeviceTemperatures failed status: %s", ret.description().c_str());
}
jfloat values[list.size()];
@@ -151,7 +153,7 @@
return env->NewObjectArray(0, gCpuUsageInfoClassInfo.clazz, nullptr);
}
hidl_vec<CpuUsage> list;
- Status status = gThermalModule->getCpuUsages(
+ Return<void> ret = gThermalModule->getCpuUsages(
[&list](ThermalStatus status, hidl_vec<CpuUsage> cpuUsages) {
if (status.code == ThermalStatusCode::SUCCESS) {
list = std::move(cpuUsages);
@@ -159,10 +161,10 @@
ALOGE("Couldn't get CPU usages because of HAL error: %s",
status.debugMessage.c_str());
}
- }).getStatus();
+ });
- if (!status.isOk()) {
- ALOGE("getCpuUsages failed status: %d", status.exceptionCode());
+ if (!ret.isOk()) {
+ ALOGE("getCpuUsages failed status: %s", ret.description().c_str());
}
jobjectArray cpuUsages = env->NewObjectArray(list.size(), gCpuUsageInfoClassInfo.clazz,
diff --git a/services/core/jni/com_android_server_hdmi_HdmiCecController.cpp b/services/core/jni/com_android_server_hdmi_HdmiCecController.cpp
index 0c5729e..7790d15 100644
--- a/services/core/jni/com_android_server_hdmi_HdmiCecController.cpp
+++ b/services/core/jni/com_android_server_hdmi_HdmiCecController.cpp
@@ -185,14 +185,14 @@
mLooper(looper) {
mHdmiCecCallback = new HdmiCecCallback(this);
Return<void> ret = mHdmiCec->setCallback(mHdmiCecCallback);
- if (!ret.getStatus().isOk()) {
+ if (!ret.isOk()) {
ALOGE("Failed to set a cec callback.");
}
}
HdmiCecController::~HdmiCecController() {
Return<void> ret = mHdmiCec->setCallback(nullptr);
- if (!ret.getStatus().isOk()) {
+ if (!ret.isOk()) {
ALOGE("Failed to set a cec callback.");
}
}
@@ -200,7 +200,7 @@
int HdmiCecController::sendMessage(const CecMessage& message) {
// TODO: propagate send_message's return value.
Return<SendMessageResult> ret = mHdmiCec->sendMessage(message);
- if (!ret.getStatus().isOk()) {
+ if (!ret.isOk()) {
ALOGE("Failed to send CEC message.");
return static_cast<int>(SendMessageResult::FAIL);
}
@@ -209,7 +209,7 @@
int HdmiCecController::addLogicalAddress(CecLogicalAddress address) {
Return<Result> ret = mHdmiCec->addLogicalAddress(address);
- if (!ret.getStatus().isOk()) {
+ if (!ret.isOk()) {
ALOGE("Failed to add a logical address.");
return static_cast<int>(Result::FAILURE_UNKNOWN);
}
@@ -218,7 +218,7 @@
void HdmiCecController::clearLogicaladdress() {
Return<void> ret = mHdmiCec->clearLogicalAddress();
- if (!ret.getStatus().isOk()) {
+ if (!ret.isOk()) {
ALOGE("Failed to clear logical address.");
}
}
@@ -230,7 +230,7 @@
result = res;
addr = paddr;
});
- if (!ret.getStatus().isOk()) {
+ if (!ret.isOk()) {
ALOGE("Failed to get physical address.");
return INVALID_PHYSICAL_ADDRESS;
}
@@ -239,7 +239,7 @@
int HdmiCecController::getVersion() {
Return<int32_t> ret = mHdmiCec->getCecVersion();
- if (!ret.getStatus().isOk()) {
+ if (!ret.isOk()) {
ALOGE("Failed to get cec version.");
}
return ret;
@@ -247,7 +247,7 @@
uint32_t HdmiCecController::getVendorId() {
Return<uint32_t> ret = mHdmiCec->getVendorId();
- if (!ret.getStatus().isOk()) {
+ if (!ret.isOk()) {
ALOGE("Failed to get vendor id.");
}
return ret;
@@ -267,7 +267,7 @@
Return<void> ret = mHdmiCec->getPortInfo([&ports](hidl_vec<HdmiPortInfo> list) {
ports = list;
});
- if (!ret.getStatus().isOk()) {
+ if (!ret.isOk()) {
ALOGE("Failed to get port information.");
return NULL;
}
@@ -287,14 +287,14 @@
void HdmiCecController::setOption(OptionKey key, bool enabled) {
Return<void> ret = mHdmiCec->setOption(key, enabled);
- if (!ret.getStatus().isOk()) {
+ if (!ret.isOk()) {
ALOGE("Failed to set option.");
}
}
void HdmiCecController::setLanguage(hidl_string language) {
Return<void> ret = mHdmiCec->setLanguage(language);
- if (!ret.getStatus().isOk()) {
+ if (!ret.isOk()) {
ALOGE("Failed to set language.");
}
}
@@ -302,7 +302,7 @@
// Enable audio return channel.
void HdmiCecController::enableAudioReturnChannel(int port, bool enabled) {
Return<void> ret = mHdmiCec->enableAudioReturnChannel(port, enabled);
- if (!ret.getStatus().isOk()) {
+ if (!ret.isOk()) {
ALOGE("Failed to enable/disable ARC.");
}
}
@@ -310,7 +310,7 @@
// Whether to hdmi device is connected to the given port.
bool HdmiCecController::isConnected(int port) {
Return<bool> ret = mHdmiCec->isConnected(port);
- if (!ret.getStatus().isOk()) {
+ if (!ret.isOk()) {
ALOGE("Failed to get connection info.");
}
return ret;
diff --git a/services/core/jni/com_android_server_lights_LightsService.cpp b/services/core/jni/com_android_server_lights_LightsService.cpp
index a3ab8f6..cf7f1cb 100644
--- a/services/core/jni/com_android_server_lights_LightsService.cpp
+++ b/services/core/jni/com_android_server_lights_LightsService.cpp
@@ -117,8 +117,7 @@
ALOGD_IF_SLOW(50, "Excessive delay setting light");
Return<Status> ret = gLight->setLight(type, state);
- // TODO(b/31348667): this is transport specific status
- if (!ret.getStatus().isOk()) {
+ if (!ret.isOk()) {
ALOGE("Failed to issue set light command.");
return;
}
diff --git a/services/core/jni/com_android_server_location_ContextHubService.cpp b/services/core/jni/com_android_server_location_ContextHubService.cpp
index e25bda8..47c9559 100644
--- a/services/core/jni/com_android_server_location_ContextHubService.cpp
+++ b/services/core/jni/com_android_server_location_ContextHubService.cpp
@@ -42,7 +42,6 @@
using IContexthub = android::hardware::contexthub::V1_0::IContexthub;
using Result = android::hardware::contexthub::V1_0::Result;
-using NanoAppBinary = android::hardware::contexthub::V1_0::NanoAppBinary;
using ContextHubMsg = android::hardware::contexthub::V1_0::ContextHubMsg;
using IContexthubCallback = android::hardware::contexthub::V1_0::IContexthubCallback;
using AsyncEventType = android::hardware::contexthub::V1_0::AsyncEventType;
diff --git a/services/core/jni/com_android_server_location_GnssLocationProvider.cpp b/services/core/jni/com_android_server_location_GnssLocationProvider.cpp
index b7032db..09886db 100644
--- a/services/core/jni/com_android_server_location_GnssLocationProvider.cpp
+++ b/services/core/jni/com_android_server_location_GnssLocationProvider.cpp
@@ -888,75 +888,68 @@
// TODO(b/31632518)
gnssHal = IGnss::getService("gnss");
if (gnssHal != nullptr) {
- auto result = gnssHal->getExtensionXtra([](const sp<IGnssXtra>& xtraIface) {
- gnssXtraIface = xtraIface;
- });
-
- if (!result.getStatus().isOk()) {
+ auto gnssXtra = gnssHal->getExtensionXtra();
+ if (!gnssXtra.isOk()) {
ALOGD("Unable to get a handle to Xtra");
+ } else {
+ gnssXtraIface = gnssXtra;
}
- result = gnssHal->getExtensionAGnssRil([](const sp<IAGnssRil>& rilIface) {
- agnssRilIface = rilIface;
- });
-
- if (!result.getStatus().isOk()) {
+ auto gnssRil = gnssHal->getExtensionAGnssRil();
+ if (!gnssRil.isOk()) {
ALOGD("Unable to get a handle to AGnssRil");
+ } else {
+ agnssRilIface = gnssRil;
}
- result = gnssHal->getExtensionAGnss([](const sp<IAGnss>& assistedGnssIface) {
- agnssIface = assistedGnssIface;
- });
-
- if (!result.getStatus().isOk()) {
+ auto gnssAgnss = gnssHal->getExtensionAGnss();
+ if (!gnssAgnss.isOk()) {
ALOGD("Unable to get a handle to AGnss");
+ } else {
+ agnssIface = gnssAgnss;
}
- result = gnssHal->getExtensionGnssNavigationMessage(
- [](const sp<IGnssNavigationMessage>& navigationMessageIface) {
- gnssNavigationMessageIface = navigationMessageIface;
- });
-
- if (!result.getStatus().isOk()) {
+ auto gnssNavigationMessage = gnssHal->getExtensionGnssNavigationMessage();
+ if (!gnssNavigationMessage.isOk()) {
ALOGD("Unable to get a handle to GnssNavigationMessage");
+ } else {
+ gnssNavigationMessageIface = gnssNavigationMessage;
}
- result = gnssHal->getExtensionGnssMeasurement([](
- const sp<IGnssMeasurement>& measurementIface) {
- gnssMeasurementIface = measurementIface;
- });
- if (!result.getStatus().isOk()) {
+ auto gnssMeasurement = gnssHal->getExtensionGnssMeasurement();
+ if (!gnssMeasurement.isOk()) {
ALOGD("Unable to get a handle to GnssMeasurement");
+ } else {
+ gnssMeasurementIface = gnssMeasurement;
}
- result = gnssHal->getExtensionGnssDebug([](const sp<IGnssDebug>& debugIface) {
- gnssDebugIface = debugIface;
- });
- if (!result.getStatus().isOk()) {
+ auto gnssDebug = gnssHal->getExtensionGnssDebug();
+ if (!gnssDebug.isOk()) {
ALOGD("Unable to get a handle to GnssDebug");
+ } else {
+ gnssDebugIface = gnssDebug;
}
- result = gnssHal->getExtensionGnssNi([](const sp<IGnssNi>& niIface) {
- gnssNiIface = niIface;
- });
- if (!result.getStatus().isOk()) {
+ auto gnssNi = gnssHal->getExtensionGnssNi();
+ if (!gnssNi.isOk()) {
ALOGD("Unable to get a handle to GnssNi");
+ } else {
+ gnssNiIface = gnssNi;
}
- result = gnssHal->getExtensionGnssConfiguration([](const sp<IGnssConfiguration>& configIface) {
- gnssConfigurationIface = configIface;
- });
- if (!result.getStatus().isOk()) {
+ auto gnssConfiguration = gnssHal->getExtensionGnssConfiguration();
+ if (!gnssConfiguration.isOk()) {
ALOGD("Unable to get a handle to GnssConfiguration");
+ } else {
+ gnssConfigurationIface = gnssConfiguration;
}
- result = gnssHal->getExtensionGnssGeofencing([](const sp<IGnssGeofencing>& geofenceIface) {
- gnssGeofencingIface = geofenceIface;
- });
- if (!result.getStatus().isOk()) {
+ auto gnssGeofencing = gnssHal->getExtensionGnssGeofencing();
+ if (!gnssGeofencing.isOk()) {
ALOGD("Unable to get a handle to GnssGeofencing");
+ } else {
+ gnssGeofencingIface = gnssGeofencing;
}
-
} else {
ALOGE("Unable to get GPS service\n");
}
@@ -994,7 +987,7 @@
}
auto result = gnssHal->setCallback(gnssCbIface);
- if ((!result) || (!result.getStatus().isOk())) {
+ if ((!result) || (!result.isOk())) {
ALOGE("SetCallback for Gnss Interface fails\n");
return JNI_FALSE;
}
@@ -1004,7 +997,7 @@
ALOGE("Unable to initialize GNSS Xtra interface\n");
} else {
result = gnssXtraIface->setCallback(gnssXtraCbIface);
- if ((!result) || (!result.getStatus().isOk())) {
+ if ((!result) || (!result.isOk())) {
gnssXtraIface = nullptr;
ALOGE("SetCallback for Gnss Xtra Interface fails\n");
}
@@ -1049,7 +1042,7 @@
min_interval,
preferred_accuracy,
preferred_time);
- if (!result.getStatus().isOk()) {
+ if (!result.isOk()) {
ALOGE("%s: GNSS setPositionMode failed\n", __func__);
return JNI_FALSE;
} else {
@@ -1063,7 +1056,7 @@
static jboolean android_location_GnssLocationProvider_start(JNIEnv* /* env */, jobject /* obj */) {
if (gnssHal != nullptr) {
auto result = gnssHal->start();
- if (!result.getStatus().isOk()) {
+ if (!result.isOk()) {
return JNI_FALSE;
} else {
return result;
@@ -1076,7 +1069,7 @@
static jboolean android_location_GnssLocationProvider_stop(JNIEnv* /* env */, jobject /* obj */) {
if (gnssHal != nullptr) {
auto result = gnssHal->stop();
- if (!result.getStatus().isOk()) {
+ if (!result.isOk()) {
return JNI_FALSE;
} else {
return result;
@@ -1090,7 +1083,7 @@
jint flags) {
if (gnssHal != nullptr) {
auto result = gnssHal->deleteAidingData(static_cast<IGnss::GnssAidingData>(flags));
- if (!result.getStatus().isOk()) {
+ if (!result.isOk()) {
ALOGE("Error in deleting aiding data");
}
}
@@ -1191,7 +1184,7 @@
jlong time, jlong timeReference, jint uncertainty) {
if (gnssHal != nullptr) {
auto result = gnssHal->injectTime(time, timeReference, uncertainty);
- if (!result || !result.getStatus().isOk()) {
+ if (!result || !result.isOk()) {
ALOGE("%s: Gnss injectTime() failed", __func__);
}
}
@@ -1201,7 +1194,7 @@
jobject /* obj */, jdouble latitude, jdouble longitude, jfloat accuracy) {
if (gnssHal != nullptr) {
auto result = gnssHal->injectLocation(latitude, longitude, accuracy);
- if (!result || !result.getStatus().isOk()) {
+ if (!result || !result.isOk()) {
ALOGE("%s: Gnss injectLocation() failed", __func__);
}
}
@@ -1238,7 +1231,7 @@
const char *apnStr = env->GetStringUTFChars(apn, NULL);
auto result = agnssIface->dataConnOpen(apnStr, static_cast<IAGnss::ApnIpType>(apnIpType));
- if ((!result) || (!result.getStatus().isOk())) {
+ if ((!result) || (!result.isOk())) {
ALOGE("%s: Failed to set APN and its IP type", __func__);
}
env->ReleaseStringUTFChars(apn, apnStr);
@@ -1252,7 +1245,7 @@
}
auto result = agnssIface->dataConnClosed();
- if ((!result) || (!result.getStatus().isOk())) {
+ if ((!result) || (!result.isOk())) {
ALOGE("%s: Failed to close AGnss data connection", __func__);
}
}
@@ -1265,7 +1258,7 @@
}
auto result = agnssIface->dataConnFailed();
- if ((!result) || (!result.getStatus().isOk())) {
+ if ((!result) || (!result.isOk())) {
ALOGE("%s: Failed to notify unavailability of AGnss data connection", __func__);
}
}
@@ -1281,7 +1274,7 @@
auto result = agnssIface->setServer(static_cast<IAGnssCallback::AGnssType>(type),
c_hostname,
port);
- if ((!result) || (!result.getStatus().isOk())) {
+ if ((!result) || (!result.isOk())) {
ALOGE("%s: Failed to set AGnss host name and port", __func__);
}
@@ -1354,13 +1347,13 @@
auto result = agnssRilIface->updateNetworkState(connected,
static_cast<IAGnssRil::NetworkType>(type),
roaming);
- if ((!result) || (!result.getStatus().isOk())) {
+ if ((!result) || (!result.isOk())) {
ALOGE("updateNetworkState failed");
}
const char *c_apn = env->GetStringUTFChars(apn, NULL);
result = agnssRilIface->updateNetworkAvailability(available, c_apn);
- if ((!result) || (!result.getStatus().isOk())) {
+ if ((!result) || (!result.isOk())) {
ALOGE("updateNetworkAvailability failed");
}
@@ -1384,7 +1377,7 @@
geofenceId, latitude, longitude, radius,
static_cast<IGnssGeofenceCallback::GeofenceTransition>(last_transition),
monitor_transition, notification_responsiveness, unknown_timer);
- return boolToJbool(result.getStatus().isOk());
+ return boolToJbool(result.isOk());
} else {
ALOGE("Geofence Interface not available");
}
@@ -1395,7 +1388,7 @@
jobject /* obj */, jint geofenceId) {
if (gnssGeofencingIface != nullptr) {
auto result = gnssGeofencingIface->removeGeofence(geofenceId);
- return boolToJbool(result.getStatus().isOk());
+ return boolToJbool(result.isOk());
} else {
ALOGE("Geofence interface not available");
}
@@ -1406,7 +1399,7 @@
jobject /* obj */, jint geofenceId) {
if (gnssGeofencingIface != nullptr) {
auto result = gnssGeofencingIface->pauseGeofence(geofenceId);
- return boolToJbool(result.getStatus().isOk());
+ return boolToJbool(result.isOk());
} else {
ALOGE("Geofence interface not available");
}
@@ -1417,7 +1410,7 @@
jobject /* obj */, jint geofenceId, jint monitor_transition) {
if (gnssGeofencingIface != nullptr) {
auto result = gnssGeofencingIface->resumeGeofence(geofenceId, monitor_transition);
- return boolToJbool(result.getStatus().isOk());
+ return boolToJbool(result.isOk());
} else {
ALOGE("Geofence interface not available");
}
@@ -1463,7 +1456,7 @@
}
auto result = gnssMeasurementIface->close();
- return boolToJbool(result.getStatus().isOk());
+ return boolToJbool(result.isOk());
}
static jboolean android_location_GnssLocationProvider_is_navigation_message_supported(
@@ -1505,7 +1498,7 @@
}
auto result = gnssNavigationMessageIface->close();
- return boolToJbool(result.getStatus().isOk());
+ return boolToJbool(result.isOk());
}
static jboolean android_location_GnssLocationProvider_set_emergency_supl_pdn(JNIEnv*,
@@ -1517,7 +1510,7 @@
}
auto result = gnssConfigurationIface->setEmergencySuplPdn(emergencySuplPdn);
- if (result.getStatus().isOk()) {
+ if (result.isOk()) {
return result;
} else {
return JNI_FALSE;
@@ -1532,7 +1525,7 @@
return JNI_FALSE;
}
auto result = gnssConfigurationIface->setSuplVersion(version);
- if (result.getStatus().isOk()) {
+ if (result.isOk()) {
return result;
} else {
return JNI_FALSE;
@@ -1548,7 +1541,7 @@
}
auto result = gnssConfigurationIface->setSuplEs(suplEs);
- if (result.getStatus().isOk()) {
+ if (result.isOk()) {
return result;
} else {
return JNI_FALSE;
@@ -1564,7 +1557,7 @@
}
auto result = gnssConfigurationIface->setSuplMode(mode);
- if (result.getStatus().isOk()) {
+ if (result.isOk()) {
return result;
} else {
return JNI_FALSE;
@@ -1580,7 +1573,7 @@
}
auto result = gnssConfigurationIface->setGpsLock(gpsLock);
- if (result.getStatus().isOk()) {
+ if (result.isOk()) {
return result;
} else {
return JNI_FALSE;
@@ -1597,7 +1590,7 @@
auto result = gnssConfigurationIface->setLppProfile(lppProfile);
- if (result.getStatus().isOk()) {
+ if (result.isOk()) {
return result;
} else {
return JNI_FALSE;
@@ -1613,7 +1606,7 @@
}
auto result = gnssConfigurationIface->setGlonassPositioningProtocol(gnssPosProtocol);
- if (result.getStatus().isOk()) {
+ if (result.isOk()) {
return result;
} else {
return JNI_FALSE;
diff --git a/services/coverage/Android.mk b/services/coverage/Android.mk
new file mode 100644
index 0000000..da99994
--- /dev/null
+++ b/services/coverage/Android.mk
@@ -0,0 +1,12 @@
+LOCAL_PATH := $(call my-dir)
+
+include $(CLEAR_VARS)
+
+LOCAL_MODULE := services.coverage
+
+LOCAL_SRC_FILES += \
+ $(call all-java-files-under,java)
+
+LOCAL_JAVA_LIBRARIES := jacocoagent
+
+include $(BUILD_STATIC_JAVA_LIBRARY)
diff --git a/services/coverage/java/com/android/server/coverage/CoverageService.java b/services/coverage/java/com/android/server/coverage/CoverageService.java
new file mode 100644
index 0000000..d600aa8c
--- /dev/null
+++ b/services/coverage/java/com/android/server/coverage/CoverageService.java
@@ -0,0 +1,145 @@
+/*
+ * Copyright (C) 2016 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.coverage;
+
+import android.os.Binder;
+import android.os.ParcelFileDescriptor;
+import android.os.ShellCallback;
+import android.os.ShellCommand;
+import android.os.ResultReceiver;
+
+import org.jacoco.agent.rt.RT;
+
+import java.io.BufferedOutputStream;
+import java.io.File;
+import java.io.FileDescriptor;
+import java.io.IOException;
+import java.io.PrintWriter;
+
+/**
+ * A service that responds to `cmd coverage ...` and provides a mechanism for dumping code coverage
+ * information from the system server process.
+ * @hide
+ */
+public class CoverageService extends Binder {
+
+ public static final String COVERAGE_SERVICE = "coverage";
+ public static final boolean ENABLED;
+
+ static {
+ // This service should only be enabled if org.jacoco.agent.rt.RT was added to the build
+ boolean shouldEnable = true;
+ try {
+ Class.forName("org.jacoco.agent.rt.RT");
+ } catch (ClassNotFoundException e) {
+ shouldEnable = false;
+ }
+ ENABLED = shouldEnable;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public void onShellCommand(FileDescriptor in, FileDescriptor out, FileDescriptor err,
+ String[] args, ShellCallback callback, ResultReceiver resultReceiver) {
+ new CoverageCommand().exec(this, in, out, err, args, callback, resultReceiver);
+ }
+
+ /**
+ * A {@link ShellCommand} implementation for performing coverage shell commands.
+ */
+ private static class CoverageCommand extends ShellCommand {
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public int onCommand(String cmd) {
+ if ("dump".equals(cmd)) {
+ return onDump();
+ } else if ("reset".equals(cmd)) {
+ return onReset();
+ } else {
+ return handleDefaultCommands(cmd);
+ }
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public void onHelp() {
+ PrintWriter pw = getOutPrintWriter();
+ pw.println("Coverage commands:");
+ pw.println(" help");
+ pw.println(" Print this help text.");
+ pw.println(" dump [FILE]");
+ pw.println(" Dump code coverage to FILE.");
+ pw.println(" reset");
+ pw.println(" Reset coverage information.");
+ }
+
+ /**
+ * Perform the "dump" command to write the collected execution data to a file.
+ *
+ * @return The command result.
+ */
+ private int onDump() {
+ // Figure out where to dump the coverage data
+ String dest = getNextArg();
+ if (dest == null) {
+ dest = "/data/local/tmp/coverage.ec";
+ } else {
+ File f = new File(dest);
+ if (f.isDirectory()) {
+ dest = new File(f, "coverage.ec").getAbsolutePath();
+ }
+ }
+
+ // Try to open the destination file
+ ParcelFileDescriptor fd = openOutputFileForSystem(dest);
+ if (fd == null) {
+ return -1;
+ }
+
+ // Write the execution data to the file
+ try (BufferedOutputStream output = new BufferedOutputStream(
+ new ParcelFileDescriptor.AutoCloseOutputStream(fd))) {
+ output.write(RT.getAgent().getExecutionData(false));
+ output.flush();
+ getOutPrintWriter().println(String.format("Dumped coverage data to %s", dest));
+ } catch (IOException e) {
+ getErrPrintWriter().println("Failed to dump coverage data: " + e.getMessage());
+ return -1;
+ }
+
+ return 0;
+ }
+
+ /**
+ * Perform the "reset" command to clear the collected execution data.
+ *
+ * @return The command result.
+ */
+ private int onReset() {
+ RT.getAgent().reset();
+ getOutPrintWriter().println("Reset coverage data");
+ return 0;
+ }
+ }
+}
diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
index 10a19d7..9f66062 100644
--- a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
+++ b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
@@ -75,6 +75,7 @@
import android.app.admin.SecurityLog.SecurityEvent;
import android.app.admin.SystemUpdatePolicy;
import android.app.backup.IBackupManager;
+import android.app.trust.TrustManager;
import android.content.BroadcastReceiver;
import android.content.ComponentName;
import android.content.Context;
@@ -1492,6 +1493,10 @@
return TelephonyManager.from(mContext);
}
+ TrustManager getTrustManager() {
+ return (TrustManager) mContext.getSystemService(Context.TRUST_SERVICE);
+ }
+
IWindowManager getIWindowManager() {
return IWindowManager.Stub
.asInterface(ServiceManager.getService(Context.WINDOW_SERVICE));
@@ -4405,31 +4410,52 @@
}
@Override
- public void lockNow(boolean parent) {
+ public void lockNow(int flags, boolean parent) {
if (!mHasFeature) {
return;
}
+
+ final int callingUserId = mInjector.userHandleGetCallingUserId();
synchronized (this) {
// This API can only be called by an active device admin,
// so try to retrieve it to check that the caller is one.
- getActiveAdminForCallerLocked(
+ final ActiveAdmin admin = getActiveAdminForCallerLocked(
null, DeviceAdminInfo.USES_POLICY_FORCE_LOCK, parent);
- int userToLock = mInjector.userHandleGetCallingUserId();
-
- // Unless this is a managed profile with work challenge enabled, lock all users.
- if (parent || !isSeparateProfileChallengeEnabled(userToLock)) {
- userToLock = UserHandle.USER_ALL;
- }
final long ident = mInjector.binderClearCallingIdentity();
try {
+ // Evict key
+ if ((flags & DevicePolicyManager.FLAG_EVICT_CE_KEY) != 0) {
+ enforceManagedProfile(callingUserId, "set FLAG_EVICT_CE_KEY");
+ if (!isProfileOwner(admin.info.getComponent(), callingUserId)) {
+ throw new SecurityException(
+ "Only profile owner admins can set FLAG_EVICT_CE_KEY");
+ }
+ if (parent) {
+ throw new IllegalArgumentException(
+ "Cannot set FLAG_EVICT_CE_KEY for the parent");
+ }
+ if (!mInjector.storageManagerIsFileBasedEncryptionEnabled()) {
+ throw new UnsupportedOperationException(
+ "FLAG_EVICT_CE_KEY only applies to FBE devices");
+ }
+ mUserManager.evictCredentialEncryptionKey(callingUserId);
+ }
+
+ // Lock all users unless this is a managed profile with a separate challenge
+ final int userToLock = (parent || !isSeparateProfileChallengeEnabled(callingUserId)
+ ? UserHandle.USER_ALL : callingUserId);
mLockPatternUtils.requireStrongAuth(
STRONG_AUTH_REQUIRED_AFTER_DPM_LOCK_NOW, userToLock);
+
+ // Require authentication for the device or profile
if (userToLock == UserHandle.USER_ALL) {
// Power off the display
mInjector.powerManagerGoToSleep(SystemClock.uptimeMillis(),
PowerManager.GO_TO_SLEEP_REASON_DEVICE_ADMIN, 0);
mInjector.getIWindowManager().lockNow(null);
+ } else {
+ mInjector.getTrustManager().setDeviceLockedForUser(userToLock, true);
}
} catch (RemoteException e) {
} finally {
@@ -4788,7 +4814,9 @@
}
}
- private void wipeDataLocked(boolean wipeExtRequested, String reason, boolean force) {
+ private void wipeDataNoLock(boolean wipeExtRequested, String reason, boolean force) {
+ wtfIfInLock();
+
if (wipeExtRequested) {
StorageManager sm = (StorageManager) mContext.getSystemService(
Context.STORAGE_SERVICE);
@@ -4808,13 +4836,14 @@
}
final int userHandle = mInjector.userHandleGetCallingUserId();
enforceFullCrossUsersPermission(userHandle);
+
+ final String source;
synchronized (this) {
// This API can only be called by an active device admin,
// so try to retrieve it to check that the caller is one.
final ActiveAdmin admin = getActiveAdminForCallerLocked(null,
DeviceAdminInfo.USES_POLICY_WIPE_DATA);
-
- final String source = admin.info.getComponent().flattenToShortString();
+ source = admin.info.getComponent().flattenToShortString();
long ident = mInjector.binderClearCallingIdentity();
try {
@@ -4844,45 +4873,47 @@
}
}
- boolean wipeExtRequested = (flags & WIPE_EXTERNAL_STORAGE) != 0;
- wipeDeviceOrUserLocked(wipeExtRequested, userHandle,
- "DevicePolicyManager.wipeData() from " + source, /*force=*/ true);
} finally {
mInjector.binderRestoreCallingIdentity(ident);
}
}
+ final boolean wipeExtRequested = (flags & WIPE_EXTERNAL_STORAGE) != 0;
+ wipeDeviceNoLock(wipeExtRequested, userHandle,
+ "DevicePolicyManager.wipeData() from " + source, /*force=*/ true);
}
- private void wipeDeviceOrUserLocked(
+ private void wipeDeviceNoLock(
boolean wipeExtRequested, final int userHandle, String reason, boolean force) {
- // TODO If split user is enabled and the device owner is set in the primary user (rather
- // than system), we should probably trigger factory reset. Current code just remove
- // that user (but still clears FRP...)
- if (userHandle == UserHandle.USER_SYSTEM) {
- wipeDataLocked(wipeExtRequested, reason, force);
- } else {
- mHandler.post(new Runnable() {
- @Override
- public void run() {
- try {
- IActivityManager am = mInjector.getIActivityManager();
- if (am.getCurrentUser().id == userHandle) {
- am.switchUser(UserHandle.USER_SYSTEM);
- }
+ wtfIfInLock();
- boolean userRemoved = force
- ? mUserManagerInternal.removeUserEvenWhenDisallowed(userHandle)
- : mUserManager.removeUser(userHandle);
- if (!userRemoved) {
- Slog.w(LOG_TAG, "Couldn't remove user " + userHandle);
- } else if (isManagedProfile(userHandle)) {
- sendWipeProfileNotification();
- }
- } catch (RemoteException re) {
- // Shouldn't happen
+ long ident = mInjector.binderClearCallingIdentity();
+ try {
+ // TODO If split user is enabled and the device owner is set in the primary user (rather
+ // than system), we should probably trigger factory reset. Current code just remove
+ // that user (but still clears FRP...)
+ if (userHandle == UserHandle.USER_SYSTEM) {
+ wipeDataNoLock(wipeExtRequested, reason, force);
+ } else {
+ try {
+ IActivityManager am = mInjector.getIActivityManager();
+ if (am.getCurrentUser().id == userHandle) {
+ am.switchUser(UserHandle.USER_SYSTEM);
}
+
+ boolean userRemoved = force
+ ? mUserManagerInternal.removeUserEvenWhenDisallowed(userHandle)
+ : mUserManager.removeUser(userHandle);
+ if (!userRemoved) {
+ Slog.w(LOG_TAG, "Couldn't remove user " + userHandle);
+ } else if (isManagedProfile(userHandle)) {
+ sendWipeProfileNotification();
+ }
+ } catch (RemoteException re) {
+ // Shouldn't happen
}
- });
+ }
+ } finally {
+ mInjector.binderRestoreCallingIdentity(ident);
}
}
@@ -5047,8 +5078,7 @@
}
if (wipeData) {
// Call without holding lock.
- wipeDeviceOrUserLocked(false, identifier,
- "reportFailedPasswordAttempt()", false);
+ wipeDeviceNoLock(false, identifier, "reportFailedPasswordAttempt()", false);
}
} finally {
mInjector.binderRestoreCallingIdentity(ident);
@@ -5980,8 +6010,10 @@
throw new IllegalArgumentException("Invalid component " + admin
+ " for device owner");
}
+ final boolean hasIncompatibleAccountsOrNonAdb =
+ hasIncompatibleAccountsOrNonAdbNoLock(userId, admin);
synchronized (this) {
- enforceCanSetDeviceOwnerLocked(admin, userId);
+ enforceCanSetDeviceOwnerLocked(admin, userId, hasIncompatibleAccountsOrNonAdb);
final ActiveAdmin activeAdmin = getActiveAdminUncheckedLocked(admin, userId);
if (activeAdmin == null
|| getUserData(userId).mRemovingAdmins.contains(admin)) {
@@ -6217,8 +6249,10 @@
throw new IllegalArgumentException("Component " + who
+ " not installed for userId:" + userHandle);
}
+ final boolean hasIncompatibleAccountsOrNonAdb =
+ hasIncompatibleAccountsOrNonAdbNoLock(userHandle, who);
synchronized (this) {
- enforceCanSetProfileOwnerLocked(who, userHandle);
+ enforceCanSetProfileOwnerLocked(who, userHandle, hasIncompatibleAccountsOrNonAdb);
if (getActiveAdminUncheckedLocked(who, userHandle) == null
|| getUserData(userHandle).mRemovingAdmins.contains(who)) {
@@ -6546,14 +6580,24 @@
}
/**
+ * Calls wtfStack() if called with the DPMS lock held.
+ */
+ private void wtfIfInLock() {
+ if (Thread.holdsLock(this)) {
+ Slog.wtfStack(LOG_TAG, "Shouldn't be called with DPMS lock held");
+ }
+ }
+
+ /**
* The profile owner can only be set by adb or an app with the MANAGE_PROFILE_AND_DEVICE_OWNERS
* permission.
* The profile owner can only be set before the user setup phase has completed,
* except for:
* - SYSTEM_UID
- * - adb if there are no accounts. (But see {@link #hasIncompatibleAccountsLocked})
+ * - adb unless hasIncompatibleAccountsOrNonAdb is true.
*/
- private void enforceCanSetProfileOwnerLocked(@Nullable ComponentName owner, int userHandle) {
+ private void enforceCanSetProfileOwnerLocked(@Nullable ComponentName owner, int userHandle,
+ boolean hasIncompatibleAccountsOrNonAdb) {
UserInfo info = getUserInfo(userHandle);
if (info == null) {
// User doesn't exist.
@@ -6573,7 +6617,7 @@
}
if (isAdb()) {
if ((mIsWatch || hasUserSetupCompleted(userHandle))
- && hasIncompatibleAccountsLocked(userHandle, owner)) {
+ && hasIncompatibleAccountsOrNonAdb) {
throw new IllegalStateException("Not allowed to set the profile owner because "
+ "there are already some accounts on the profile");
}
@@ -6590,12 +6634,14 @@
* The Device owner can only be set by adb or an app with the MANAGE_PROFILE_AND_DEVICE_OWNERS
* permission.
*/
- private void enforceCanSetDeviceOwnerLocked(@Nullable ComponentName owner, int userId) {
+ private void enforceCanSetDeviceOwnerLocked(@Nullable ComponentName owner, int userId,
+ boolean hasIncompatibleAccountsOrNonAdb) {
if (!isAdb()) {
enforceCanManageProfileAndDeviceOwners();
}
- final int code = checkDeviceOwnerProvisioningPreConditionLocked(owner, userId, isAdb());
+ final int code = checkDeviceOwnerProvisioningPreConditionLocked(
+ owner, userId, isAdb(), hasIncompatibleAccountsOrNonAdb);
switch (code) {
case CODE_OK:
return;
@@ -8904,7 +8950,7 @@
* except for adb command if no accounts or additional users are present on the device.
*/
private int checkDeviceOwnerProvisioningPreConditionLocked(@Nullable ComponentName owner,
- int deviceOwnerUserId, boolean isAdb) {
+ int deviceOwnerUserId, boolean isAdb, boolean hasIncompatibleAccountsOrNonAdb) {
if (mOwners.hasDeviceOwner()) {
return CODE_HAS_DEVICE_OWNER;
}
@@ -8924,7 +8970,7 @@
if (mUserManager.getUserCount() > 1) {
return CODE_NONSYSTEM_USER_EXISTS;
}
- if (hasIncompatibleAccountsLocked(UserHandle.USER_SYSTEM, owner)) {
+ if (hasIncompatibleAccountsOrNonAdb) {
return CODE_ACCOUNTS_NOT_EMPTY;
}
} else {
@@ -8951,8 +8997,10 @@
private int checkDeviceOwnerProvisioningPreCondition(int deviceOwnerUserId) {
synchronized (this) {
+ // hasIncompatibleAccountsOrNonAdb doesn't matter since the caller is not adb.
return checkDeviceOwnerProvisioningPreConditionLocked(/* owner unknown */ null,
- deviceOwnerUserId, /* isAdb= */ false);
+ deviceOwnerUserId, /* isAdb= */ false,
+ /* hasIncompatibleAccountsOrNonAdb=*/ true);
}
}
@@ -9850,8 +9898,19 @@
* - Otherwise, if there's any account that does not have ..._ALLOWED, or does have
* ..._DISALLOWED, return true.
* - Otherwise return false.
+ *
+ * If the caller is *not* ADB, it also returns true. The returned value shouldn't be used
+ * when the caller is not ADB.
+ *
+ * DO NOT CALL IT WITH THE DPMS LOCK HELD.
*/
- private boolean hasIncompatibleAccountsLocked(int userId, @Nullable ComponentName owner) {
+ private boolean hasIncompatibleAccountsOrNonAdbNoLock(
+ int userId, @Nullable ComponentName owner) {
+ if (!isAdb()) {
+ return true;
+ }
+ wtfIfInLock();
+
final long token = mInjector.binderClearCallingIdentity();
try {
final AccountManager am = AccountManager.get(mContext);
@@ -9859,22 +9918,30 @@
if (accounts.length == 0) {
return false;
}
+ synchronized (this) {
+ if (owner == null || !isAdminTestOnlyLocked(owner, userId)) {
+ Log.w(LOG_TAG,
+ "Non test-only owner can't be installed with existing accounts.");
+ return true;
+ }
+ }
+
final String[] feature_allow =
{ DevicePolicyManager.ACCOUNT_FEATURE_DEVICE_OR_PROFILE_OWNER_ALLOWED };
final String[] feature_disallow =
{ DevicePolicyManager.ACCOUNT_FEATURE_DEVICE_OR_PROFILE_OWNER_DISALLOWED };
- // Even if we find incompatible accounts along the way, we still check all accounts
- // for logging.
boolean compatible = true;
for (Account account : accounts) {
if (hasAccountFeatures(am, account, feature_disallow)) {
Log.e(LOG_TAG, account + " has " + feature_disallow[0]);
compatible = false;
+ break;
}
if (!hasAccountFeatures(am, account, feature_allow)) {
Log.e(LOG_TAG, account + " doesn't have " + feature_allow[0]);
compatible = false;
+ break;
}
}
if (compatible) {
@@ -9882,28 +9949,6 @@
} else {
Log.e(LOG_TAG, "Found incompatible accounts");
}
-
- // Then check if the owner is test-only.
- String log;
- if (owner == null) {
- // Owner is unknown. Suppose it's not test-only
- compatible = false;
- log = "Only test-only device/profile owner can be installed with accounts";
- } else if (isAdminTestOnlyLocked(owner, userId)) {
- if (compatible) {
- log = "Installing test-only owner " + owner;
- } else {
- log = "Can't install test-only owner " + owner + " with incompatible accounts";
- }
- } else {
- compatible = false;
- log = "Can't install non test-only owner " + owner + " with accounts";
- }
- if (compatible) {
- Log.w(LOG_TAG, log);
- } else {
- Log.e(LOG_TAG, log);
- }
return !compatible;
} finally {
mInjector.binderRestoreCallingIdentity(token);
@@ -9965,6 +10010,7 @@
+ " service not being available yet.");
}
mNetworkLogger = null;
+ mInjector.getNotificationManager().cancel(NETWORK_LOGGING_NOTIFICATION_ID);
}
} finally {
mInjector.binderRestoreCallingIdentity(callingIdentity);
diff --git a/services/java/com/android/server/SystemServer.java b/services/java/com/android/server/SystemServer.java
index be13499..283de42 100644
--- a/services/java/com/android/server/SystemServer.java
+++ b/services/java/com/android/server/SystemServer.java
@@ -63,6 +63,7 @@
import com.android.server.clipboard.ClipboardService;
import com.android.server.connectivity.IpConnectivityMetrics;
import com.android.server.connectivity.MetricsLoggerService;
+import com.android.server.coverage.CoverageService;
import com.android.server.devicepolicy.DevicePolicyManagerService;
import com.android.server.display.DisplayManagerService;
import com.android.server.display.NightDisplayService;
@@ -164,6 +165,8 @@
"com.android.server.LockSettingsService$Lifecycle";
private static final String STORAGE_MANAGER_SERVICE_CLASS =
"com.android.server.StorageManagerService$Lifecycle";
+ private static final String STORAGE_STATS_SERVICE_CLASS =
+ "com.android.server.usage.StorageStatsService$Lifecycle";
private static final String SEARCH_MANAGER_SERVICE_CLASS =
"com.android.server.search.SearchManagerService$Lifecycle";
private static final String THERMAL_OBSERVER_CLASS =
@@ -218,6 +221,7 @@
private boolean mOnlyCore;
private boolean mFirstBoot;
+ private final boolean mRuntimeRestart;
/**
* Start the sensor service.
@@ -234,6 +238,8 @@
public SystemServer() {
// Check for factory test mode.
mFactoryTestMode = FactoryTest.getMode();
+ // Remember if it's runtime restart(when sys.boot_completed is already set) or reboot
+ mRuntimeRestart = "1".equals(SystemProperties.get("sys.boot_completed"));
}
private void run() {
@@ -270,13 +276,16 @@
// Here we go!
Slog.i(TAG, "Entered the Android system server!");
- int uptimeMillis = (int) SystemClock.uptimeMillis();
+ int uptimeMillis = (int) SystemClock.elapsedRealtime();
EventLog.writeEvent(EventLogTags.BOOT_PROGRESS_SYSTEM_RUN, uptimeMillis);
- MetricsLogger.histogram(null, "boot_system_server_init", uptimeMillis);
- // Also report when first stage of init has started
- long initStartNs = SystemProperties.getLong("ro.boottime.init", -1);
- if (initStartNs >= 0) {
- MetricsLogger.histogram(null, "boot_android_init", (int)(initStartNs / 1000000));
+ if (!mRuntimeRestart) {
+ MetricsLogger.histogram(null, "boot_system_server_init", uptimeMillis);
+ // Also report when first stage of init has started
+ long initStartNs = SystemProperties.getLong("ro.boottime.init", -1);
+ if (initStartNs >= 0) {
+ MetricsLogger.histogram(null, "boot_android_init",
+ (int)(initStartNs / 1000000));
+ }
}
// In case the runtime switched since last boot (such as when
@@ -344,6 +353,8 @@
// Create the system service manager.
mSystemServiceManager = new SystemServiceManager(mSystemContext);
LocalServices.addService(SystemServiceManager.class, mSystemServiceManager);
+ // Prepare the thread pool for init tasks that can be parallelized
+ SystemServerInitThreadPool.get();
} finally {
traceEnd(); // InitBeforeStartServices
}
@@ -361,12 +372,16 @@
} finally {
traceEnd();
}
+ SystemServerInitThreadPool.shutdown();
// For debug builds, log event loop stalls to dropbox for analysis.
if (StrictMode.conditionallyEnableDebugLogging()) {
Slog.i(TAG, "Enabled StrictMode for system server main thread.");
}
- MetricsLogger.histogram(null, "boot_system_server_ready", (int) SystemClock.uptimeMillis());
+ if (!mRuntimeRestart) {
+ MetricsLogger.histogram(null, "boot_system_server_ready",
+ (int) SystemClock.elapsedRealtime());
+ }
// Loop forever.
Looper.loop();
@@ -495,16 +510,20 @@
}
// Start the package manager.
- MetricsLogger.histogram(null, "boot_package_manager_init_start",
- (int) SystemClock.uptimeMillis());
+ if (!mRuntimeRestart) {
+ MetricsLogger.histogram(null, "boot_package_manager_init_start",
+ (int) SystemClock.elapsedRealtime());
+ }
traceBeginAndSlog("StartPackageManagerService");
mPackageManagerService = PackageManagerService.main(mSystemContext, installer,
mFactoryTestMode != FactoryTest.FACTORY_TEST_OFF, mOnlyCore);
mFirstBoot = mPackageManagerService.isFirstBoot();
mPackageManager = mSystemContext.getPackageManager();
traceEnd();
- MetricsLogger.histogram(null, "boot_package_manager_init_ready",
- (int) SystemClock.uptimeMillis());
+ if (!mRuntimeRestart) {
+ MetricsLogger.histogram(null, "boot_package_manager_init_ready",
+ (int) SystemClock.elapsedRealtime());
+ }
// Manages A/B OTA dexopting. This is a bootstrap service as we need it to rename
// A/B artifacts after boot, before anything else might touch/need them.
// Note: this isn't needed during decryption (we don't have /data anyways).
@@ -710,10 +729,12 @@
traceEnd();
}
+ traceBeginAndSlog("SetWindowManagerService");
mActivityManagerService.setWindowManager(wm);
+ traceEnd();
- inputManager.setWindowManagerCallbacks(wm.getInputMonitor());
traceBeginAndSlog("StartInputManager");
+ inputManager.setWindowManagerCallbacks(wm.getInputMonitor());
inputManager.start();
traceEnd();
@@ -789,7 +810,7 @@
if (mFactoryTestMode != FactoryTest.FACTORY_TEST_LOW_LEVEL) {
if (!disableStorage &&
- !"0".equals(SystemProperties.get("system_init.startmountservice"))) {
+ !"0".equals(SystemProperties.get("system_init.startmountservice"))) {
traceBeginAndSlog("StartStorageManagerService");
try {
/*
@@ -800,7 +821,15 @@
storageManager = IStorageManager.Stub.asInterface(
ServiceManager.getService("mount"));
} catch (Throwable e) {
- reportWtf("starting StorageManager Service", e);
+ reportWtf("starting StorageManagerService", e);
+ }
+ traceEnd();
+
+ traceBeginAndSlog("StartStorageStatsService");
+ try {
+ mSystemServiceManager.startService(STORAGE_STATS_SERVICE_CLASS);
+ } catch (Throwable e) {
+ reportWtf("starting StorageStatsService", e);
}
traceEnd();
}
@@ -1238,8 +1267,10 @@
}
if (!disableNetwork && !disableNonCoreServices && EmergencyAffordanceManager.ENABLED) {
- // EmergencyMode sevice
+ // EmergencyMode service
+ traceBeginAndSlog("StartEmergencyAffordanceService");
mSystemServiceManager.startService(EmergencyAffordanceService.class);
+ traceEnd();
}
if (!disableNonCoreServices) {
@@ -1256,6 +1287,12 @@
traceEnd();
}
+ if (!disableNonCoreServices && CoverageService.ENABLED) {
+ traceBeginAndSlog("AddCoverageService");
+ ServiceManager.addService(CoverageService.COVERAGE_SERVICE, new CoverageService());
+ traceEnd();
+ }
+
if (mPackageManager.hasSystemFeature(PackageManager.FEATURE_PRINTING)) {
traceBeginAndSlog("StartPrintManager");
mSystemServiceManager.startService(PRINT_MANAGER_SERVICE_CLASS);
@@ -1482,176 +1519,167 @@
// where third party code can really run (but before it has actually
// started launching the initial applications), for us to complete our
// initialization.
- mActivityManagerService.systemReady(new Runnable() {
- @Override
- public void run() {
- Slog.i(TAG, "Making services ready");
- traceBeginAndSlog("StartActivityManagerReadyPhase");
- mSystemServiceManager.startBootPhase(
- SystemService.PHASE_ACTIVITY_MANAGER_READY);
- traceEnd();
- traceBeginAndSlog("PhaseActivityManagerReady");
-
- traceBeginAndSlog("StartObservingNativeCrashes");
- try {
- mActivityManagerService.startObservingNativeCrashes();
- } catch (Throwable e) {
- reportWtf("observing native crashes", e);
- }
- traceEnd();
-
- if (!mOnlyCore) {
- Slog.i(TAG, "WebViewFactory preparation");
- traceBeginAndSlog("WebViewFactoryPreparation");
- mWebViewUpdateService.prepareWebViewInSystemServer();
- traceEnd();
- }
-
- traceBeginAndSlog("StartSystemUI");
- try {
- startSystemUi(context);
- } catch (Throwable e) {
- reportWtf("starting System UI", e);
- }
- traceEnd();
- traceBeginAndSlog("MakeNetworkScoreReady");
- try {
- if (networkScoreF != null) networkScoreF.systemReady();
- } catch (Throwable e) {
- reportWtf("making Network Score Service ready", e);
- }
- traceEnd();
- traceBeginAndSlog("MakeNetworkManagementServiceReady");
- try {
- if (networkManagementF != null) networkManagementF.systemReady();
- } catch (Throwable e) {
- reportWtf("making Network Managment Service ready", e);
- }
- CountDownLatch networkPolicyInitReadySignal = null;
- if (networkPolicyF != null) {
- networkPolicyInitReadySignal = networkPolicyF
- .networkScoreAndNetworkManagementServiceReady();
- }
- traceEnd();
- traceBeginAndSlog("MakeNetworkStatsServiceReady");
- try {
- if (networkStatsF != null) networkStatsF.systemReady();
- } catch (Throwable e) {
- reportWtf("making Network Stats Service ready", e);
- }
- traceEnd();
- traceBeginAndSlog("MakeConnectivityServiceReady");
- try {
- if (connectivityF != null) connectivityF.systemReady();
- } catch (Throwable e) {
- reportWtf("making Connectivity Service ready", e);
- }
- traceEnd();
- traceBeginAndSlog("MakeNetworkPolicyServiceReady");
- try {
- if (networkPolicyF != null) {
- networkPolicyF.systemReady(networkPolicyInitReadySignal);
- }
- } catch (Throwable e) {
- reportWtf("making Network Policy Service ready", e);
- }
- traceEnd();
-
- traceBeginAndSlog("StartWatchdog");
- Watchdog.getInstance().start();
- traceEnd();
-
- // It is now okay to let the various system services start their
- // third party code...
- traceBeginAndSlog("PhaseThirdPartyAppsCanStart");
- mSystemServiceManager.startBootPhase(
- SystemService.PHASE_THIRD_PARTY_APPS_CAN_START);
- traceEnd();
-
- traceBeginAndSlog("MakeLocationServiceReady");
- try {
- if (locationF != null) locationF.systemRunning();
- } catch (Throwable e) {
- reportWtf("Notifying Location Service running", e);
- }
- traceEnd();
- traceBeginAndSlog("MakeCountryDetectionServiceReady");
- try {
- if (countryDetectorF != null) countryDetectorF.systemRunning();
- } catch (Throwable e) {
- reportWtf("Notifying CountryDetectorService running", e);
- }
- traceEnd();
- traceBeginAndSlog("MakeNetworkTimeUpdateReady");
- try {
- if (networkTimeUpdaterF != null) networkTimeUpdaterF.systemRunning();
- } catch (Throwable e) {
- reportWtf("Notifying NetworkTimeService running", e);
- }
- traceEnd();
- traceBeginAndSlog("MakeCommonTimeManagementServiceReady");
- try {
- if (commonTimeMgmtServiceF != null) {
- commonTimeMgmtServiceF.systemRunning();
- }
- } catch (Throwable e) {
- reportWtf("Notifying CommonTimeManagementService running", e);
- }
- traceEnd();
- traceBeginAndSlog("MakeInputManagerServiceReady");
- try {
- // TODO(BT) Pass parameter to input manager
- if (inputManagerF != null) inputManagerF.systemRunning();
- } catch (Throwable e) {
- reportWtf("Notifying InputManagerService running", e);
- }
- traceEnd();
- traceBeginAndSlog("MakeTelephonyRegistryReady");
- try {
- if (telephonyRegistryF != null) telephonyRegistryF.systemRunning();
- } catch (Throwable e) {
- reportWtf("Notifying TelephonyRegistry running", e);
- }
- traceEnd();
- traceBeginAndSlog("MakeMediaRouterServiceReady");
- try {
- if (mediaRouterF != null) mediaRouterF.systemRunning();
- } catch (Throwable e) {
- reportWtf("Notifying MediaRouterService running", e);
- }
- traceEnd();
- traceBeginAndSlog("MakeMmsServiceReady");
- try {
- if (mmsServiceF != null) mmsServiceF.systemRunning();
- } catch (Throwable e) {
- reportWtf("Notifying MmsService running", e);
- }
- traceEnd();
-
- traceBeginAndSlog("MakeNetworkScoreServiceReady");
- try {
- if (networkScoreF != null) networkScoreF.systemRunning();
- } catch (Throwable e) {
- reportWtf("Notifying NetworkScoreService running", e);
- }
- traceEnd();
-
- traceBeginAndSlog("IncidentDaemonReady");
- try {
- // TODO: Switch from checkService to getService once it's always
- // in the build and should reliably be there.
- final IIncidentManager incident = IIncidentManager.Stub.asInterface(
- ServiceManager.checkService("incident"));
- if (incident != null) incident.systemRunning();
- } catch (Throwable e) {
- reportWtf("Notifying incident daemon running", e);
- }
- traceEnd();
-
-
- traceEnd(); // PhaseActivityManagerReady
+ mActivityManagerService.systemReady(() -> {
+ Slog.i(TAG, "Making services ready");
+ traceBeginAndSlog("StartActivityManagerReadyPhase");
+ mSystemServiceManager.startBootPhase(
+ SystemService.PHASE_ACTIVITY_MANAGER_READY);
+ traceEnd();
+ traceBeginAndSlog("StartObservingNativeCrashes");
+ try {
+ mActivityManagerService.startObservingNativeCrashes();
+ } catch (Throwable e) {
+ reportWtf("observing native crashes", e);
}
- });
+ traceEnd();
+
+ if (!mOnlyCore) {
+ Slog.i(TAG, "WebViewFactory preparation");
+ traceBeginAndSlog("WebViewFactoryPreparation");
+ mWebViewUpdateService.prepareWebViewInSystemServer();
+ traceEnd();
+ }
+
+ traceBeginAndSlog("StartSystemUI");
+ try {
+ startSystemUi(context);
+ } catch (Throwable e) {
+ reportWtf("starting System UI", e);
+ }
+ traceEnd();
+ traceBeginAndSlog("MakeNetworkScoreReady");
+ try {
+ if (networkScoreF != null) networkScoreF.systemReady();
+ } catch (Throwable e) {
+ reportWtf("making Network Score Service ready", e);
+ }
+ traceEnd();
+ traceBeginAndSlog("MakeNetworkManagementServiceReady");
+ try {
+ if (networkManagementF != null) networkManagementF.systemReady();
+ } catch (Throwable e) {
+ reportWtf("making Network Managment Service ready", e);
+ }
+ CountDownLatch networkPolicyInitReadySignal = null;
+ if (networkPolicyF != null) {
+ networkPolicyInitReadySignal = networkPolicyF
+ .networkScoreAndNetworkManagementServiceReady();
+ }
+ traceEnd();
+ traceBeginAndSlog("MakeNetworkStatsServiceReady");
+ try {
+ if (networkStatsF != null) networkStatsF.systemReady();
+ } catch (Throwable e) {
+ reportWtf("making Network Stats Service ready", e);
+ }
+ traceEnd();
+ traceBeginAndSlog("MakeConnectivityServiceReady");
+ try {
+ if (connectivityF != null) connectivityF.systemReady();
+ } catch (Throwable e) {
+ reportWtf("making Connectivity Service ready", e);
+ }
+ traceEnd();
+ traceBeginAndSlog("MakeNetworkPolicyServiceReady");
+ try {
+ if (networkPolicyF != null) {
+ networkPolicyF.systemReady(networkPolicyInitReadySignal);
+ }
+ } catch (Throwable e) {
+ reportWtf("making Network Policy Service ready", e);
+ }
+ traceEnd();
+
+ traceBeginAndSlog("StartWatchdog");
+ Watchdog.getInstance().start();
+ traceEnd();
+
+ // It is now okay to let the various system services start their
+ // third party code...
+ traceBeginAndSlog("PhaseThirdPartyAppsCanStart");
+ mSystemServiceManager.startBootPhase(
+ SystemService.PHASE_THIRD_PARTY_APPS_CAN_START);
+ traceEnd();
+
+ traceBeginAndSlog("MakeLocationServiceReady");
+ try {
+ if (locationF != null) locationF.systemRunning();
+ } catch (Throwable e) {
+ reportWtf("Notifying Location Service running", e);
+ }
+ traceEnd();
+ traceBeginAndSlog("MakeCountryDetectionServiceReady");
+ try {
+ if (countryDetectorF != null) countryDetectorF.systemRunning();
+ } catch (Throwable e) {
+ reportWtf("Notifying CountryDetectorService running", e);
+ }
+ traceEnd();
+ traceBeginAndSlog("MakeNetworkTimeUpdateReady");
+ try {
+ if (networkTimeUpdaterF != null) networkTimeUpdaterF.systemRunning();
+ } catch (Throwable e) {
+ reportWtf("Notifying NetworkTimeService running", e);
+ }
+ traceEnd();
+ traceBeginAndSlog("MakeCommonTimeManagementServiceReady");
+ try {
+ if (commonTimeMgmtServiceF != null) {
+ commonTimeMgmtServiceF.systemRunning();
+ }
+ } catch (Throwable e) {
+ reportWtf("Notifying CommonTimeManagementService running", e);
+ }
+ traceEnd();
+ traceBeginAndSlog("MakeInputManagerServiceReady");
+ try {
+ // TODO(BT) Pass parameter to input manager
+ if (inputManagerF != null) inputManagerF.systemRunning();
+ } catch (Throwable e) {
+ reportWtf("Notifying InputManagerService running", e);
+ }
+ traceEnd();
+ traceBeginAndSlog("MakeTelephonyRegistryReady");
+ try {
+ if (telephonyRegistryF != null) telephonyRegistryF.systemRunning();
+ } catch (Throwable e) {
+ reportWtf("Notifying TelephonyRegistry running", e);
+ }
+ traceEnd();
+ traceBeginAndSlog("MakeMediaRouterServiceReady");
+ try {
+ if (mediaRouterF != null) mediaRouterF.systemRunning();
+ } catch (Throwable e) {
+ reportWtf("Notifying MediaRouterService running", e);
+ }
+ traceEnd();
+ traceBeginAndSlog("MakeMmsServiceReady");
+ try {
+ if (mmsServiceF != null) mmsServiceF.systemRunning();
+ } catch (Throwable e) {
+ reportWtf("Notifying MmsService running", e);
+ }
+ traceEnd();
+
+ traceBeginAndSlog("MakeNetworkScoreServiceReady");
+ try {
+ if (networkScoreF != null) networkScoreF.systemRunning();
+ } catch (Throwable e) {
+ reportWtf("Notifying NetworkScoreService running", e);
+ }
+ traceEnd();
+ traceBeginAndSlog("IncidentDaemonReady");
+ try {
+ // TODO: Switch from checkService to getService once it's always
+ // in the build and should reliably be there.
+ final IIncidentManager incident = IIncidentManager.Stub.asInterface(
+ ServiceManager.checkService("incident"));
+ if (incident != null) incident.systemRunning();
+ } catch (Throwable e) {
+ reportWtf("Notifying incident daemon running", e);
+ }
+ traceEnd();
+ }, BOOT_TIMINGS_TRACE_LOG);
}
static final void startSystemUi(Context context) {
diff --git a/services/tests/notification/AndroidManifest.xml b/services/tests/notification/AndroidManifest.xml
index 087806e..1ed8ed0 100644
--- a/services/tests/notification/AndroidManifest.xml
+++ b/services/tests/notification/AndroidManifest.xml
@@ -18,7 +18,10 @@
package="com.android.frameworks.tests.notification">
<uses-permission android:name="android.permission.INTERACT_ACROSS_USERS" />
+ <uses-permission android:name="android.permission.INTERACT_ACROSS_USERS_FULL" />
+ <uses-permission android:name="android.permission.UPDATE_APP_OPS_STATS" />
<uses-permission android:name="android.permission.MANAGE_USERS" />
+ <uses-permission android:name="android.permission.WRITE_SECURE_SETTINGS" />
<application>
<uses-library android:name="android.test.runner" />
diff --git a/services/tests/notification/src/com/android/server/notification/NotificationManagerServiceTest.java b/services/tests/notification/src/com/android/server/notification/NotificationManagerServiceTest.java
index e1c0166..40938fd 100644
--- a/services/tests/notification/src/com/android/server/notification/NotificationManagerServiceTest.java
+++ b/services/tests/notification/src/com/android/server/notification/NotificationManagerServiceTest.java
@@ -16,6 +16,7 @@
package com.android.server.notification;
+import static junit.framework.Assert.assertEquals;
import static junit.framework.Assert.assertTrue;
import static junit.framework.Assert.fail;
@@ -29,24 +30,29 @@
import static org.mockito.Mockito.when;
import android.app.INotificationManager;
-import android.app.IOnNotificationChannelCreatedListener;
import android.app.Notification;
import android.app.NotificationChannel;
import android.app.NotificationManager;
import android.content.Context;
import android.content.pm.ApplicationInfo;
import android.content.pm.IPackageManager;
+import android.content.pm.ParceledListSlice;
import android.os.Binder;
import android.os.Handler;
import android.os.UserHandle;
import android.service.notification.StatusBarNotification;
+import android.support.test.annotation.UiThreadTest;
import android.support.test.InstrumentationRegistry;
import android.support.test.runner.AndroidJUnit4;
import android.test.suitebuilder.annotation.SmallTest;
+import java.util.Arrays;
+import java.util.List;
import java.util.concurrent.CountDownLatch;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
+import com.android.server.lights.Light;
+import com.android.server.lights.LightsManager;
@SmallTest
@RunWith(AndroidJUnit4.class)
@@ -58,6 +64,7 @@
private IPackageManager mPackageManager = mock(IPackageManager.class);
@Before
+ @UiThreadTest
public void setUp() throws Exception {
final Context context = InstrumentationRegistry.getTargetContext();
mNotificationManagerService = new NotificationManagerService(context);
@@ -67,37 +74,32 @@
applicationInfo.uid = Binder.getCallingUid();
when(mPackageManager.getApplicationInfo(any(), anyInt(), anyInt()))
.thenReturn(applicationInfo);
- mNotificationManagerService.setPackageManager(mPackageManager);
- mNotificationManagerService.setHandler(new Handler(context.getMainLooper()));
+ final LightsManager mockLightsManager = mock(LightsManager.class);
+ when(mockLightsManager.getLight(anyInt())).thenReturn(mock(Light.class));
+ mNotificationManagerService.init(mPackageManager, mockLightsManager);
// Tests call directly into the Binder.
mBinderService = mNotificationManagerService.getBinderService();
}
@Test
- public void testCreateNotificationChannel_SuccessCallsListener() throws Exception {
+ @UiThreadTest
+ public void testCreateNotificationChannels_SingleChannel() throws Exception {
final NotificationChannel channel =
new NotificationChannel("id", "name", NotificationManager.IMPORTANCE_DEFAULT);
- mNotificationManagerService.setRankingHelper(mock(RankingHelper.class));
- final CountDownLatch latch = new CountDownLatch(1);
- mBinderService.createNotificationChannel("test_pkg", channel,
- new IOnNotificationChannelCreatedListener.Stub() {
- @Override public void onNotificationChannelCreated(
- NotificationChannel channel) {
- latch.countDown();
- }});
- latch.await();
+ mBinderService.createNotificationChannels("test_pkg",
+ new ParceledListSlice(Arrays.asList(channel)));
+ final NotificationChannel createdChannel =
+ mBinderService.getNotificationChannel("test_pkg", "id");
+ assertTrue(createdChannel != null);
}
@Test
- public void testCreateNotificationChannel_FailureDoesNotCallListener() throws Exception {
+ @UiThreadTest
+ public void testCreateNotificationChannels_NullChannelThrowsException() throws Exception {
try {
- mBinderService.createNotificationChannel("test_pkg", null,
- new IOnNotificationChannelCreatedListener.Stub() {
- @Override public void onNotificationChannelCreated(
- NotificationChannel channel) {
- fail("Listener was triggered from failure.");
- }});
+ mBinderService.createNotificationChannels("test_pkg",
+ new ParceledListSlice(Arrays.asList(null)));
fail("Exception should be thrown immediately.");
} catch (NullPointerException e) {
// pass
@@ -105,6 +107,54 @@
}
@Test
+ @UiThreadTest
+ public void testCreateNotificationChannels_TwoChannels() throws Exception {
+ final NotificationChannel channel1 =
+ new NotificationChannel("id1", "name", NotificationManager.IMPORTANCE_DEFAULT);
+ final NotificationChannel channel2 =
+ new NotificationChannel("id2", "name", NotificationManager.IMPORTANCE_DEFAULT);
+ mBinderService.createNotificationChannels("test_pkg",
+ new ParceledListSlice(Arrays.asList(channel1, channel2)));
+ assertTrue(mBinderService.getNotificationChannel("test_pkg", "id1") != null);
+ assertTrue(mBinderService.getNotificationChannel("test_pkg", "id2") != null);
+ }
+
+ @Test
+ @UiThreadTest
+ public void testCreateNotificationChannels_SecondCreateDoesNotChangeImportance()
+ throws Exception {
+ final NotificationChannel channel =
+ new NotificationChannel("id", "name", NotificationManager.IMPORTANCE_DEFAULT);
+ mBinderService.createNotificationChannels("test_pkg",
+ new ParceledListSlice(Arrays.asList(channel)));
+
+ // Recreating the channel doesn't throw, but ignores importance.
+ final NotificationChannel dupeChannel =
+ new NotificationChannel("id", "name", NotificationManager.IMPORTANCE_HIGH);
+ mBinderService.createNotificationChannels("test_pkg",
+ new ParceledListSlice(Arrays.asList(dupeChannel)));
+ final NotificationChannel createdChannel =
+ mBinderService.getNotificationChannel("test_pkg", "id");
+ assertEquals(NotificationManager.IMPORTANCE_DEFAULT, createdChannel.getImportance());
+ }
+
+ @Test
+ @UiThreadTest
+ public void testCreateNotificationChannels_IdenticalChannelsInListIgnoresSecond()
+ throws Exception {
+ final NotificationChannel channel1 =
+ new NotificationChannel("id", "name", NotificationManager.IMPORTANCE_DEFAULT);
+ final NotificationChannel channel2 =
+ new NotificationChannel("id", "name", NotificationManager.IMPORTANCE_HIGH);
+ mBinderService.createNotificationChannels("test_pkg",
+ new ParceledListSlice(Arrays.asList(channel1, channel2)));
+ final NotificationChannel createdChannel =
+ mBinderService.getNotificationChannel("test_pkg", "id");
+ assertEquals(NotificationManager.IMPORTANCE_DEFAULT, createdChannel.getImportance());
+ }
+
+ @Test
+ @UiThreadTest
public void testBlockedNotifications_suspended() throws Exception {
NotificationUsageStats usageStats = mock(NotificationUsageStats.class);
when(mPackageManager.isPackageSuspendedForUser(anyString(), anyInt())).thenReturn(true);
@@ -120,13 +170,14 @@
}
@Test
+ @UiThreadTest
public void testBlockedNotifications_blockedChannel() throws Exception {
NotificationUsageStats usageStats = mock(NotificationUsageStats.class);
when(mPackageManager.isPackageSuspendedForUser(anyString(), anyInt())).thenReturn(false);
NotificationChannel channel = new NotificationChannel("id", "name",
NotificationManager.IMPORTANCE_HIGH);
- channel.setAllowed(false);
+ channel.setImportance(NotificationManager.IMPORTANCE_NONE);
NotificationRecord r = generateNotificationRecord(channel);
NotificationManagerService.EnqueueNotificationRunnable enqueue =
mNotificationManagerService.new EnqueueNotificationRunnable(UserHandle.USER_SYSTEM,
@@ -136,6 +187,7 @@
}
@Test
+ @UiThreadTest
public void testBlockedNotifications_blockedApp() throws Exception {
NotificationUsageStats usageStats = mock(NotificationUsageStats.class);
when(mPackageManager.isPackageSuspendedForUser(anyString(), anyInt())).thenReturn(false);
diff --git a/services/tests/notification/src/com/android/server/notification/RankingHelperTest.java b/services/tests/notification/src/com/android/server/notification/RankingHelperTest.java
index 5696a72..f8061f6 100644
--- a/services/tests/notification/src/com/android/server/notification/RankingHelperTest.java
+++ b/services/tests/notification/src/com/android/server/notification/RankingHelperTest.java
@@ -488,25 +488,6 @@
}
@Test
- public void testUpdate_userLockedAllowed() throws Exception {
- final NotificationChannel channel =
- new NotificationChannel("id2", "name2", NotificationManager.IMPORTANCE_LOW);
- channel.setAllowed(true);
- channel.lockFields(NotificationChannel.USER_LOCKED_ALLOWED);
-
- mHelper.createNotificationChannel(pkg, uid, channel, false);
-
- final NotificationChannel channel2 =
- new NotificationChannel("id2", "name2", NotificationManager.IMPORTANCE_HIGH);
- channel2.setAllowed(false);
-
- mHelper.updateNotificationChannelFromAssistant(pkg, uid, channel2);
-
- // no fields should be changed
- assertEquals(channel, mHelper.getNotificationChannel(pkg, uid, channel.getId()));
- }
-
- @Test
public void testUpdate_userLockedBadge() throws Exception {
final NotificationChannel channel =
new NotificationChannel("id2", "name2", NotificationManager.IMPORTANCE_LOW);
@@ -567,7 +548,6 @@
channel.setBypassDnd(true);
channel.setLockscreenVisibility(Notification.VISIBILITY_SECRET);
channel.setShowBadge(true);
- channel.setAllowed(false);
int lockMask = 0;
for (int i = 0; i < NotificationChannel.LOCKABLE_FIELDS.length; i++) {
lockMask |= NotificationChannel.LOCKABLE_FIELDS[i];
@@ -583,7 +563,7 @@
assertEquals(channel.shouldShowLights(), savedChannel.shouldShowLights());
assertFalse(savedChannel.canBypassDnd());
assertFalse(Notification.VISIBILITY_SECRET == savedChannel.getLockscreenVisibility());
- assertFalse(savedChannel.canShowBadge());
+ assertEquals(channel.canShowBadge(), savedChannel.canShowBadge());
}
@Test
@@ -595,7 +575,6 @@
channel.setBypassDnd(true);
channel.setLockscreenVisibility(Notification.VISIBILITY_SECRET);
channel.setShowBadge(true);
- channel.setAllowed(false);
int lockMask = 0;
for (int i = 0; i < NotificationChannel.LOCKABLE_FIELDS.length; i++) {
lockMask |= NotificationChannel.LOCKABLE_FIELDS[i];
@@ -611,6 +590,6 @@
assertEquals(channel.shouldShowLights(), savedChannel.shouldShowLights());
assertFalse(savedChannel.canBypassDnd());
assertFalse(Notification.VISIBILITY_SECRET == savedChannel.getLockscreenVisibility());
- assertFalse(savedChannel.canShowBadge());
+ assertEquals(channel.canShowBadge(), savedChannel.canShowBadge());
}
}
diff --git a/services/tests/servicestests/Android.mk b/services/tests/servicestests/Android.mk
index 86983eb..f934d34 100644
--- a/services/tests/servicestests/Android.mk
+++ b/services/tests/servicestests/Android.mk
@@ -14,6 +14,7 @@
LOCAL_STATIC_JAVA_LIBRARIES := \
frameworks-base-testutils \
services.accessibility \
+ services.appwidget \
services.core \
services.devicepolicy \
services.net \
@@ -49,10 +50,7 @@
LOCAL_ADDITIONAL_DEPENDENCIES := $(LOCAL_PATH)/Android.mk
-# Code coverage puts us over the dex limit, so enable multi-dex for coverage-enabled builds
-ifeq (true,$(EMMA_INSTRUMENT))
LOCAL_JACK_FLAGS := --multi-dex native
-endif # EMMA_INSTRUMENT_STATIC
LOCAL_STATIC_JAVA_LIBRARIES += ub-uiautomator
diff --git a/services/tests/servicestests/AndroidManifest.xml b/services/tests/servicestests/AndroidManifest.xml
index 4165467..1c92e45 100644
--- a/services/tests/servicestests/AndroidManifest.xml
+++ b/services/tests/servicestests/AndroidManifest.xml
@@ -164,6 +164,13 @@
<activity android:name="com.android.server.am.TaskStackChangedListenerTest$ActivityTaskChangeCallbacks" />
<activity android:name="com.android.server.am.TaskStackChangedListenerTest$ActivityTaskDescriptionChange" />
+ <receiver android:name="com.android.server.appwidget.DummyAppWidget">
+ <intent-filter>
+ <action android:name="android.appwidget.action.APPWIDGET_UPDATE" />
+ </intent-filter>
+ <meta-data android:name="android.appwidget.provider"
+ android:resource="@xml/dummy_appwidget_info" />
+ </receiver>
</application>
<instrumentation
diff --git a/services/tests/servicestests/res/xml/dummy_appwidget_info.xml b/services/tests/servicestests/res/xml/dummy_appwidget_info.xml
new file mode 100644
index 0000000..c7144da
--- /dev/null
+++ b/services/tests/servicestests/res/xml/dummy_appwidget_info.xml
@@ -0,0 +1,24 @@
+<!--
+ ~ 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
+ -->
+
+<appwidget-provider xmlns:android="http://schemas.android.com/apk/res/android"
+ android:minWidth="40dp"
+ android:minHeight="40dp"
+ android:updatePeriodMillis="86400000"
+ android:previewImage="@drawable/icon1"
+ android:resizeMode="horizontal|vertical"
+ android:widgetCategory="home_screen">
+</appwidget-provider>
\ No newline at end of file
diff --git a/services/tests/servicestests/src/com/android/server/NetworkScoreServiceTest.java b/services/tests/servicestests/src/com/android/server/NetworkScoreServiceTest.java
index 69d27f2..9bb7bd1 100644
--- a/services/tests/servicestests/src/com/android/server/NetworkScoreServiceTest.java
+++ b/services/tests/servicestests/src/com/android/server/NetworkScoreServiceTest.java
@@ -53,6 +53,7 @@
import android.net.INetworkRecommendationProvider;
import android.net.INetworkScoreCache;
import android.net.NetworkKey;
+import android.net.NetworkScoreManager;
import android.net.NetworkScorerAppManager;
import android.net.NetworkScorerAppManager.NetworkScorerAppData;
import android.net.RecommendationRequest;
@@ -60,6 +61,7 @@
import android.net.ScoredNetwork;
import android.net.WifiKey;
import android.net.wifi.WifiConfiguration;
+import android.os.Binder;
import android.os.Bundle;
import android.os.IBinder;
import android.os.IRemoteCallback;
@@ -134,9 +136,10 @@
mNetworkScoreService.systemRunning();
- verify(mContext).bindServiceAsUser(MockUtils.checkIntent(new Intent().setComponent(
- new ComponentName(NEW_SCORER.packageName,
- NEW_SCORER.recommendationServiceClassName))),
+ verify(mContext).bindServiceAsUser(MockUtils.checkIntent(
+ new Intent(NetworkScoreManager.ACTION_RECOMMEND_NETWORKS)
+ .setComponent(new ComponentName(NEW_SCORER.packageName,
+ NEW_SCORER.recommendationServiceClassName))),
any(ServiceConnection.class),
eq(Context.BIND_AUTO_CREATE | Context.BIND_FOREGROUND_SERVICE),
eq(UserHandle.SYSTEM));
@@ -145,11 +148,11 @@
@Test
public void testRequestScores_noPermission() throws Exception {
doThrow(new SecurityException()).when(mContext)
- .enforceCallingOrSelfPermission(eq(permission.BROADCAST_NETWORK_PRIVILEGED),
+ .enforceCallingOrSelfPermission(eq(permission.REQUEST_NETWORK_SCORES),
anyString());
try {
mNetworkScoreService.requestScores(null);
- fail("BROADCAST_NETWORK_PRIVILEGED not enforced.");
+ fail("REQUEST_NETWORK_SCORES not enforced.");
} catch (SecurityException e) {
// expected
}
@@ -182,11 +185,11 @@
@Test
public void testRequestRecommendation_noPermission() throws Exception {
doThrow(new SecurityException()).when(mContext)
- .enforceCallingOrSelfPermission(eq(permission.BROADCAST_NETWORK_PRIVILEGED),
+ .enforceCallingOrSelfPermission(eq(permission.REQUEST_NETWORK_SCORES),
anyString());
try {
mNetworkScoreService.requestRecommendation(mRecommendationRequest);
- fail("BROADCAST_NETWORK_PRIVILEGED not enforced.");
+ fail("REQUEST_NETWORK_SCORES not enforced.");
} catch (SecurityException e) {
// expected
}
@@ -259,7 +262,7 @@
@Test
public void testUpdateScores_notActiveScorer() {
- when(mNetworkScorerAppManager.isCallerActiveScorer(anyInt())).thenReturn(false);
+ bindToScorer(false /*callerIsScorer*/);
try {
mNetworkScoreService.updateScores(new ScoredNetwork[0]);
@@ -271,7 +274,7 @@
@Test
public void testUpdateScores_oneRegisteredCache() throws RemoteException {
- when(mNetworkScorerAppManager.isCallerActiveScorer(anyInt())).thenReturn(true);
+ bindToScorer(true /*callerIsScorer*/);
mNetworkScoreService.registerNetworkScoreCache(NetworkKey.TYPE_WIFI,
mNetworkScoreCache, CACHE_FILTER_NONE);
@@ -286,7 +289,7 @@
@Test
public void testUpdateScores_twoRegisteredCaches() throws RemoteException {
- when(mNetworkScorerAppManager.isCallerActiveScorer(anyInt())).thenReturn(true);
+ bindToScorer(true /*callerIsScorer*/);
mNetworkScoreService.registerNetworkScoreCache(NetworkKey.TYPE_WIFI,
mNetworkScoreCache, CACHE_FILTER_NONE);
@@ -320,9 +323,9 @@
}
@Test
- public void testClearScores_notActiveScorer_noBroadcastNetworkPermission() {
- when(mNetworkScorerAppManager.isCallerActiveScorer(anyInt())).thenReturn(false);
- when(mContext.checkCallingOrSelfPermission(permission.BROADCAST_NETWORK_PRIVILEGED))
+ public void testClearScores_notActiveScorer_noRequestNetworkScoresPermission() {
+ bindToScorer(false /*callerIsScorer*/);
+ when(mContext.checkCallingOrSelfPermission(permission.REQUEST_NETWORK_SCORES))
.thenReturn(PackageManager.PERMISSION_DENIED);
try {
mNetworkScoreService.clearScores();
@@ -333,9 +336,9 @@
}
@Test
- public void testClearScores_activeScorer_noBroadcastNetworkPermission() {
- when(mNetworkScorerAppManager.isCallerActiveScorer(anyInt())).thenReturn(true);
- when(mContext.checkCallingOrSelfPermission(permission.BROADCAST_NETWORK_PRIVILEGED))
+ public void testClearScores_activeScorer_noRequestNetworkScoresPermission() {
+ bindToScorer(true /*callerIsScorer*/);
+ when(mContext.checkCallingOrSelfPermission(permission.REQUEST_NETWORK_SCORES))
.thenReturn(PackageManager.PERMISSION_DENIED);
mNetworkScoreService.clearScores();
@@ -343,7 +346,7 @@
@Test
public void testClearScores_activeScorer() throws RemoteException {
- when(mNetworkScorerAppManager.isCallerActiveScorer(anyInt())).thenReturn(true);
+ bindToScorer(true /*callerIsScorer*/);
mNetworkScoreService.registerNetworkScoreCache(NetworkKey.TYPE_WIFI, mNetworkScoreCache,
CACHE_FILTER_NONE);
@@ -353,10 +356,10 @@
}
@Test
- public void testClearScores_notActiveScorer_hasBroadcastNetworkPermission()
+ public void testClearScores_notActiveScorer_hasRequestNetworkScoresPermission()
throws RemoteException {
- when(mNetworkScorerAppManager.isCallerActiveScorer(anyInt())).thenReturn(false);
- when(mContext.checkCallingOrSelfPermission(permission.BROADCAST_NETWORK_PRIVILEGED))
+ bindToScorer(false /*callerIsScorer*/);
+ when(mContext.checkCallingOrSelfPermission(permission.REQUEST_NETWORK_SCORES))
.thenReturn(PackageManager.PERMISSION_GRANTED);
mNetworkScoreService.registerNetworkScoreCache(NetworkKey.TYPE_WIFI, mNetworkScoreCache,
@@ -380,9 +383,9 @@
}
@Test
- public void testDisableScoring_notActiveScorer_noBroadcastNetworkPermission() {
- when(mNetworkScorerAppManager.isCallerActiveScorer(anyInt())).thenReturn(false);
- when(mContext.checkCallingOrSelfPermission(permission.BROADCAST_NETWORK_PRIVILEGED))
+ public void testDisableScoring_notActiveScorer_noRequestNetworkScoresPermission() {
+ bindToScorer(false /*callerIsScorer*/);
+ when(mContext.checkCallingOrSelfPermission(permission.REQUEST_NETWORK_SCORES))
.thenReturn(PackageManager.PERMISSION_DENIED);
try {
@@ -394,9 +397,9 @@
}
@Test
- public void testRegisterNetworkScoreCache_noBroadcastNetworkPermission() {
+ public void testRegisterNetworkScoreCache_noRequestNetworkScoresPermission() {
doThrow(new SecurityException()).when(mContext).enforceCallingOrSelfPermission(
- eq(permission.BROADCAST_NETWORK_PRIVILEGED), anyString());
+ eq(permission.REQUEST_NETWORK_SCORES), anyString());
try {
mNetworkScoreService.registerNetworkScoreCache(
@@ -408,9 +411,9 @@
}
@Test
- public void testUnregisterNetworkScoreCache_noBroadcastNetworkPermission() {
+ public void testUnregisterNetworkScoreCache_noRequestNetworkScoresPermission() {
doThrow(new SecurityException()).when(mContext).enforceCallingOrSelfPermission(
- eq(permission.BROADCAST_NETWORK_PRIVILEGED), anyString());
+ eq(permission.REQUEST_NETWORK_SCORES), anyString());
try {
mNetworkScoreService.unregisterNetworkScoreCache(
@@ -446,6 +449,27 @@
assertFalse(stringWriter.toString().isEmpty());
}
+ @Test
+ public void testIsCallerActiveScorer_noBoundService() throws Exception {
+ mNetworkScoreService.systemRunning();
+
+ assertFalse(mNetworkScoreService.isCallerActiveScorer(Binder.getCallingUid()));
+ }
+
+ @Test
+ public void testIsCallerActiveScorer_boundServiceIsNotCaller() throws Exception {
+ bindToScorer(false /*callerIsScorer*/);
+
+ assertFalse(mNetworkScoreService.isCallerActiveScorer(Binder.getCallingUid()));
+ }
+
+ @Test
+ public void testIsCallerActiveScorer_boundServiceIsCaller() throws Exception {
+ bindToScorer(true /*callerIsScorer*/);
+
+ assertTrue(mNetworkScoreService.isCallerActiveScorer(Binder.getCallingUid()));
+ }
+
// "injects" the mock INetworkRecommendationProvider into the NetworkScoreService.
private void injectProvider() {
final ComponentName componentName = new ComponentName(NEW_SCORER.packageName,
@@ -465,4 +489,14 @@
});
mNetworkScoreService.systemRunning();
}
+
+ private void bindToScorer(boolean callerIsScorer) {
+ final int callingUid = callerIsScorer ? Binder.getCallingUid() : 0;
+ NetworkScorerAppData appData = new NetworkScorerAppData(NEW_SCORER.packageName,
+ callingUid, NEW_SCORER.recommendationServiceClassName);
+ when(mNetworkScorerAppManager.getActiveScorer()).thenReturn(appData);
+ when(mContext.bindServiceAsUser(isA(Intent.class), isA(ServiceConnection.class), anyInt(),
+ isA(UserHandle.class))).thenReturn(true);
+ mNetworkScoreService.systemRunning();
+ }
}
diff --git a/services/tests/servicestests/src/com/android/server/accessibility/AccessibilityCacheTest.java b/services/tests/servicestests/src/com/android/server/accessibility/AccessibilityCacheTest.java
index 9ccf290..ace65a6 100644
--- a/services/tests/servicestests/src/com/android/server/accessibility/AccessibilityCacheTest.java
+++ b/services/tests/servicestests/src/com/android/server/accessibility/AccessibilityCacheTest.java
@@ -17,12 +17,14 @@
package com.android.server.accessibility;
import static junit.framework.Assert.assertEquals;
+import static junit.framework.Assert.assertNotNull;
import static junit.framework.Assert.assertNull;
import static org.mockito.Matchers.anyBoolean;
import static org.mockito.Matchers.anyObject;
import static org.mockito.Mockito.doAnswer;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.never;
import static org.mockito.Mockito.when;
import android.support.test.runner.AndroidJUnit4;
@@ -479,6 +481,25 @@
AccessibilityEvent.CONTENT_CHANGE_TYPE_CONTENT_DESCRIPTION);
}
+ @Test
+ public void testCacheCriticalEventList_doesntLackEvents() {
+ for (int i = 0; i < 32; i++) {
+ int eventType = 1 << i;
+ if ((eventType & AccessibilityCache.CACHE_CRITICAL_EVENTS_MASK) == 0) {
+ try {
+ assertEventTypeClearsNode(eventType, false);
+ verify(mAccessibilityNodeRefresher, never())
+ .refreshNode(anyObject(), anyBoolean());
+ } catch (Throwable e) {
+ throw new AssertionError(
+ "Failed for eventType: " + AccessibilityEvent.eventTypeToString(
+ eventType),
+ e);
+ }
+ }
+ }
+ }
+
private void assertNodeIsRefreshedWithEventType(int eventType, int contentChangeTypes) {
AccessibilityNodeInfo nodeInfo = getNodeWithA11yAndWindowId(SINGLE_VIEW_ID, WINDOW_ID_1);
mAccessibilityCache.add(nodeInfo);
@@ -521,13 +542,28 @@
}
private void assertEventTypeClearsNode(int eventType) {
+ assertEventTypeClearsNode(eventType, true);
+ }
+
+ private void assertEventTypeClearsNode(int eventType, boolean clears) {
final int nodeId = 0xBEEF;
AccessibilityNodeInfo nodeInfo = getNodeWithA11yAndWindowId(nodeId, WINDOW_ID_1);
long id = nodeInfo.getSourceNodeId();
mAccessibilityCache.add(nodeInfo);
nodeInfo.recycle();
mAccessibilityCache.onAccessibilityEvent(AccessibilityEvent.obtain(eventType));
- assertNull(mAccessibilityCache.getNode(WINDOW_ID_1, id));
+ AccessibilityNodeInfo cachedNode = mAccessibilityCache.getNode(WINDOW_ID_1, id);
+ try {
+ if (clears) {
+ assertNull(cachedNode);
+ } else {
+ assertNotNull(cachedNode);
+ }
+ } finally {
+ if (cachedNode != null) {
+ cachedNode.recycle();
+ }
+ }
}
private AccessibilityNodeInfo getParentNode() {
diff --git a/services/tests/servicestests/src/com/android/server/appwidget/AppWidgetServiceImplTest.java b/services/tests/servicestests/src/com/android/server/appwidget/AppWidgetServiceImplTest.java
new file mode 100644
index 0000000..4886a5f
--- /dev/null
+++ b/services/tests/servicestests/src/com/android/server/appwidget/AppWidgetServiceImplTest.java
@@ -0,0 +1,129 @@
+/*
+ * 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.appwidget;
+
+import static org.mockito.Matchers.any;
+import static org.mockito.Matchers.anyInt;
+import static org.mockito.Matchers.anyString;
+import static org.mockito.Matchers.eq;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.times;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+import android.app.admin.DevicePolicyManagerInternal;
+import android.appwidget.AppWidgetManager;
+import android.appwidget.AppWidgetProviderInfo;
+import android.content.BroadcastReceiver;
+import android.content.ComponentName;
+import android.content.ContextWrapper;
+import android.content.Intent;
+import android.content.IntentFilter;
+import android.content.IntentSender;
+import android.content.pm.ShortcutServiceInternal;
+import android.os.Handler;
+import android.os.UserHandle;
+import android.test.InstrumentationTestCase;
+import android.test.suitebuilder.annotation.SmallTest;
+
+import com.android.server.LocalServices;
+
+import org.mockito.ArgumentCaptor;
+
+
+/**
+ * Tests for {@link AppWidgetManager} and {@link AppWidgetServiceImpl}.
+ *
+ m FrameworksServicesTests &&
+ adb install \
+ -r -g ${ANDROID_PRODUCT_OUT}/data/app/FrameworksServicesTests/FrameworksServicesTests.apk &&
+ adb shell am instrument -e class com.android.server.appwidget.AppWidgetServiceImplTest \
+ -w com.android.frameworks.servicestests/android.support.test.runner.AndroidJUnitRunner
+ */
+@SmallTest
+public class AppWidgetServiceImplTest extends InstrumentationTestCase {
+
+ private TestContext mTestContext;
+ private AppWidgetServiceImpl mService;
+ private AppWidgetManager mManager;
+
+ private ShortcutServiceInternal mMockShortcutService;
+
+ @Override
+ protected void setUp() throws Exception {
+ super.setUp();
+ LocalServices.removeServiceForTest(DevicePolicyManagerInternal.class);
+ LocalServices.removeServiceForTest(ShortcutServiceInternal.class);
+
+ mTestContext = new TestContext();
+ mService = new AppWidgetServiceImpl(mTestContext);
+ mManager = new AppWidgetManager(mTestContext, mService);
+
+ mMockShortcutService = mock(ShortcutServiceInternal.class);
+ LocalServices.addService(ShortcutServiceInternal.class, mMockShortcutService);
+
+ mService.onStart();
+ }
+
+ public void testRequestPinAppWidget_otherProvider() {
+ ComponentName otherProvider = null;
+ for (AppWidgetProviderInfo provider : mManager.getInstalledProviders()) {
+ if (!provider.provider.getPackageName().equals(mTestContext.getPackageName())) {
+ otherProvider = provider.provider;
+ break;
+ }
+ }
+ if (otherProvider == null) {
+ // No other provider found. Ignore this test.
+ }
+ assertFalse(mManager.requestPinAppWidget(otherProvider, null));
+ }
+
+ public void testRequestPinAppWidget() {
+ ComponentName provider = new ComponentName(mTestContext, DummyAppWidget.class);
+ // Set up users.
+ when(mMockShortcutService.requestPinAppWidget(anyString(),
+ any(AppWidgetProviderInfo.class), any(IntentSender.class), anyInt()))
+ .thenReturn(true);
+ assertTrue(mManager.requestPinAppWidget(provider, null));
+
+ final ArgumentCaptor<AppWidgetProviderInfo> providerCaptor =
+ ArgumentCaptor.forClass(AppWidgetProviderInfo.class);
+ verify(mMockShortcutService, times(1)).requestPinAppWidget(anyString(),
+ providerCaptor.capture(), eq(null), anyInt());
+ assertEquals(provider, providerCaptor.getValue().provider);
+ }
+
+ private class TestContext extends ContextWrapper {
+
+ public TestContext() {
+ super(getInstrumentation().getContext());
+ }
+
+ @Override
+ public Intent registerReceiverAsUser(BroadcastReceiver receiver, UserHandle user,
+ IntentFilter filter, String broadcastPermission, Handler scheduler) {
+ // ignore.
+ return null;
+ }
+
+ @Override
+ public void unregisterReceiver(BroadcastReceiver receiver) {
+ // ignore.
+ }
+ }
+}
diff --git a/services/tests/servicestests/src/com/android/server/appwidget/DummyAppWidget.java b/services/tests/servicestests/src/com/android/server/appwidget/DummyAppWidget.java
new file mode 100644
index 0000000..803119f4
--- /dev/null
+++ b/services/tests/servicestests/src/com/android/server/appwidget/DummyAppWidget.java
@@ -0,0 +1,31 @@
+/*
+ * 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.appwidget;
+
+import android.content.BroadcastReceiver;
+import android.content.Context;
+import android.content.Intent;
+
+/**
+ * Dummy widget for testing
+ */
+public class DummyAppWidget extends BroadcastReceiver {
+
+ @Override
+ public void onReceive(Context context, Intent intent) {
+ }
+}
diff --git a/services/tests/servicestests/src/com/android/server/devicepolicy/DevicePolicyManagerTest.java b/services/tests/servicestests/src/com/android/server/devicepolicy/DevicePolicyManagerTest.java
index 469dea5..182f045 100644
--- a/services/tests/servicestests/src/com/android/server/devicepolicy/DevicePolicyManagerTest.java
+++ b/services/tests/servicestests/src/com/android/server/devicepolicy/DevicePolicyManagerTest.java
@@ -1208,8 +1208,8 @@
);
verify(mContext.userManagerInternal).setDevicePolicyUserRestrictions(
eq(UserHandle.USER_SYSTEM),
- MockUtils.checkUserRestrictions(),
- MockUtils.checkUserRestrictions(defaultRestrictions)
+ MockUtils.checkUserRestrictions(defaultRestrictions),
+ MockUtils.checkUserRestrictions()
);
reset(mContext.userManagerInternal);
@@ -1479,8 +1479,8 @@
);
verify(mContext.userManagerInternal).setDevicePolicyUserRestrictions(
eq(UserHandle.USER_SYSTEM),
- MockUtils.checkUserRestrictions(),
- MockUtils.checkUserRestrictions(defaultRestrictions)
+ MockUtils.checkUserRestrictions(defaultRestrictions),
+ MockUtils.checkUserRestrictions()
);
reset(mContext.userManagerInternal);
@@ -1521,8 +1521,8 @@
);
verify(mContext.userManagerInternal, atLeast(1)).setDevicePolicyUserRestrictions(
eq(UserHandle.USER_SYSTEM),
- MockUtils.checkUserRestrictions(),
- MockUtils.checkUserRestrictions(newDefaultEnabledRestriction)
+ MockUtils.checkUserRestrictions(newDefaultEnabledRestriction),
+ MockUtils.checkUserRestrictions()
);
reset(mContext.userManagerInternal);
@@ -2289,6 +2289,11 @@
setUpPackageManagerForAdmin(admin1, mContext.binder.callingUid);
mContext.packageName = admin1.getPackageName();
+ final ComponentName adminDifferentPackage =
+ new ComponentName("another.package", "whatever.random.class");
+ final int ANOTHER_UID = UserHandle.getUid(DpmMockContext.CALLER_USER_HANDLE, 948);
+ setUpPackageManagerForFakeAdmin(adminDifferentPackage, ANOTHER_UID, admin2);
+
// COMP mode is allowed.
assertProvisioningAllowed(DevicePolicyManager.ACTION_PROVISION_MANAGED_PROFILE, true);
@@ -2304,12 +2309,66 @@
.thenReturn(UserManager.RESTRICTION_SOURCE_DEVICE_OWNER);
assertProvisioningAllowed(DevicePolicyManager.ACTION_PROVISION_MANAGED_PROFILE, true);
+ // But another app should not
+ mContext.binder.callingUid = ANOTHER_UID;
+ mContext.packageName = adminDifferentPackage.getPackageName();
+ assertProvisioningAllowed(DevicePolicyManager.ACTION_PROVISION_MANAGED_PROFILE, false);
+
// The DO should not be allowed to initiate provisioning if the restriction is set by
// another entity.
when(mContext.userManager.getUserRestrictionSource(
eq(UserManager.DISALLOW_ADD_MANAGED_PROFILE),
eq(UserHandle.getUserHandleForUid(mContext.binder.callingUid))))
.thenReturn(UserManager.RESTRICTION_SOURCE_SYSTEM);
+ mContext.binder.callingUid = DpmMockContext.CALLER_UID;
+ mContext.packageName = admin1.getPackageName();
+ assertProvisioningAllowed(DevicePolicyManager.ACTION_PROVISION_MANAGED_PROFILE, false);
+
+ mContext.binder.callingUid = ANOTHER_UID;
+ mContext.packageName = adminDifferentPackage.getPackageName();
+ assertProvisioningAllowed(DevicePolicyManager.ACTION_PROVISION_MANAGED_PROFILE, false);
+ }
+
+ public void testIsProvisioningAllowed_nonSplitUser_comp() throws Exception {
+ setDeviceOwner();
+ setup_nonSplitUser_afterDeviceSetup_primaryUser();
+ setUpPackageManagerForAdmin(admin1, DpmMockContext.CALLER_UID);
+
+ final ComponentName adminDifferentPackage =
+ new ComponentName("another.package", "whatever.class");
+ final int ANOTHER_UID = UserHandle.getUid(DpmMockContext.CALLER_USER_HANDLE, 948);
+ setUpPackageManagerForFakeAdmin(adminDifferentPackage, ANOTHER_UID, admin2);
+
+ final int MANAGED_PROFILE_USER_ID = 18;
+ final int MANAGED_PROFILE_ADMIN_UID = UserHandle.getUid(MANAGED_PROFILE_USER_ID, 1308);
+ addManagedProfile(admin1, MANAGED_PROFILE_ADMIN_UID, admin1);
+
+ when(mContext.userManager.canAddMoreManagedProfiles(DpmMockContext.CALLER_USER_HANDLE,
+ false /* we can't remove a managed profile */)).thenReturn(false);
+ when(mContext.userManager.canAddMoreManagedProfiles(DpmMockContext.CALLER_USER_HANDLE,
+ true)).thenReturn(true);
+
+ // We can delete the managed profile to create a new one, so provisioning is allowed.
+ mContext.packageName = admin1.getPackageName();
+ mContext.binder.callingUid = DpmMockContext.CALLER_UID;
+ assertProvisioningAllowed(DevicePolicyManager.ACTION_PROVISION_MANAGED_PROFILE, true);
+
+ mContext.packageName = adminDifferentPackage.getPackageName();
+ mContext.binder.callingUid = ANOTHER_UID;
+ assertProvisioningAllowed(DevicePolicyManager.ACTION_PROVISION_MANAGED_PROFILE, true);
+
+ when(mContext.userManager.hasUserRestriction(
+ eq(UserManager.DISALLOW_REMOVE_MANAGED_PROFILE),
+ eq(UserHandle.of(DpmMockContext.CALLER_USER_HANDLE))))
+ .thenReturn(true);
+
+ // Now, we can't remove the profile any more to create a new one.
+ mContext.packageName = admin1.getPackageName();
+ mContext.binder.callingUid = DpmMockContext.CALLER_UID;
+ assertProvisioningAllowed(DevicePolicyManager.ACTION_PROVISION_MANAGED_PROFILE, false);
+
+ mContext.packageName = adminDifferentPackage.getPackageName();
+ mContext.binder.callingUid = ANOTHER_UID;
assertProvisioningAllowed(DevicePolicyManager.ACTION_PROVISION_MANAGED_PROFILE, false);
}
diff --git a/services/tests/servicestests/src/com/android/server/devicepolicy/DpmMockContext.java b/services/tests/servicestests/src/com/android/server/devicepolicy/DpmMockContext.java
index 1247b2d..65255d9 100644
--- a/services/tests/servicestests/src/com/android/server/devicepolicy/DpmMockContext.java
+++ b/services/tests/servicestests/src/com/android/server/devicepolicy/DpmMockContext.java
@@ -16,6 +16,8 @@
package com.android.server.devicepolicy;
+import android.accounts.Account;
+import android.accounts.AccountManager;
import android.app.IActivityManager;
import android.app.NotificationManager;
import android.app.backup.IBackupManager;
@@ -273,6 +275,7 @@
public final SettingsForMock settings;
public final MockContentResolver contentResolver;
public final TelephonyManager telephonyManager;
+ public final AccountManager accountManager;
/** Note this is a partial mock, not a real mock. */
public final PackageManager packageManager;
@@ -315,6 +318,7 @@
wifiManager = mock(WifiManager.class);
settings = mock(SettingsForMock.class);
telephonyManager = mock(TelephonyManager.class);
+ accountManager = mock(AccountManager.class);
// Package manager is huge, so we use a partial mock instead.
packageManager = spy(context.getPackageManager());
@@ -375,6 +379,7 @@
}
}
);
+ when(accountManager.getAccountsAsUser(anyInt())).thenReturn(new Account[0]);
// Create a data directory.
final File dir = new File(dataDir, "user" + userId);
@@ -464,6 +469,8 @@
return powerManager;
case Context.WIFI_SERVICE:
return wifiManager;
+ case Context.ACCOUNT_SERVICE:
+ return accountManager;
}
throw new UnsupportedOperationException();
}
diff --git a/services/tests/servicestests/src/com/android/server/pm/BaseShortcutManagerTest.java b/services/tests/servicestests/src/com/android/server/pm/BaseShortcutManagerTest.java
index 6bc4c19..10ca902 100644
--- a/services/tests/servicestests/src/com/android/server/pm/BaseShortcutManagerTest.java
+++ b/services/tests/servicestests/src/com/android/server/pm/BaseShortcutManagerTest.java
@@ -404,7 +404,6 @@
@Override
boolean injectIsActivityEnabledAndExported(ComponentName activity, @UserIdInt int userId) {
- assertNotNull(activity);
return mEnabledActivityChecker.test(activity, userId);
}
@@ -441,7 +440,7 @@
}
@Override
- void injectSendIntentSender(IntentSender intent) {
+ void injectSendIntentSender(IntentSender intent, Intent extras) {
mContext.sendIntentSender(intent);
}
@@ -450,11 +449,6 @@
// During tests, WTF is fatal.
fail(message + " exception: " + th + "\n" + Log.getStackTraceString(th));
}
-
- @Override
- void verifyError() {
- fail("Verify error");
- }
}
/** ShortcutManager with injection override methods. */
diff --git a/services/tests/servicestests/src/com/android/server/pm/InstallerTest.java b/services/tests/servicestests/src/com/android/server/pm/InstallerTest.java
new file mode 100644
index 0000000..5ab9020
--- /dev/null
+++ b/services/tests/servicestests/src/com/android/server/pm/InstallerTest.java
@@ -0,0 +1,170 @@
+/*
+ * 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.pm;
+
+import android.content.pm.ApplicationInfo;
+import android.content.pm.PackageManager;
+import android.content.pm.PackageStats;
+import android.os.SystemClock;
+import android.os.UserHandle;
+import android.test.AndroidTestCase;
+import android.util.Log;
+
+import com.android.internal.util.ArrayUtils;
+
+import java.util.Arrays;
+
+public class InstallerTest extends AndroidTestCase {
+ private static final String TAG = "InstallerTest";
+
+ private Installer mInstaller;
+
+ private final Timer mManual = new Timer("Manual");
+ private final Timer mQuota = new Timer("Quota");
+
+ private static class Timer {
+ private final String mTitle;
+ private long mStart;
+ private long mTotal;
+
+ public Timer(String title) {
+ mTitle = title;
+ }
+
+ public void start() {
+ mStart = SystemClock.currentTimeMicro();
+ }
+
+ public void stop() {
+ mTotal += SystemClock.currentTimeMicro() - mStart;
+ }
+
+ public void reset() {
+ mStart = 0;
+ mTotal = 0;
+ }
+
+ @Override
+ public String toString() {
+ return mTitle + ": " + (mTotal / 1000) + "ms";
+ }
+ }
+
+ @Override
+ public void setUp() throws Exception {
+ mInstaller = new Installer(getContext());
+ mInstaller.onStart();
+ mManual.reset();
+ mQuota.reset();
+ }
+
+ @Override
+ public void tearDown() throws Exception {
+ Log.i(TAG, mManual.toString());
+ Log.i(TAG, mQuota.toString());
+ mInstaller = null;
+ }
+
+ public void testGetAppSize() throws Exception {
+ final PackageManager pm = getContext().getPackageManager();
+ for (ApplicationInfo app : pm.getInstalledApplications(0)) {
+ final int userId = UserHandle.getUserId(app.uid);
+ final int appId = UserHandle.getAppId(app.uid);
+
+ final String[] packageNames = pm.getPackagesForUid(app.uid);
+ final long[] ceDataInodes = new long[packageNames.length];
+ final String[] codePaths = new String[packageNames.length];
+
+ for (int i = 0; i < packageNames.length; i++) {
+ final ApplicationInfo info = pm.getApplicationInfo(packageNames[i], 0);
+ codePaths[i] = info.getCodePath();
+ }
+
+ final PackageStats stats = new PackageStats(app.packageName);
+ final PackageStats quotaStats = new PackageStats(app.packageName);
+
+ mManual.start();
+ mInstaller.getAppSize(app.volumeUuid, packageNames, userId, 0,
+ appId, ceDataInodes, codePaths, stats);
+ mManual.stop();
+
+ mQuota.start();
+ mInstaller.getAppSize(app.volumeUuid, packageNames, userId, Installer.FLAG_USE_QUOTA,
+ appId, ceDataInodes, codePaths, quotaStats);
+ mQuota.stop();
+
+ checkEquals(Arrays.toString(packageNames) + " UID=" + app.uid, stats, quotaStats);
+ }
+ }
+
+ public void testGetUserSize() throws Exception {
+ int[] appIds = null;
+
+ final PackageManager pm = getContext().getPackageManager();
+ for (ApplicationInfo app : pm.getInstalledApplications(0)) {
+ final int appId = UserHandle.getAppId(app.uid);
+ if (!ArrayUtils.contains(appIds, appId)) {
+ appIds = ArrayUtils.appendInt(appIds, appId);
+ }
+ }
+
+ final PackageStats stats = new PackageStats("android");
+ final PackageStats quotaStats = new PackageStats("android");
+
+ mManual.start();
+ mInstaller.getUserSize(null, UserHandle.USER_SYSTEM, 0,
+ appIds, stats);
+ mManual.stop();
+
+ mQuota.start();
+ mInstaller.getUserSize(null, UserHandle.USER_SYSTEM, Installer.FLAG_USE_QUOTA,
+ appIds, quotaStats);
+ mQuota.stop();
+
+ checkEquals(Arrays.toString(appIds), stats, quotaStats);
+ }
+
+ public void testGetExternalSize() throws Exception {
+ mManual.start();
+ final long[] stats = mInstaller.getExternalSize(null, UserHandle.USER_SYSTEM, 0);
+ mManual.stop();
+
+ mQuota.start();
+ final long[] quotaStats = mInstaller.getExternalSize(null, UserHandle.USER_SYSTEM,
+ Installer.FLAG_USE_QUOTA);
+ mQuota.stop();
+
+ for (int i = 0; i < stats.length; i++) {
+ checkEquals("#" + i, stats[i], quotaStats[i]);
+ }
+ }
+
+ private static void checkEquals(String msg, PackageStats a, PackageStats b) {
+ checkEquals(msg + " codeSize", a.codeSize, b.codeSize);
+ checkEquals(msg + " dataSize", a.dataSize, b.dataSize);
+ checkEquals(msg + " cacheSize", a.cacheSize, b.cacheSize);
+ checkEquals(msg + " externalCodeSize", a.externalCodeSize, b.externalCodeSize);
+ checkEquals(msg + " externalDataSize", a.externalDataSize, b.externalDataSize);
+ checkEquals(msg + " externalCacheSize", a.externalCacheSize, b.externalCacheSize);
+ }
+
+ private static void checkEquals(String msg, long expected, long actual) {
+ if (expected != actual) {
+ Log.e(TAG, msg + " expected " + expected + " actual " + actual);
+ }
+ }
+}
diff --git a/services/tests/servicestests/src/com/android/server/pm/PackageParserTest.java b/services/tests/servicestests/src/com/android/server/pm/PackageParserTest.java
index 84bb4e8..e30bd5d 100644
--- a/services/tests/servicestests/src/com/android/server/pm/PackageParserTest.java
+++ b/services/tests/servicestests/src/com/android/server/pm/PackageParserTest.java
@@ -15,14 +15,37 @@
*/
package com.android.server.pm;
+import android.annotation.TestApi;
+import android.content.pm.ActivityInfo;
+import android.content.pm.ApplicationInfo;
+import android.content.pm.ConfigurationInfo;
+import android.content.pm.FeatureGroupInfo;
+import android.content.pm.FeatureInfo;
+import android.content.pm.InstrumentationInfo;
import android.content.pm.PackageParser;
+import android.content.pm.ProviderInfo;
+import android.content.pm.ServiceInfo;
+import android.content.pm.Signature;
+import android.os.Bundle;
+import android.os.Parcel;
import android.support.test.runner.AndroidJUnit4;
import android.test.suitebuilder.annotation.MediumTest;
import java.io.File;
+import java.lang.reflect.Array;
+import java.lang.reflect.Field;
import java.nio.charset.StandardCharsets;
+import java.security.cert.Certificate;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
import static org.junit.Assert.*;
+
+import android.util.ArrayMap;
+import android.util.ArraySet;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
@@ -87,6 +110,36 @@
assertEquals("android", pkg.packageName);
}
+ @Test
+ public void test_serializePackage() throws Exception {
+ PackageParser pp = new PackageParser();
+ pp.setCacheDir(mTmpDir);
+
+ PackageParser.Package pkg = pp.parsePackage(FRAMEWORK, 0 /* parseFlags */,
+ true /* useCaches */);
+
+ Parcel p = Parcel.obtain();
+ pkg.writeToParcel(p, 0 /* flags */);
+
+ p.setDataPosition(0);
+ PackageParser.Package deserialized = new PackageParser.Package(p);
+
+ assertPackagesEqual(pkg, deserialized);
+ }
+
+ @Test
+ public void test_roundTripKnownFields() throws Exception {
+ PackageParser.Package pkg = new PackageParser.Package("foo");
+ setKnownFields(pkg);
+
+ Parcel p = Parcel.obtain();
+ pkg.writeToParcel(p, 0 /* flags */);
+
+ p.setDataPosition(0);
+ PackageParser.Package deserialized = new PackageParser.Package(p);
+ assertAllFieldsExist(deserialized);
+ }
+
/**
* A trivial subclass of package parser that only caches the package name, and throws away
* all other information.
@@ -102,4 +155,375 @@
return new Package(new String(cacheEntry, StandardCharsets.UTF_8));
}
}
+
+ // NOTE: The equality assertions below are based on code autogenerated by IntelliJ.
+
+ public static void assertPackagesEqual(PackageParser.Package a, PackageParser.Package b) {
+ assertEquals(a.baseRevisionCode, b.baseRevisionCode);
+ assertEquals(a.baseHardwareAccelerated, b.baseHardwareAccelerated);
+ assertEquals(a.mVersionCode, b.mVersionCode);
+ assertEquals(a.mSharedUserLabel, b.mSharedUserLabel);
+ assertEquals(a.mPreferredOrder, b.mPreferredOrder);
+ assertEquals(a.installLocation, b.installLocation);
+ assertEquals(a.coreApp, b.coreApp);
+ assertEquals(a.mRequiredForAllUsers, b.mRequiredForAllUsers);
+ assertEquals(a.mOverlayPriority, b.mOverlayPriority);
+ assertEquals(a.mTrustedOverlay, b.mTrustedOverlay);
+ assertEquals(a.use32bitAbi, b.use32bitAbi);
+ assertEquals(a.packageName, b.packageName);
+ assertTrue(Arrays.equals(a.splitNames, b.splitNames));
+ assertEquals(a.volumeUuid, b.volumeUuid);
+ assertEquals(a.codePath, b.codePath);
+ assertEquals(a.baseCodePath, b.baseCodePath);
+ assertTrue(Arrays.equals(a.splitCodePaths, b.splitCodePaths));
+ assertTrue(Arrays.equals(a.splitRevisionCodes, b.splitRevisionCodes));
+ assertTrue(Arrays.equals(a.splitFlags, b.splitFlags));
+ assertTrue(Arrays.equals(a.splitPrivateFlags, b.splitPrivateFlags));
+ assertApplicationInfoEqual(a.applicationInfo, b.applicationInfo);
+
+ assertEquals(a.permissions.size(), b.permissions.size());
+ for (int i = 0; i < a.permissions.size(); ++i) {
+ assertPermissionsEqual(a.permissions.get(i), b.permissions.get(i));
+ assertSame(a.permissions.get(i).owner, a);
+ assertSame(b.permissions.get(i).owner, b);
+ }
+
+ assertEquals(a.permissionGroups.size(), b.permissionGroups.size());
+ for (int i = 0; i < a.permissionGroups.size(); ++i) {
+ assertPermissionGroupsEqual(a.permissionGroups.get(i), b.permissionGroups.get(i));
+ }
+
+ assertEquals(a.activities.size(), b.activities.size());
+ for (int i = 0; i < a.activities.size(); ++i) {
+ assertActivitiesEqual(a.activities.get(i), b.activities.get(i));
+ }
+
+ assertEquals(a.receivers.size(), b.receivers.size());
+ for (int i = 0; i < a.receivers.size(); ++i) {
+ assertActivitiesEqual(a.receivers.get(i), b.receivers.get(i));
+ }
+
+ assertEquals(a.providers.size(), b.providers.size());
+ for (int i = 0; i < a.providers.size(); ++i) {
+ assertProvidersEqual(a.providers.get(i), b.providers.get(i));
+ }
+
+ assertEquals(a.services.size(), b.services.size());
+ for (int i = 0; i < a.services.size(); ++i) {
+ assertServicesEqual(a.services.get(i), b.services.get(i));
+ }
+
+ assertEquals(a.instrumentation.size(), b.instrumentation.size());
+ for (int i = 0; i < a.instrumentation.size(); ++i) {
+ assertInstrumentationEqual(a.instrumentation.get(i), b.instrumentation.get(i));
+ }
+
+ assertEquals(a.requestedPermissions, b.requestedPermissions);
+ assertEquals(a.protectedBroadcasts, b.protectedBroadcasts);
+ assertEquals(a.parentPackage, b.parentPackage);
+ assertEquals(a.childPackages, b.childPackages);
+ assertEquals(a.libraryNames, b.libraryNames);
+ assertEquals(a.usesLibraries, b.usesLibraries);
+ assertEquals(a.usesOptionalLibraries, b.usesOptionalLibraries);
+ assertTrue(Arrays.equals(a.usesLibraryFiles, b.usesLibraryFiles));
+ assertEquals(a.mOriginalPackages, b.mOriginalPackages);
+ assertEquals(a.mRealPackage, b.mRealPackage);
+ assertEquals(a.mAdoptPermissions, b.mAdoptPermissions);
+ assertBundleApproximateEquals(a.mAppMetaData, b.mAppMetaData);
+ assertEquals(a.mVersionName, b.mVersionName);
+ assertEquals(a.mSharedUserId, b.mSharedUserId);
+ assertTrue(Arrays.equals(a.mSignatures, b.mSignatures));
+ assertTrue(Arrays.equals(a.mCertificates, b.mCertificates));
+ assertTrue(Arrays.equals(a.mLastPackageUsageTimeInMills, b.mLastPackageUsageTimeInMills));
+ assertEquals(a.mExtras, b.mExtras);
+ assertEquals(a.mRestrictedAccountType, b.mRestrictedAccountType);
+ assertEquals(a.mRequiredAccountType, b.mRequiredAccountType);
+ assertEquals(a.mOverlayTarget, b.mOverlayTarget);
+ assertEquals(a.mSigningKeys, b.mSigningKeys);
+ assertEquals(a.mUpgradeKeySets, b.mUpgradeKeySets);
+ assertEquals(a.mKeySetMapping, b.mKeySetMapping);
+ assertEquals(a.cpuAbiOverride, b.cpuAbiOverride);
+ assertTrue(Arrays.equals(a.restrictUpdateHash, b.restrictUpdateHash));
+ }
+
+ private static void assertBundleApproximateEquals(Bundle a, Bundle b) {
+ if (a == b) {
+ return;
+ }
+
+ // Force the bundles to be unparceled.
+ a.getBoolean("foo");
+ b.getBoolean("foo");
+
+ assertEquals(a.toString(), b.toString());
+ }
+
+ private static void assertComponentsEqual(PackageParser.Component<?> a,
+ PackageParser.Component<?> b) {
+ assertEquals(a.className, b.className);
+ assertBundleApproximateEquals(a.metaData, b.metaData);
+ assertEquals(a.getComponentName(), b.getComponentName());
+
+ if (a.intents != null && b.intents != null) {
+ assertEquals(a.intents.size(), b.intents.size());
+ } else if (a.intents == null || b.intents == null) {
+ return;
+ }
+
+ for (int i = 0; i < a.intents.size(); ++i) {
+ PackageParser.IntentInfo aIntent = a.intents.get(i);
+ PackageParser.IntentInfo bIntent = b.intents.get(i);
+
+ assertEquals(aIntent.hasDefault, bIntent.hasDefault);
+ assertEquals(aIntent.labelRes, bIntent.labelRes);
+ assertEquals(aIntent.nonLocalizedLabel, bIntent.nonLocalizedLabel);
+ assertEquals(aIntent.icon, bIntent.icon);
+ assertEquals(aIntent.logo, bIntent.logo);
+ assertEquals(aIntent.banner, bIntent.banner);
+ assertEquals(aIntent.preferred, bIntent.preferred);
+ }
+ }
+
+ private static void assertPermissionsEqual(PackageParser.Permission a,
+ PackageParser.Permission b) {
+ assertComponentsEqual(a, b);
+ assertEquals(a.tree, b.tree);
+
+ // Verify basic flags in PermissionInfo to make sure they're consistent. We don't perform
+ // a full structural equality here because the code that serializes them isn't parser
+ // specific and is tested elsewhere.
+ assertEquals(a.info.protectionLevel, b.info.protectionLevel);
+ assertEquals(a.info.group, b.info.group);
+ assertEquals(a.info.flags, b.info.flags);
+
+ if (a.group != null && b.group != null) {
+ assertPermissionGroupsEqual(a.group, b.group);
+ } else if (a.group != null || b.group != null) {
+ throw new AssertionError();
+ }
+ }
+
+ private static void assertInstrumentationEqual(PackageParser.Instrumentation a,
+ PackageParser.Instrumentation b) {
+ assertComponentsEqual(a, b);
+
+ // Sanity check for InstrumentationInfo.
+ assertEquals(a.info.targetPackage, b.info.targetPackage);
+ assertEquals(a.info.sourceDir, b.info.sourceDir);
+ assertEquals(a.info.publicSourceDir, b.info.publicSourceDir);
+ }
+
+ private static void assertServicesEqual(PackageParser.Service a, PackageParser.Service b) {
+ assertComponentsEqual(a, b);
+
+ // Sanity check for ServiceInfo.
+ assertApplicationInfoEqual(a.info.applicationInfo, b.info.applicationInfo);
+ assertEquals(a.info.name, b.info.name);
+ }
+
+ private static void assertProvidersEqual(PackageParser.Provider a, PackageParser.Provider b) {
+ assertComponentsEqual(a, b);
+
+ // Sanity check for ProviderInfo
+ assertApplicationInfoEqual(a.info.applicationInfo, b.info.applicationInfo);
+ assertEquals(a.info.name, b.info.name);
+ }
+
+ private static void assertActivitiesEqual(PackageParser.Activity a, PackageParser.Activity b) {
+ assertComponentsEqual(a, b);
+
+ // Sanity check for ActivityInfo.
+ assertApplicationInfoEqual(a.info.applicationInfo, b.info.applicationInfo);
+ assertEquals(a.info.name, b.info.name);
+ }
+
+ private static void assertPermissionGroupsEqual(PackageParser.PermissionGroup a,
+ PackageParser.PermissionGroup b) {
+ assertComponentsEqual(a, b);
+
+ // Sanity check for PermissionGroupInfo.
+ assertEquals(a.info.name, b.info.name);
+ assertEquals(a.info.descriptionRes, b.info.descriptionRes);
+ }
+
+ private static void assertApplicationInfoEqual(ApplicationInfo a, ApplicationInfo that) {
+ assertEquals(a.descriptionRes, that.descriptionRes);
+ assertEquals(a.theme, that.theme);
+ assertEquals(a.fullBackupContent, that.fullBackupContent);
+ assertEquals(a.uiOptions, that.uiOptions);
+ assertEquals(a.flags, that.flags);
+ assertEquals(a.privateFlags, that.privateFlags);
+ assertEquals(a.requiresSmallestWidthDp, that.requiresSmallestWidthDp);
+ assertEquals(a.compatibleWidthLimitDp, that.compatibleWidthLimitDp);
+ assertEquals(a.largestWidthLimitDp, that.largestWidthLimitDp);
+ assertEquals(a.nativeLibraryRootRequiresIsa, that.nativeLibraryRootRequiresIsa);
+ assertEquals(a.uid, that.uid);
+ assertEquals(a.minSdkVersion, that.minSdkVersion);
+ assertEquals(a.targetSdkVersion, that.targetSdkVersion);
+ assertEquals(a.versionCode, that.versionCode);
+ assertEquals(a.enabled, that.enabled);
+ assertEquals(a.enabledSetting, that.enabledSetting);
+ assertEquals(a.installLocation, that.installLocation);
+ assertEquals(a.networkSecurityConfigRes, that.networkSecurityConfigRes);
+ assertEquals(a.taskAffinity, that.taskAffinity);
+ assertEquals(a.permission, that.permission);
+ assertEquals(a.processName, that.processName);
+ assertEquals(a.className, that.className);
+ assertEquals(a.manageSpaceActivityName, that.manageSpaceActivityName);
+ assertEquals(a.backupAgentName, that.backupAgentName);
+ assertEquals(a.volumeUuid, that.volumeUuid);
+ assertEquals(a.scanSourceDir, that.scanSourceDir);
+ assertEquals(a.scanPublicSourceDir, that.scanPublicSourceDir);
+ assertEquals(a.sourceDir, that.sourceDir);
+ assertEquals(a.publicSourceDir, that.publicSourceDir);
+ assertTrue(Arrays.equals(a.splitSourceDirs, that.splitSourceDirs));
+ assertTrue(Arrays.equals(a.splitPublicSourceDirs, that.splitPublicSourceDirs));
+ assertTrue(Arrays.equals(a.resourceDirs, that.resourceDirs));
+ assertEquals(a.seinfo, that.seinfo);
+ assertTrue(Arrays.equals(a.sharedLibraryFiles, that.sharedLibraryFiles));
+ assertEquals(a.dataDir, that.dataDir);
+ assertEquals(a.deviceProtectedDataDir, that.deviceProtectedDataDir);
+ assertEquals(a.deviceEncryptedDataDir, that.deviceEncryptedDataDir);
+ assertEquals(a.credentialProtectedDataDir, that.credentialProtectedDataDir);
+ assertEquals(a.credentialEncryptedDataDir, that.credentialEncryptedDataDir);
+ assertEquals(a.nativeLibraryDir, that.nativeLibraryDir);
+ assertEquals(a.secondaryNativeLibraryDir, that.secondaryNativeLibraryDir);
+ assertEquals(a.nativeLibraryRootDir, that.nativeLibraryRootDir);
+ assertEquals(a.primaryCpuAbi, that.primaryCpuAbi);
+ assertEquals(a.secondaryCpuAbi, that.secondaryCpuAbi);
+ }
+
+ public static void setKnownFields(PackageParser.Package pkg) {
+ pkg.baseRevisionCode = 100;
+ pkg.baseHardwareAccelerated = true;
+ pkg.mVersionCode = 100;
+ pkg.mSharedUserLabel = 100;
+ pkg.mPreferredOrder = 100;
+ pkg.installLocation = 100;
+ pkg.coreApp = true;
+ pkg.mRequiredForAllUsers = true;
+ pkg.mOverlayPriority = 100;
+ pkg.mTrustedOverlay = true;
+ pkg.use32bitAbi = true;
+ pkg.packageName = "foo";
+ pkg.splitNames = new String[] { "foo" };
+ pkg.volumeUuid = "foo";
+ pkg.codePath = "foo";
+ pkg.baseCodePath = "foo";
+ pkg.splitCodePaths = new String[] { "foo" };
+ pkg.splitRevisionCodes = new int[] { 100 };
+ pkg.splitFlags = new int[] { 100 };
+ pkg.splitPrivateFlags = new int[] { 100 };
+ pkg.applicationInfo = new ApplicationInfo();
+
+ pkg.permissions.add(new PackageParser.Permission(pkg));
+ pkg.permissionGroups.add(new PackageParser.PermissionGroup(pkg));
+
+ final PackageParser.ParseComponentArgs dummy = new PackageParser.ParseComponentArgs(
+ pkg, new String[1], 0, 0, 0, 0, 0, 0, null, 0, 0, 0);
+
+ pkg.activities.add(new PackageParser.Activity(dummy, new ActivityInfo()));
+ pkg.receivers.add(new PackageParser.Activity(dummy, new ActivityInfo()));
+ pkg.providers.add(new PackageParser.Provider(dummy, new ProviderInfo()));
+ pkg.services.add(new PackageParser.Service(dummy, new ServiceInfo()));
+ pkg.instrumentation.add(new PackageParser.Instrumentation(dummy, new InstrumentationInfo()));
+ pkg.requestedPermissions.add("foo");
+
+ pkg.protectedBroadcasts = new ArrayList<>();
+ pkg.protectedBroadcasts.add("foo");
+
+ pkg.parentPackage = new PackageParser.Package("foo");
+
+ pkg.childPackages = new ArrayList<>();
+ pkg.childPackages.add(new PackageParser.Package("bar"));
+
+ pkg.libraryNames = new ArrayList<>();
+ pkg.libraryNames.add("foo");
+
+ pkg.usesLibraries = new ArrayList<>();
+ pkg.usesLibraries.add("foo");
+
+ pkg.usesOptionalLibraries = new ArrayList<>();
+ pkg.usesOptionalLibraries.add("foo");
+
+ pkg.usesLibraryFiles = new String[] { "foo "};
+
+ pkg.mOriginalPackages = new ArrayList<>();
+ pkg.mOriginalPackages.add("foo");
+
+ pkg.mRealPackage = "foo";
+
+ pkg.mAdoptPermissions = new ArrayList<>();
+ pkg.mAdoptPermissions.add("foo");
+
+ pkg.mAppMetaData = new Bundle();
+ pkg.mVersionName = "foo";
+ pkg.mSharedUserId = "foo";
+ pkg.mSignatures = new Signature[] { new Signature(new byte[16]) };
+ pkg.mCertificates = new Certificate[][] { new Certificate[] { null }};
+ pkg.mExtras = new Bundle();
+ pkg.mRestrictedAccountType = "foo";
+ pkg.mRequiredAccountType = "foo";
+ pkg.mOverlayTarget = "foo";
+ pkg.mSigningKeys = new ArraySet<>();
+ pkg.mUpgradeKeySets = new ArraySet<>();
+ pkg.mKeySetMapping = new ArrayMap<>();
+ pkg.cpuAbiOverride = "foo";
+ pkg.restrictUpdateHash = new byte[16];
+
+ pkg.preferredActivityFilters = new ArrayList<>();
+ pkg.preferredActivityFilters.add(new PackageParser.ActivityIntentInfo(
+ new PackageParser.Activity(dummy, new ActivityInfo())));
+
+ pkg.configPreferences = new ArrayList<>();
+ pkg.configPreferences.add(new ConfigurationInfo());
+
+ pkg.reqFeatures = new ArrayList<>();
+ pkg.reqFeatures.add(new FeatureInfo());
+
+ pkg.featureGroups = new ArrayList<>();
+ pkg.featureGroups.add(new FeatureGroupInfo());
+ }
+
+ private static void assertAllFieldsExist(PackageParser.Package pkg) throws Exception {
+ Field[] fields = PackageParser.Package.class.getDeclaredFields();
+
+ Set<String> nonSerializedFields = new HashSet<>();
+ nonSerializedFields.add("mExtras");
+ nonSerializedFields.add("packageUsageTimeMillis");
+
+ for (Field f : fields) {
+ final Class<?> fieldType = f.getType();
+
+ if (nonSerializedFields.contains(f.getName())) {
+ continue;
+ }
+
+ if (List.class.isAssignableFrom(fieldType)) {
+ // Sanity check for list fields: Assume they're non-null and contain precisely
+ // one element.
+ List<?> list = (List<?>) f.get(pkg);
+ assertNotNull(list);
+ assertEquals(1, list.size());
+ } else if (fieldType.getComponentType() != null) {
+ // Sanity check for array fields: Assume they're non-null and contain precisely
+ // one element.
+ Object array = f.get(pkg);
+ assertNotNull(Array.get(array, 0));
+ } else if (fieldType == String.class) {
+ // String fields: Check that they're set to "foo".
+ String value = (String) f.get(pkg);
+ assertEquals("foo", value);
+ } else if (fieldType == int.class) {
+ // int fields: Check that they're set to 100.
+ int value = (int) f.get(pkg);
+ assertEquals(100, value);
+ } else {
+ // All other fields: Check that they're set.
+ Object o = f.get(pkg);
+ assertNotNull("Field was null: " + f.getName(), o);
+ }
+ }
+ }
}
+
diff --git a/services/tests/servicestests/src/com/android/server/pm/ParallelPackageParserTest.java b/services/tests/servicestests/src/com/android/server/pm/ParallelPackageParserTest.java
index d165b8b..6c6eb7e 100644
--- a/services/tests/servicestests/src/com/android/server/pm/ParallelPackageParserTest.java
+++ b/services/tests/servicestests/src/com/android/server/pm/ParallelPackageParserTest.java
@@ -69,7 +69,7 @@
class TestParallelPackageParser extends ParallelPackageParser {
TestParallelPackageParser() {
- super(null, false, null);
+ super(null, false, null, null);
}
@Override
diff --git a/services/tests/servicestests/src/com/android/server/pm/ShortcutManagerTest1.java b/services/tests/servicestests/src/com/android/server/pm/ShortcutManagerTest1.java
index 97bcaf0..74c1ca5 100644
--- a/services/tests/servicestests/src/com/android/server/pm/ShortcutManagerTest1.java
+++ b/services/tests/servicestests/src/com/android/server/pm/ShortcutManagerTest1.java
@@ -1292,43 +1292,7 @@
/* activity =*/ null, /* flags */ 0), getCallingUser());
});
- // Make sure floating shortcuts don't match with an activity.
- // At this point, s1 is dynamic and pinned, so it still has a target activity.
- runWithCaller(LAUNCHER_1, USER_0, () -> {
- assertWith(mLauncherApps.getShortcuts(buildQuery(
- /* time =*/ 0,
- CALLING_PACKAGE_2,
- /* activity =*/ new ComponentName(CALLING_PACKAGE_2,
- ShortcutActivity2.class.getName()),
- ShortcutQuery.FLAG_GET_PINNED),
- getCallingUser()))
- .haveIds("s3")
- .areAllPinned()
- .areAllDynamic()
- .areAllWithActivity(new ComponentName(CALLING_PACKAGE_2,
- ShortcutActivity2.class.getName()));
- });
-
- // Now remove as a dynamic, making it floating.
- runWithCaller(CALLING_PACKAGE_2, USER_0, () -> {
- mManager.removeDynamicShortcuts(list("s3"));
- assertWith(mManager.getPinnedShortcuts())
- .selectFloating()
- .areAllWithNoActivity();
- });
-
- runWithCaller(LAUNCHER_1, USER_0, () -> {
- // This shouldn't match now.
- assertWith(mLauncherApps.getShortcuts(buildQuery(
- /* time =*/ 0,
- CALLING_PACKAGE_2,
- /* activity =*/ new ComponentName(CALLING_PACKAGE_2,
- ShortcutActivity2.class.getName()),
- ShortcutQuery.FLAG_GET_PINNED),
- getCallingUser()))
- .isEmpty();
- });
-
+ // TODO More tests: pinned but dynamic.
}
public void testGetShortcuts_shortcutKinds() throws Exception {
diff --git a/services/tests/servicestests/src/com/android/server/pm/ShortcutManagerTest2.java b/services/tests/servicestests/src/com/android/server/pm/ShortcutManagerTest2.java
index 7486858..d25923c 100644
--- a/services/tests/servicestests/src/com/android/server/pm/ShortcutManagerTest2.java
+++ b/services/tests/servicestests/src/com/android/server/pm/ShortcutManagerTest2.java
@@ -1052,7 +1052,7 @@
assertEquals(CALLING_PACKAGE_1, si.getPackage());
assertEquals("id", si.getId());
- assertNull(si.getActivity()); // It's now floating, so no target activity.
+ assertEquals(ShortcutActivity2.class.getName(), si.getActivity().getClassName());
assertEquals(null, si.getIcon());
assertEquals("title", si.getTitle());
assertEquals("text", si.getText());
@@ -1116,7 +1116,7 @@
assertEquals(CALLING_PACKAGE_1, si.getPackage());
assertEquals("id", si.getId());
- assertNull(si.getActivity()); // It's now floating, so no target activity.
+ assertEquals(ShortcutActivity2.class.getName(), si.getActivity().getClassName());
assertEquals(null, si.getIcon());
assertEquals(10, si.getTitleResId());
assertEquals("r10", si.getTitleResName());
diff --git a/services/tests/servicestests/src/com/android/server/pm/ShortcutManagerTest9.java b/services/tests/servicestests/src/com/android/server/pm/ShortcutManagerTest9.java
new file mode 100644
index 0000000..84a7c19
--- /dev/null
+++ b/services/tests/servicestests/src/com/android/server/pm/ShortcutManagerTest9.java
@@ -0,0 +1,153 @@
+/*
+ * 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.pm;
+
+import static com.android.server.pm.shortcutmanagertest.ShortcutManagerTestUtils.assertExpectException;
+
+import static org.mockito.Matchers.any;
+import static org.mockito.Matchers.eq;
+import static org.mockito.Mockito.times;
+import static org.mockito.Mockito.verify;
+
+import android.annotation.Nullable;
+import android.app.PendingIntent;
+import android.appwidget.AppWidgetProviderInfo;
+import android.content.ComponentName;
+import android.content.Intent;
+import android.content.IntentSender;
+import android.content.pm.LauncherApps;
+import android.content.pm.LauncherApps.PinItemRequest;
+import android.os.UserHandle;
+import android.test.suitebuilder.annotation.SmallTest;
+
+import org.mockito.ArgumentCaptor;
+
+/**
+ * Tests for {@link android.content.pm.ShortcutServiceInternal#requestPinAppWidget}
+ * and relevant APIs.
+ *
+ m FrameworksServicesTests &&
+ adb install \
+ -r -g ${ANDROID_PRODUCT_OUT}/data/app/FrameworksServicesTests/FrameworksServicesTests.apk &&
+ adb shell am instrument -e class com.android.server.pm.ShortcutManagerTest9 \
+ -w com.android.frameworks.servicestests/android.support.test.runner.AndroidJUnitRunner
+ */
+@SmallTest
+public class ShortcutManagerTest9 extends BaseShortcutManagerTest {
+
+ private ShortcutRequestPinProcessor mProcessor;
+
+ @Override
+ protected void initService() {
+ super.initService();
+ mProcessor = mService.getShortcutRequestPinProcessorForTest();
+ }
+
+ @Override
+ protected void setCaller(String packageName, int userId) {
+ super.setCaller(packageName, userId);
+
+ // Note during this test, assume all callers are in the foreground by default.
+ makeCallerForeground();
+ }
+
+ private AppWidgetProviderInfo makeProviderInfo(String className) {
+ AppWidgetProviderInfo info = new AppWidgetProviderInfo();
+ info.provider = new ComponentName(CALLING_PACKAGE_3, className);
+ return info;
+ }
+
+ private void assertPinItemRequestIntent(Intent actualIntent, String expectedPackage) {
+ assertEquals(LauncherApps.ACTION_CONFIRM_PIN_ITEM, actualIntent.getAction());
+ assertEquals(expectedPackage, actualIntent.getComponent().getPackageName());
+ assertEquals(PIN_CONFIRM_ACTIVITY_CLASS,
+ actualIntent.getComponent().getClassName());
+ assertEquals(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK,
+ actualIntent.getFlags());
+ }
+
+ private void assertPinItemRequest(PinItemRequest actualRequest, String className) {
+ assertNotNull(actualRequest);
+ assertEquals(PinItemRequest.REQUEST_TYPE_APPWIDGET, actualRequest.getRequestType());
+ assertEquals(className, actualRequest.getAppWidgetProviderInfo().provider.getClassName());
+ }
+
+ public void testNotForeground() {
+ setDefaultLauncher(USER_0, mMainActivityFetcher.apply(LAUNCHER_1, USER_0));
+
+ runWithCaller(CALLING_PACKAGE_1, USER_P0, () -> {
+ makeCallerBackground();
+
+ assertExpectException(IllegalStateException.class, "foreground activity", () -> {
+ mInternal.requestPinAppWidget(CALLING_PACKAGE_1, makeProviderInfo("dummy"),
+ /* resultIntent= */ null, USER_P0);
+ });
+
+ verify(mServiceContext, times(0)).sendIntentSender(any(IntentSender.class));
+ verify(mServiceContext, times(0)).startActivityAsUser(
+ any(Intent.class), any(UserHandle.class));
+ });
+ }
+
+ private void checkRequestPinAppWidget(@Nullable PendingIntent resultIntent) {
+ setDefaultLauncher(USER_0, mMainActivityFetcher.apply(LAUNCHER_1, USER_0));
+ setDefaultLauncher(USER_10, mMainActivityFetcher.apply(LAUNCHER_2, USER_10));
+
+ runWithCaller(CALLING_PACKAGE_1, USER_P0, () -> {
+ AppWidgetProviderInfo info = makeProviderInfo("c1");
+
+ assertTrue(mInternal.requestPinAppWidget(CALLING_PACKAGE_1, info,
+ resultIntent == null ? null : resultIntent.getIntentSender(), USER_P0));
+
+ verify(mServiceContext, times(0)).sendIntentSender(any(IntentSender.class));
+ });
+
+ runWithCaller(LAUNCHER_1, USER_0, () -> {
+ // Check the intent passed to startActivityAsUser().
+ final ArgumentCaptor<Intent> intent = ArgumentCaptor.forClass(Intent.class);
+
+ verify(mServiceContext).startActivityAsUser(intent.capture(), eq(HANDLE_USER_0));
+
+ assertPinItemRequestIntent(intent.getValue(), mInjectedClientPackage);
+
+ // Check the request object.
+ final PinItemRequest request = mLauncherApps.getPinItemRequest(intent.getValue());
+ assertPinItemRequest(request, "c1");
+
+ // Accept the request.
+ assertTrue(request.accept());
+ });
+
+ // This method is always called, even with PI == null.
+ if (resultIntent == null) {
+ verify(mServiceContext, times(1)).sendIntentSender(eq(null));
+ } else {
+ verify(mServiceContext, times(1)).sendIntentSender(any(IntentSender.class));
+ }
+ }
+
+ public void testRequestPinAppWidget() {
+ checkRequestPinAppWidget(/* resultIntent=*/ null);
+ }
+
+ public void testRequestPinAppWidget_withCallback() {
+ final PendingIntent resultIntent =
+ PendingIntent.getActivity(getTestContext(), 0, new Intent(), 0);
+
+ checkRequestPinAppWidget(resultIntent);
+ }
+}
diff --git a/services/tests/servicestests/src/com/android/server/wm/AppWindowContainerControllerTests.java b/services/tests/servicestests/src/com/android/server/wm/AppWindowContainerControllerTests.java
new file mode 100644
index 0000000..8a962e7
--- /dev/null
+++ b/services/tests/servicestests/src/com/android/server/wm/AppWindowContainerControllerTests.java
@@ -0,0 +1,42 @@
+/*
+ * 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.wm;
+
+import org.junit.Test;
+
+import android.platform.test.annotations.Presubmit;
+import android.support.test.filters.SmallTest;
+import android.support.test.runner.AndroidJUnit4;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertTrue;
+
+/**
+ * Test class for {@link WindowContainerController}.
+ *
+ * Build/Install/Run:
+ * bit FrameworksServicesTests:com.android.server.wm.AppWindowContainerControllerTests
+ */
+@SmallTest
+@Presubmit
+@org.junit.runner.RunWith(AndroidJUnit4.class)
+public class AppWindowContainerControllerTests extends WindowTestsBase {
+// TODO Add tests once TaskWindowContainerController is created.
+ @Test
+ public void dummyTest() throws Exception {}
+}
diff --git a/services/tests/servicestests/src/com/android/server/wm/TaskStackContainersTests.java b/services/tests/servicestests/src/com/android/server/wm/TaskStackContainersTests.java
index 7463102..24893a1 100644
--- a/services/tests/servicestests/src/com/android/server/wm/TaskStackContainersTests.java
+++ b/services/tests/servicestests/src/com/android/server/wm/TaskStackContainersTests.java
@@ -47,14 +47,15 @@
// Test that always-on-top stack can't be moved to position other than top.
final TaskStack stack1 = createTaskStackOnDisplay(sDisplayContent);
final TaskStack stack2 = createTaskStackOnDisplay(sDisplayContent);
- sDisplayContent.addStackToDisplay(PINNED_STACK_ID, true);
- final TaskStack pinnedStack = sWm.mStackIdToStack.get(PINNED_STACK_ID);
+ final TaskStack pinnedStack = addPinnedStack();
final WindowContainer taskStackContainer = stack1.getParent();
final int stack1Pos = taskStackContainer.mChildren.indexOf(stack1);
final int stack2Pos = taskStackContainer.mChildren.indexOf(stack2);
final int pinnedStackPos = taskStackContainer.mChildren.indexOf(pinnedStack);
+ assertGreaterThan(pinnedStackPos, stack2Pos);
+ assertGreaterThan(stack2Pos, stack1Pos);
taskStackContainer.positionChildAt(WindowContainer.POSITION_BOTTOM, pinnedStack, false);
assertEquals(taskStackContainer.mChildren.get(stack1Pos), stack1);
@@ -66,4 +67,43 @@
assertEquals(taskStackContainer.mChildren.get(stack2Pos), stack2);
assertEquals(taskStackContainer.mChildren.get(pinnedStackPos), pinnedStack);
}
+ @Test
+ public void testStackPositionBelowPinnedStack() throws Exception {
+ // Test that no stack can be above pinned stack.
+ final TaskStack pinnedStack = addPinnedStack();
+ final TaskStack stack1 = createTaskStackOnDisplay(sDisplayContent);
+
+ final WindowContainer taskStackContainer = stack1.getParent();
+
+ final int stackPos = taskStackContainer.mChildren.indexOf(stack1);
+ final int pinnedStackPos = taskStackContainer.mChildren.indexOf(pinnedStack);
+ assertGreaterThan(pinnedStackPos, stackPos);
+
+ taskStackContainer.positionChildAt(WindowContainer.POSITION_TOP, stack1, false);
+ assertEquals(taskStackContainer.mChildren.get(stackPos), stack1);
+ assertEquals(taskStackContainer.mChildren.get(pinnedStackPos), pinnedStack);
+
+ taskStackContainer.positionChildAt(taskStackContainer.mChildren.size() - 1, stack1, false);
+ assertEquals(taskStackContainer.mChildren.get(stackPos), stack1);
+ assertEquals(taskStackContainer.mChildren.get(pinnedStackPos), pinnedStack);
+ }
+
+ private TaskStack addPinnedStack() {
+ TaskStack pinnedStack = sWm.mStackIdToStack.get(PINNED_STACK_ID);
+ if (pinnedStack == null) {
+ sDisplayContent.addStackToDisplay(PINNED_STACK_ID, true);
+ pinnedStack = sWm.mStackIdToStack.get(PINNED_STACK_ID);
+ }
+
+ if (!pinnedStack.isVisible()) {
+ // Stack should contain visible app window to be considered visible.
+ final Task pinnedTask = createTaskInStack(pinnedStack, 0 /* userId */);
+ assertFalse(pinnedStack.isVisible());
+ final TestAppWindowToken pinnedApp = new TestAppWindowToken(sDisplayContent);
+ pinnedTask.addChild(pinnedApp, 0 /* addPos */);
+ assertTrue(pinnedStack.isVisible());
+ }
+
+ return pinnedStack;
+ }
}
diff --git a/services/tests/servicestests/src/com/android/server/wm/TaskStackTests.java b/services/tests/servicestests/src/com/android/server/wm/TaskStackTests.java
index eca2500..1c69033 100644
--- a/services/tests/servicestests/src/com/android/server/wm/TaskStackTests.java
+++ b/services/tests/servicestests/src/com/android/server/wm/TaskStackTests.java
@@ -56,4 +56,20 @@
assertEquals(stack.mChildren.get(0), task2);
assertEquals(stack.mChildren.get(1), task1);
}
+
+ @Test
+ public void testStackRemoveImmediately() throws Exception {
+ final TaskStack stack = createTaskStackOnDisplay(sDisplayContent);
+ final Task task = createTaskInStack(stack, 0 /* userId */);
+ assertEquals(stack, task.mStack);
+ assertTrue(sDisplayContent.mDimLayerController.hasDimLayerUser(stack));
+ assertTrue(sDisplayContent.mDimLayerController.hasDimLayerUser(task));
+
+ // Remove stack and check if its child is also removed.
+ stack.removeImmediately();
+ assertNull(stack.getDisplayContent());
+ assertNull(task.mStack);
+ assertFalse(sDisplayContent.mDimLayerController.hasDimLayerUser(stack));
+ assertFalse(sDisplayContent.mDimLayerController.hasDimLayerUser(task));
+ }
}
diff --git a/services/tests/servicestests/src/com/android/server/wm/UnknownAppVisibilityControllerTest.java b/services/tests/servicestests/src/com/android/server/wm/UnknownAppVisibilityControllerTest.java
index 07f65bd..6129198 100644
--- a/services/tests/servicestests/src/com/android/server/wm/UnknownAppVisibilityControllerTest.java
+++ b/services/tests/servicestests/src/com/android/server/wm/UnknownAppVisibilityControllerTest.java
@@ -19,7 +19,6 @@
import static junit.framework.Assert.assertTrue;
import static org.mockito.Mockito.any;
import static org.mockito.Mockito.doAnswer;
-import static org.mockito.Mockito.mock;
import android.app.ActivityManagerInternal;
import android.content.Context;
@@ -27,7 +26,6 @@
import android.support.test.InstrumentationRegistry;
import android.support.test.filters.SmallTest;
import android.support.test.runner.AndroidJUnit4;
-import android.view.IApplicationToken;
import com.android.server.LocalServices;
@@ -114,7 +112,6 @@
}
private AppWindowToken createAppToken() {
- return new AppWindowToken(mWm, mock(IApplicationToken.class), false,
- mWm.getDefaultDisplayContentLocked());
+ return new AppWindowToken(mWm, null, false, mWm.getDefaultDisplayContentLocked());
}
}
diff --git a/services/tests/servicestests/src/com/android/server/wm/WindowContainerControllerTests.java b/services/tests/servicestests/src/com/android/server/wm/WindowContainerControllerTests.java
new file mode 100644
index 0000000..956735c
--- /dev/null
+++ b/services/tests/servicestests/src/com/android/server/wm/WindowContainerControllerTests.java
@@ -0,0 +1,84 @@
+/*
+ * Copyright (C) 2016 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.wm;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import android.platform.test.annotations.Presubmit;
+import android.support.test.filters.SmallTest;
+import android.support.test.runner.AndroidJUnit4;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertTrue;
+
+/**
+ * Test class for {@link WindowContainerController}.
+ *
+ * Build/Install/Run:
+ * bit FrameworksServicesTests:com.android.server.wm.WindowContainerControllerTests
+ */
+@SmallTest
+@Presubmit
+@org.junit.runner.RunWith(AndroidJUnit4.class)
+public class WindowContainerControllerTests extends WindowTestsBase {
+
+ @Test
+ public void testCreation() throws Exception {
+ final WindowContainerController controller = new WindowContainerController(null, sWm);
+ final WindowContainer container = new WindowContainer();
+
+ container.setController(controller);
+ assertEquals(controller, container.getController());
+ assertEquals(controller.mContainer, container);
+ }
+
+ @Test
+ public void testSetContainer() throws Exception {
+ final WindowContainerController controller = new WindowContainerController(null, sWm);
+ final WindowContainer container = new WindowContainer();
+
+ controller.setContainer(container);
+ assertEquals(controller.mContainer, container);
+
+ // Assert we can't change the container to another one once set
+ boolean gotException = false;
+ try {
+ controller.setContainer(new WindowContainer());
+ } catch (IllegalArgumentException e) {
+ gotException = true;
+ }
+ assertTrue(gotException);
+
+ // Assert that we can set the container to null.
+ controller.setContainer(null);
+ assertNull(controller.mContainer);
+ }
+
+ @Test
+ public void testRemoveContainer() throws Exception {
+ final WindowContainerController controller = new WindowContainerController(null, sWm);
+ final WindowContainer container = new WindowContainer();
+
+ controller.setContainer(container);
+ assertEquals(controller.mContainer, container);
+
+ controller.removeContainer();
+ assertNull(controller.mContainer);
+ }
+}
diff --git a/services/tests/servicestests/src/com/android/server/wm/WindowContainerTests.java b/services/tests/servicestests/src/com/android/server/wm/WindowContainerTests.java
index 7277ba4..b57329c 100644
--- a/services/tests/servicestests/src/com/android/server/wm/WindowContainerTests.java
+++ b/services/tests/servicestests/src/com/android/server/wm/WindowContainerTests.java
@@ -52,7 +52,7 @@
@SmallTest
@Presubmit
@RunWith(AndroidJUnit4.class)
-public class WindowContainerTests {
+public class WindowContainerTests extends WindowTestsBase {
@Test
public void testCreation() throws Exception {
@@ -192,6 +192,44 @@
}
@Test
+ public void testRemoveImmediately_WithController() throws Exception {
+ final WindowContainer container = new WindowContainer();
+ final WindowContainerController controller = new WindowContainerController(null, sWm);
+
+ container.setController(controller);
+ assertEquals(controller, container.getController());
+ assertEquals(container, controller.mContainer);
+
+ container.removeImmediately();
+ assertNull(container.getController());
+ assertNull(controller.mContainer);
+ }
+
+ @Test
+ public void testSetController() throws Exception {
+ final WindowContainerController controller = new WindowContainerController(null, sWm);
+ final WindowContainer container = new WindowContainer();
+
+ container.setController(controller);
+ assertEquals(controller, container.getController());
+ assertEquals(container, controller.mContainer);
+
+ // Assert we can't change the controller to another one once set
+ boolean gotException = false;
+ try {
+ container.setController(new WindowContainerController(null, sWm));
+ } catch (IllegalArgumentException e) {
+ gotException = true;
+ }
+ assertTrue(gotException);
+
+ // Assert that we can set the controller to null.
+ container.setController(null);
+ assertNull(container.getController());
+ assertNull(controller.mContainer);
+ }
+
+ @Test
public void testPositionChildAt() throws Exception {
final TestWindowContainerBuilder builder = new TestWindowContainerBuilder();
final TestWindowContainer root = builder.setLayer(0).build();
diff --git a/services/tests/servicestests/src/com/android/server/wm/WindowTestsBase.java b/services/tests/servicestests/src/com/android/server/wm/WindowTestsBase.java
index 3985687..fb3beb3 100644
--- a/services/tests/servicestests/src/com/android/server/wm/WindowTestsBase.java
+++ b/services/tests/servicestests/src/com/android/server/wm/WindowTestsBase.java
@@ -44,7 +44,7 @@
/**
* Common base class for window manager unit test classes.
*/
-public class WindowTestsBase {
+class WindowTestsBase {
static WindowManagerService sWm = null;
private final IWindow mIWindow = new TestIWindow();
private final Session mMockSession = mock(Session.class);
@@ -52,17 +52,17 @@
private static int sNextTaskId = 0;
private static boolean sOneTimeSetupDone = false;
- protected static DisplayContent sDisplayContent;
- protected static WindowLayersController sLayersController;
- protected static WindowState sWallpaperWindow;
- protected static WindowState sImeWindow;
- protected static WindowState sImeDialogWindow;
- protected static WindowState sStatusBarWindow;
- protected static WindowState sDockedDividerWindow;
- protected static WindowState sNavBarWindow;
- protected static WindowState sAppWindow;
- protected static WindowState sChildAppWindowAbove;
- protected static WindowState sChildAppWindowBelow;
+ static DisplayContent sDisplayContent;
+ static WindowLayersController sLayersController;
+ static WindowState sWallpaperWindow;
+ static WindowState sImeWindow;
+ static WindowState sImeDialogWindow;
+ static WindowState sStatusBarWindow;
+ static WindowState sDockedDividerWindow;
+ static WindowState sNavBarWindow;
+ static WindowState sAppWindow;
+ static WindowState sChildAppWindowAbove;
+ static WindowState sChildAppWindowBelow;
@Before
public void setUp() throws Exception {
diff --git a/services/usage/java/com/android/server/usage/StorageStatsService.java b/services/usage/java/com/android/server/usage/StorageStatsService.java
new file mode 100644
index 0000000..512a119
--- /dev/null
+++ b/services/usage/java/com/android/server/usage/StorageStatsService.java
@@ -0,0 +1,254 @@
+/*
+ * 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.usage;
+
+import android.app.AppOpsManager;
+import android.app.usage.ExternalStorageStats;
+import android.app.usage.IStorageStatsManager;
+import android.app.usage.StorageStats;
+import android.content.Context;
+import android.content.pm.ApplicationInfo;
+import android.content.pm.PackageManager;
+import android.content.pm.PackageManager.NameNotFoundException;
+import android.content.pm.PackageStats;
+import android.content.pm.UserInfo;
+import android.os.Binder;
+import android.os.Environment;
+import android.os.SystemProperties;
+import android.os.UserHandle;
+import android.os.UserManager;
+import android.os.storage.StorageManager;
+import android.os.storage.VolumeInfo;
+import android.util.Log;
+
+import com.android.internal.util.ArrayUtils;
+import com.android.server.SystemService;
+import com.android.server.pm.Installer;
+import com.android.server.pm.Installer.InstallerException;
+
+public class StorageStatsService extends IStorageStatsManager.Stub {
+ private static final String TAG = "StorageStatsService";
+
+ private static final String PROP_VERIFY_STORAGE = "fw.verify_storage";
+
+ // TODO: pivot all methods to manual mode when quota isn't supported
+
+ public static class Lifecycle extends SystemService {
+ private StorageStatsService mService;
+
+ public Lifecycle(Context context) {
+ super(context);
+ }
+
+ @Override
+ public void onStart() {
+ mService = new StorageStatsService(getContext());
+ publishBinderService(Context.STORAGE_STATS_SERVICE, mService);
+ }
+ }
+
+ private final Context mContext;
+ private final AppOpsManager mAppOps;
+ private final UserManager mUser;
+ private final PackageManager mPackage;
+ private final StorageManager mStorage;
+ private final Installer mInstaller;
+
+ public StorageStatsService(Context context) {
+ mContext = context;
+ mAppOps = context.getSystemService(AppOpsManager.class);
+ mUser = context.getSystemService(UserManager.class);
+ mPackage = context.getSystemService(PackageManager.class);
+ mStorage = context.getSystemService(StorageManager.class);
+ mInstaller = new Installer(context);
+ }
+
+ private void enforcePermission(int callingUid, String callingPackage) {
+ final int mode = mAppOps.checkOp(AppOpsManager.OP_GET_USAGE_STATS,
+ callingUid, callingPackage);
+ switch (mode) {
+ case AppOpsManager.MODE_ALLOWED:
+ return;
+ case AppOpsManager.MODE_DEFAULT:
+ mContext.enforceCallingPermission(
+ android.Manifest.permission.PACKAGE_USAGE_STATS, TAG);
+ default:
+ throw new SecurityException("Blocked by mode " + mode);
+ }
+ }
+
+ @Override
+ public long getTotalBytes(String volumeUuid, String callingPackage) {
+ enforcePermission(Binder.getCallingUid(), callingPackage);
+
+ if (volumeUuid == StorageManager.UUID_PRIVATE_INTERNAL) {
+ // TODO: round total size to nearest power of two
+ return mStorage.getPrimaryStorageSize();
+ } else {
+ final VolumeInfo vol = mStorage.findVolumeByUuid(volumeUuid);
+ return vol.disk.size;
+ }
+ }
+
+ @Override
+ public long getFreeBytes(String volumeUuid, String callingPackage) {
+ enforcePermission(Binder.getCallingUid(), callingPackage);
+
+ long cacheBytes = 0;
+ for (UserInfo user : mUser.getUsers()) {
+ final StorageStats stats = queryStatsForUser(volumeUuid, user.id, null);
+ cacheBytes += stats.cacheBytes;
+ }
+
+ if (volumeUuid == StorageManager.UUID_PRIVATE_INTERNAL) {
+ return Environment.getDataDirectory().getFreeSpace() + cacheBytes;
+ } else {
+ final VolumeInfo vol = mStorage.findVolumeByUuid(volumeUuid);
+ return vol.getPath().getFreeSpace() + cacheBytes;
+ }
+ }
+
+ @Override
+ public StorageStats queryStatsForUid(String volumeUuid, int uid, String callingPackage) {
+ enforcePermission(Binder.getCallingUid(), callingPackage);
+ if (UserHandle.getUserId(uid) != UserHandle.getCallingUserId()) {
+ mContext.enforceCallingOrSelfPermission(
+ android.Manifest.permission.INTERACT_ACROSS_USERS, TAG);
+ }
+
+ final int userId = UserHandle.getUserId(uid);
+ final int appId = UserHandle.getUserId(uid);
+
+ final String[] packageNames = mPackage.getPackagesForUid(uid);
+ final long[] ceDataInodes = new long[packageNames.length];
+ final String[] codePaths = new String[packageNames.length];
+
+ for (int i = 0; i < packageNames.length; i++) {
+ try {
+ codePaths[i] = mPackage.getApplicationInfoAsUser(packageNames[i], 0,
+ userId).getCodePath();
+ } catch (NameNotFoundException e) {
+ throw new IllegalStateException(e);
+ }
+ }
+
+ final PackageStats stats = new PackageStats(TAG);
+ try {
+ mInstaller.getAppSize(volumeUuid, packageNames, userId, Installer.FLAG_USE_QUOTA,
+ appId, ceDataInodes, codePaths, stats);
+
+ if (SystemProperties.getBoolean(PROP_VERIFY_STORAGE, false)) {
+ final PackageStats manualStats = new PackageStats(TAG);
+ mInstaller.getAppSize(volumeUuid, packageNames, userId, 0,
+ appId, ceDataInodes, codePaths, manualStats);
+ checkEquals("UID " + uid, manualStats, stats);
+ }
+ } catch (InstallerException e) {
+ throw new IllegalStateException(e);
+ }
+ return translate(stats);
+ }
+
+ @Override
+ public StorageStats queryStatsForUser(String volumeUuid, int userId, String callingPackage) {
+ enforcePermission(Binder.getCallingUid(), callingPackage);
+ if (userId != UserHandle.getCallingUserId()) {
+ mContext.enforceCallingOrSelfPermission(
+ android.Manifest.permission.INTERACT_ACROSS_USERS, TAG);
+ }
+
+ int[] appIds = null;
+ for (ApplicationInfo app : mPackage.getInstalledApplicationsAsUser(0, userId)) {
+ final int appId = UserHandle.getAppId(app.uid);
+ if (!ArrayUtils.contains(appIds, appId)) {
+ appIds = ArrayUtils.appendInt(appIds, appId);
+ }
+ }
+
+ final PackageStats stats = new PackageStats(TAG);
+ try {
+ mInstaller.getUserSize(volumeUuid, userId, Installer.FLAG_USE_QUOTA, appIds, stats);
+
+ if (SystemProperties.getBoolean(PROP_VERIFY_STORAGE, false)) {
+ final PackageStats manualStats = new PackageStats(TAG);
+ mInstaller.getUserSize(volumeUuid, userId, 0, appIds, manualStats);
+ checkEquals("User " + userId, manualStats, stats);
+ }
+ } catch (InstallerException e) {
+ throw new IllegalStateException(e);
+ }
+ return translate(stats);
+ }
+
+ @Override
+ public ExternalStorageStats queryExternalStatsForUser(String volumeUuid, int userId,
+ String callingPackage) {
+ enforcePermission(Binder.getCallingUid(), callingPackage);
+ if (userId != UserHandle.getCallingUserId()) {
+ mContext.enforceCallingOrSelfPermission(
+ android.Manifest.permission.INTERACT_ACROSS_USERS, TAG);
+ }
+
+ final long[] stats;
+ try {
+ stats = mInstaller.getExternalSize(volumeUuid, userId, Installer.FLAG_USE_QUOTA);
+
+ if (SystemProperties.getBoolean(PROP_VERIFY_STORAGE, false)) {
+ final long[] manualStats = mInstaller.getExternalSize(volumeUuid, userId, 0);
+ checkEquals("External " + userId, manualStats, stats);
+ }
+ } catch (InstallerException e) {
+ throw new IllegalStateException(e);
+ }
+
+ final ExternalStorageStats res = new ExternalStorageStats();
+ res.totalBytes = stats[0];
+ res.audioBytes = stats[1];
+ res.videoBytes = stats[2];
+ res.imageBytes = stats[3];
+ return res;
+ }
+
+ private static void checkEquals(String msg, long[] a, long[] b) {
+ for (int i = 0; i < a.length; i++) {
+ checkEquals(msg + "[" + i + "]", a[i], b[i]);
+ }
+ }
+
+ private static void checkEquals(String msg, PackageStats a, PackageStats b) {
+ checkEquals(msg + " codeSize", a.codeSize, b.codeSize);
+ checkEquals(msg + " dataSize", a.dataSize, b.dataSize);
+ checkEquals(msg + " cacheSize", a.cacheSize, b.cacheSize);
+ checkEquals(msg + " externalCodeSize", a.externalCodeSize, b.externalCodeSize);
+ checkEquals(msg + " externalDataSize", a.externalDataSize, b.externalDataSize);
+ checkEquals(msg + " externalCacheSize", a.externalCacheSize, b.externalCacheSize);
+ }
+
+ private static void checkEquals(String msg, long expected, long actual) {
+ if (expected != actual) {
+ Log.e(TAG, msg + " expected " + expected + " actual " + actual);
+ }
+ }
+
+ private static StorageStats translate(PackageStats stats) {
+ final StorageStats res = new StorageStats();
+ res.codeBytes = stats.codeSize + stats.externalCodeSize;
+ res.dataBytes = stats.dataSize + stats.externalDataSize;
+ res.cacheBytes = stats.cacheSize + stats.externalCacheSize;
+ return res;
+ }
+}
diff --git a/telecomm/java/android/telecom/Call.java b/telecomm/java/android/telecom/Call.java
index c69b7c2..b20384d 100644
--- a/telecomm/java/android/telecom/Call.java
+++ b/telecomm/java/android/telecom/Call.java
@@ -115,6 +115,13 @@
*/
public static final String AVAILABLE_PHONE_ACCOUNTS = "selectPhoneAccountAccounts";
+ /**
+ * Extra key used to indicate the time (in millis) when the last outgoing emergency call was
+ * made. This is used to identify potential emergency callbacks.
+ */
+ public static final String EXTRA_LAST_EMERGENCY_CALLBACK_TIME_MILLIS =
+ "android.telecom.extra.LAST_EMERGENCY_CALLBACK_TIME_MILLIS";
+
public static class Details {
/** Call can currently be put on hold or unheld. */
diff --git a/telephony/java/android/telephony/DisconnectCause.java b/telephony/java/android/telephony/DisconnectCause.java
index 989f72c..10cb7c9 100644
--- a/telephony/java/android/telephony/DisconnectCause.java
+++ b/telephony/java/android/telephony/DisconnectCause.java
@@ -239,6 +239,13 @@
*/
public static final int DIALED_CALL_FORWARDING_WHILE_ROAMING = 57;
+ /**
+ * The network does not accept the emergency call request because IMEI was used as
+ * identification and this cability is not supported by the network.
+ * {@hide}
+ */
+ public static final int IMEI_NOT_ACCEPTED = 58;
+
//*********************************************************************************************
// When adding a disconnect type:
// 1) Please assign the new type the next id value below.
@@ -247,14 +254,14 @@
// 4) Update toString() with the newly added disconnect type.
// 5) Update android.telecom.DisconnectCauseUtil with any mappings to a telecom.DisconnectCause.
//
- // NextId: 58
+ // NextId: 59
//*********************************************************************************************
/** Smallest valid value for call disconnect codes. */
public static final int MINIMUM_VALID_VALUE = NOT_DISCONNECTED;
/** Largest valid value for call disconnect codes. */
- public static final int MAXIMUM_VALID_VALUE = DIALED_CALL_FORWARDING_WHILE_ROAMING;
+ public static final int MAXIMUM_VALID_VALUE = IMEI_NOT_ACCEPTED;
/** Private constructor to avoid class instantiation. */
private DisconnectCause() {
@@ -378,6 +385,8 @@
return "DIALED_ON_WRONG_SLOT";
case DIALED_CALL_FORWARDING_WHILE_ROAMING:
return "DIALED_CALL_FORWARDING_WHILE_ROAMING";
+ case IMEI_NOT_ACCEPTED:
+ return "IMEI_NOT_ACCEPTED";
default:
return "INVALID: " + cause;
}
diff --git a/tests/UiBench/AndroidManifest.xml b/tests/UiBench/AndroidManifest.xml
index 29154aa..0681b61 100644
--- a/tests/UiBench/AndroidManifest.xml
+++ b/tests/UiBench/AndroidManifest.xml
@@ -76,6 +76,14 @@
</intent-filter>
</activity>
<activity
+ android:name=".ResizeHWLayerActivity"
+ android:label="General/Resize HW Layer" >
+ <intent-filter>
+ <action android:name="android.intent.action.MAIN" />
+ <category android:name="com.android.test.uibench.TEST" />
+ </intent-filter>
+ </activity>
+ <activity
android:name=".TrivialAnimationActivity"
android:label="General/Trivial Animation" >
<intent-filter>
diff --git a/tests/UiBench/src/com/android/test/uibench/ResizeHWLayerActivity.java b/tests/UiBench/src/com/android/test/uibench/ResizeHWLayerActivity.java
new file mode 100644
index 0000000..23a2713
--- /dev/null
+++ b/tests/UiBench/src/com/android/test/uibench/ResizeHWLayerActivity.java
@@ -0,0 +1,60 @@
+/*
+ * 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.test.uibench;
+
+import android.animation.PropertyValuesHolder;
+import android.animation.ValueAnimator;
+import android.graphics.Color;
+import android.os.Bundle;
+import android.support.v7.app.AppCompatActivity;
+import android.util.DisplayMetrics;
+import android.view.View;
+import android.view.ViewGroup.LayoutParams;
+import android.widget.FrameLayout;
+
+/**
+ * Tests resizing of a View backed by a hardware layer.
+ */
+public class ResizeHWLayerActivity extends AppCompatActivity {
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ DisplayMetrics metrics = getResources().getDisplayMetrics();
+ int width = metrics.widthPixels;
+ int height = metrics.heightPixels;
+ View child = new View(this);
+ child.setBackgroundColor(Color.BLUE);
+ child.setLayoutParams(new FrameLayout.LayoutParams(width, height));
+ child.setLayerType(View.LAYER_TYPE_HARDWARE, null);
+ PropertyValuesHolder pvhWidth = PropertyValuesHolder.ofInt("width", width, 1);
+ PropertyValuesHolder pvhHeight = PropertyValuesHolder.ofInt("height", height, 1);
+ final LayoutParams params = child.getLayoutParams();
+ ValueAnimator animator = ValueAnimator.ofPropertyValuesHolder(pvhWidth, pvhHeight);
+ animator.setRepeatMode(ValueAnimator.REVERSE);
+ animator.setRepeatCount(ValueAnimator.INFINITE);
+ animator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
+ @Override
+ public void onAnimationUpdate(ValueAnimator valueAnimator) {
+ params.width = (Integer)valueAnimator.getAnimatedValue("width");
+ params.height = (Integer)valueAnimator.getAnimatedValue("height");
+ child.requestLayout();
+ }
+ });
+ animator.start();
+ setContentView(child);
+ }
+}
diff --git a/tests/permission/src/com/android/framework/permission/tests/WindowManagerPermissionTests.java b/tests/permission/src/com/android/framework/permission/tests/WindowManagerPermissionTests.java
index 28a2cb3..4aeae70 100644
--- a/tests/permission/src/com/android/framework/permission/tests/WindowManagerPermissionTests.java
+++ b/tests/permission/src/com/android/framework/permission/tests/WindowManagerPermissionTests.java
@@ -43,26 +43,6 @@
@SmallTest
public void testMANAGE_APP_TOKENS() {
try {
- mWm.pauseKeyDispatching(null);
- fail("IWindowManager.pauseKeyDispatching did not throw SecurityException as"
- + " expected");
- } catch (SecurityException e) {
- // expected
- } catch (RemoteException e) {
- fail("Unexpected remote exception");
- }
-
- try {
- mWm.resumeKeyDispatching(null);
- fail("IWindowManager.resumeKeyDispatching did not throw SecurityException as"
- + " expected");
- } catch (SecurityException e) {
- // expected
- } catch (RemoteException e) {
- fail("Unexpected remote exception");
- }
-
- try {
mWm.setEventDispatching(true);
fail("IWindowManager.setEventDispatching did not throw SecurityException as"
+ " expected");
@@ -93,26 +73,6 @@
}
try {
- mWm.addAppToken(0, null, 0, 0, false, false, 0, false, false, false, 0, -1);
- fail("IWindowManager.addAppToken did not throw SecurityException as"
- + " expected");
- } catch (SecurityException e) {
- // expected
- } catch (RemoteException e) {
- fail("Unexpected remote exception");
- }
-
- try {
- mWm.addAppToTask(null, 0);
- fail("IWindowManager.setAppGroupId did not throw SecurityException as"
- + " expected");
- } catch (SecurityException e) {
- // expected
- } catch (RemoteException e) {
- fail("Unexpected remote exception");
- }
-
- try {
mWm.updateOrientationFromAppTokens(new Configuration(),
null /* freezeThisOneIfNeeded */, DEFAULT_DISPLAY);
fail("IWindowManager.updateOrientationFromAppTokens did not throw SecurityException as"
@@ -124,17 +84,6 @@
}
try {
- mWm.setAppOrientation(null, 0);
- mWm.addWindowToken(null, 0, DEFAULT_DISPLAY);
- fail("IWindowManager.setAppOrientation did not throw SecurityException as"
- + " expected");
- } catch (SecurityException e) {
- // expected
- } catch (RemoteException e) {
- fail("Unexpected remote exception");
- }
-
- try {
mWm.setFocusedApp(null, false);
fail("IWindowManager.setFocusedApp did not throw SecurityException as"
+ " expected");
@@ -163,56 +112,6 @@
} catch (RemoteException e) {
fail("Unexpected remote exception");
}
-
- try {
- mWm.setAppStartingWindow(null, "foo", 0, null, null, 0, 0, 0, 0, null, false);
- fail("IWindowManager.setAppStartingWindow did not throw SecurityException as"
- + " expected");
- } catch (SecurityException e) {
- // expected
- } catch (RemoteException e) {
- fail("Unexpected remote exception");
- }
-
- try {
- mWm.setAppVisibility(null, false);
- fail("IWindowManager.setAppVisibility did not throw SecurityException as"
- + " expected");
- } catch (SecurityException e) {
- // expected
- } catch (RemoteException e) {
- fail("Unexpected remote exception");
- }
-
- try {
- mWm.startAppFreezingScreen(null, 0);
- fail("IWindowManager.startAppFreezingScreen did not throw SecurityException as"
- + " expected");
- } catch (SecurityException e) {
- // expected
- } catch (RemoteException e) {
- fail("Unexpected remote exception");
- }
-
- try {
- mWm.stopAppFreezingScreen(null, false);
- fail("IWindowManager.stopAppFreezingScreen did not throw SecurityException as"
- + " expected");
- } catch (SecurityException e) {
- // expected
- } catch (RemoteException e) {
- fail("Unexpected remote exception");
- }
-
- try {
- mWm.removeAppToken(null, DEFAULT_DISPLAY);
- fail("IWindowManager.removeAppToken did not throw SecurityException as"
- + " expected");
- } catch (SecurityException e) {
- // expected
- } catch (RemoteException e) {
- fail("Unexpected remote exception");
- }
}
@SmallTest
diff --git a/tools/aapt/Command.cpp b/tools/aapt/Command.cpp
index 2e34197..0e031e7 100644
--- a/tools/aapt/Command.cpp
+++ b/tools/aapt/Command.cpp
@@ -393,10 +393,14 @@
printf("\n");
}
-static void printUsesImpliedPermission(const String8& name, const String8& reason) {
- printf("uses-implied-permission: name='%s' reason='%s'\n",
- ResTable::normalizeForOutput(name.string()).string(),
- ResTable::normalizeForOutput(reason.string()).string());
+static void printUsesImpliedPermission(const String8& name, const String8& reason,
+ const int32_t maxSdkVersion = -1) {
+ printf("uses-implied-permission: name='%s'",
+ ResTable::normalizeForOutput(name.string()).string());
+ if (maxSdkVersion != -1) {
+ printf(" maxSdkVersion='%d'", maxSdkVersion);
+ }
+ printf(" reason='%s'\n", ResTable::normalizeForOutput(reason.string()).string());
}
Vector<String8> getNfcAidCategories(AssetManager& assets, const String8& xmlPath, bool offHost,
@@ -1027,6 +1031,7 @@
// These two implement the implicit permissions that are granted
// to pre-1.6 applications.
bool hasWriteExternalStoragePermission = false;
+ int32_t writeExternalStoragePermissionMaxSdkVersion = -1;
bool hasReadPhoneStatePermission = false;
// If an app requests write storage, they will also get read storage.
@@ -1538,8 +1543,12 @@
addImpliedFeaturesForPermission(targetSdk, name, &impliedFeatures, false);
+ const int32_t maxSdkVersion =
+ AaptXml::getIntegerAttribute(tree, MAX_SDK_VERSION_ATTR, -1);
+
if (name == "android.permission.WRITE_EXTERNAL_STORAGE") {
hasWriteExternalStoragePermission = true;
+ writeExternalStoragePermissionMaxSdkVersion = maxSdkVersion;
} else if (name == "android.permission.READ_EXTERNAL_STORAGE") {
hasReadExternalStoragePermission = true;
} else if (name == "android.permission.READ_PHONE_STATE") {
@@ -1556,7 +1565,7 @@
printUsesPermission(name,
AaptXml::getIntegerAttribute(tree, REQUIRED_ATTR, 1) == 0,
- AaptXml::getIntegerAttribute(tree, MAX_SDK_VERSION_ATTR));
+ maxSdkVersion);
} else if (tag == "uses-permission-sdk-23" || tag == "uses-permission-sdk-m") {
String8 name = AaptXml::getAttribute(tree, NAME_ATTR, &error);
@@ -2039,9 +2048,11 @@
// do this (regardless of target API version) because we can't have
// an app with write permission but not read permission.
if (!hasReadExternalStoragePermission && hasWriteExternalStoragePermission) {
- printUsesPermission(String8("android.permission.READ_EXTERNAL_STORAGE"));
+ printUsesPermission(String8("android.permission.READ_EXTERNAL_STORAGE"),
+ false /* optional */, writeExternalStoragePermissionMaxSdkVersion);
printUsesImpliedPermission(String8("android.permission.READ_EXTERNAL_STORAGE"),
- String8("requested WRITE_EXTERNAL_STORAGE"));
+ String8("requested WRITE_EXTERNAL_STORAGE"),
+ writeExternalStoragePermissionMaxSdkVersion);
}
// Pre-JellyBean call log permission compatibility.
diff --git a/tools/layoutlib/bridge/src/android/graphics/Bitmap_Delegate.java b/tools/layoutlib/bridge/src/android/graphics/Bitmap_Delegate.java
index 2ae4654..9d9d71f 100644
--- a/tools/layoutlib/bridge/src/android/graphics/Bitmap_Delegate.java
+++ b/tools/layoutlib/bridge/src/android/graphics/Bitmap_Delegate.java
@@ -62,7 +62,7 @@
public enum BitmapCreateFlags {
- PREMULTIPLIED, MUTABLE
+ NONE, PREMULTIPLIED, MUTABLE
}
// ---- delegate manager ----
@@ -616,6 +616,26 @@
// do nothing as Bitmap_Delegate does not have caches
}
+ @LayoutlibDelegate
+ /*package*/ static Bitmap nativeCopyPreserveInternalConfig(long nativeBitmap) {
+ Bitmap_Delegate srcBmpDelegate = sManager.getDelegate(nativeBitmap);
+ if (srcBmpDelegate == null) {
+ return null;
+ }
+
+ BufferedImage srcImage = srcBmpDelegate.getImage();
+
+ // create the image
+ BufferedImage image = new BufferedImage(srcImage.getColorModel(), srcImage.copyData(null),
+ srcImage.isAlphaPremultiplied(), null);
+
+ // create a delegate with the content of the stream.
+ Bitmap_Delegate delegate = new Bitmap_Delegate(image, srcBmpDelegate.getConfig());
+
+ return createBitmap(delegate, EnumSet.of(BitmapCreateFlags.NONE),
+ Bitmap.getDefaultDensity());
+ }
+
// ---- Private delegate/helper methods ----
private Bitmap_Delegate(BufferedImage image, Config config) {
diff --git a/tools/layoutlib/bridge/src/android/graphics/LayerRasterizer_Delegate.java b/tools/layoutlib/bridge/src/android/graphics/LayerRasterizer_Delegate.java
deleted file mode 100644
index 10cc572..0000000
--- a/tools/layoutlib/bridge/src/android/graphics/LayerRasterizer_Delegate.java
+++ /dev/null
@@ -1,69 +0,0 @@
-/*
- * Copyright (C) 2010 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 android.graphics;
-
-import com.android.layoutlib.bridge.impl.DelegateManager;
-import com.android.tools.layoutlib.annotations.LayoutlibDelegate;
-
-/**
- * Delegate implementing the native methods of android.graphics.LayerRasterizer
- *
- * Through the layoutlib_create tool, the original native methods of LayerRasterizer have
- * been replaced by calls to methods of the same name in this delegate class.
- *
- * This class behaves like the original native implementation, but in Java, keeping previously
- * native data into its own objects and mapping them to int that are sent back and forth between
- * it and the original LayerRasterizer class.
- *
- * Because this extends {@link Rasterizer_Delegate}, there's no need to use a
- * {@link DelegateManager}, as all the Shader classes will be added to the manager
- * owned by {@link Rasterizer_Delegate}.
- *
- * @see Rasterizer_Delegate
- *
- */
-public class LayerRasterizer_Delegate extends Rasterizer_Delegate {
-
- // ---- delegate data ----
-
- // ---- Public Helper methods ----
-
- @Override
- public boolean isSupported() {
- return false;
- }
-
- @Override
- public String getSupportMessage() {
- return "Layer Rasterizers are not supported.";
- }
-
- // ---- native methods ----
-
- @LayoutlibDelegate
- /*package*/ static long nativeConstructor() {
- LayerRasterizer_Delegate newDelegate = new LayerRasterizer_Delegate();
- return sManager.addNewDelegate(newDelegate);
- }
-
- @LayoutlibDelegate
- /*package*/ static void nativeAddLayer(long native_layer, long native_paint, float dx, float dy) {
-
- }
-
- // ---- Private delegate/helper methods ----
-}
diff --git a/tools/layoutlib/bridge/src/android/graphics/Paint_Delegate.java b/tools/layoutlib/bridge/src/android/graphics/Paint_Delegate.java
index e68d8b3..9b8fa99 100644
--- a/tools/layoutlib/bridge/src/android/graphics/Paint_Delegate.java
+++ b/tools/layoutlib/bridge/src/android/graphics/Paint_Delegate.java
@@ -99,7 +99,6 @@
private Shader_Delegate mShader;
private PathEffect_Delegate mPathEffect;
private MaskFilter_Delegate mMaskFilter;
- private Rasterizer_Delegate mRasterizer;
private Locale mLocale = Locale.getDefault();
@@ -248,15 +247,6 @@
return mMaskFilter;
}
- /**
- * Returns the {@link Rasterizer} delegate or null if none have been set
- *
- * @return the delegate or null.
- */
- public Rasterizer_Delegate getRasterizer() {
- return mRasterizer;
- }
-
// ---- native methods ----
@LayoutlibDelegate
@@ -898,25 +888,6 @@
}
@LayoutlibDelegate
- /*package*/ static long nSetRasterizer(long native_object, long rasterizer) {
- // get the delegate from the native int.
- Paint_Delegate delegate = sManager.getDelegate(native_object);
- if (delegate == null) {
- return rasterizer;
- }
-
- delegate.mRasterizer = Rasterizer_Delegate.getDelegate(rasterizer);
-
- // since none of those are supported, display a fidelity warning right away
- if (delegate.mRasterizer != null && !delegate.mRasterizer.isSupported()) {
- Bridge.getLog().fidelityWarning(LayoutLog.TAG_RASTERIZER,
- delegate.mRasterizer.getSupportMessage(), null, null /*data*/);
- }
-
- return rasterizer;
- }
-
- @LayoutlibDelegate
/*package*/ static int nGetTextAlign(long native_object) {
// get the delegate from the native int.
Paint_Delegate delegate = sManager.getDelegate(native_object);
@@ -1235,7 +1206,6 @@
mShader = paint.mShader;
mPathEffect = paint.mPathEffect;
mMaskFilter = paint.mMaskFilter;
- mRasterizer = paint.mRasterizer;
mHintingMode = paint.mHintingMode;
if (needsFontUpdate) {
@@ -1262,7 +1232,6 @@
mShader = null;
mPathEffect = null;
mMaskFilter = null;
- mRasterizer = null;
updateFontObject();
mHintingMode = Paint.HINTING_ON;
}
diff --git a/tools/layoutlib/bridge/src/android/graphics/PathMeasure_Delegate.java b/tools/layoutlib/bridge/src/android/graphics/PathMeasure_Delegate.java
index fc9b4f7..7f707c9 100644
--- a/tools/layoutlib/bridge/src/android/graphics/PathMeasure_Delegate.java
+++ b/tools/layoutlib/bridge/src/android/graphics/PathMeasure_Delegate.java
@@ -56,8 +56,8 @@
if (native_path != 0) {
if (forceClosed) {
// Copy the path and call close
- native_path = Path_Delegate.init2(native_path);
- Path_Delegate.native_close(native_path);
+ native_path = Path_Delegate.nInit(native_path);
+ Path_Delegate.nClose(native_path);
}
Path_Delegate pathDelegate = Path_Delegate.getDelegate(native_path);
@@ -108,8 +108,8 @@
if (native_path != 0) {
if (forceClosed) {
// Copy the path and call close
- native_path = Path_Delegate.init2(native_path);
- Path_Delegate.native_close(native_path);
+ native_path = Path_Delegate.nInit(native_path);
+ Path_Delegate.nClose(native_path);
}
Path_Delegate pathDelegate = Path_Delegate.getDelegate(native_path);
@@ -184,28 +184,28 @@
if (type != PathIterator.SEG_MOVETO) {
float[] lastPoint = new float[2];
iterator.getCurrentSegmentEnd(lastPoint);
- Path_Delegate.native_moveTo(native_dst_path, lastPoint[0], lastPoint[1]);
+ Path_Delegate.nMoveTo(native_dst_path, lastPoint[0], lastPoint[1]);
}
}
isZeroLength = isZeroLength && iterator.getCurrentSegmentLength() > 0;
switch (type) {
case PathIterator.SEG_MOVETO:
- Path_Delegate.native_moveTo(native_dst_path, points[0], points[1]);
+ Path_Delegate.nMoveTo(native_dst_path, points[0], points[1]);
break;
case PathIterator.SEG_LINETO:
- Path_Delegate.native_lineTo(native_dst_path, points[0], points[1]);
+ Path_Delegate.nLineTo(native_dst_path, points[0], points[1]);
break;
case PathIterator.SEG_CLOSE:
- Path_Delegate.native_close(native_dst_path);
+ Path_Delegate.nClose(native_dst_path);
break;
case PathIterator.SEG_CUBICTO:
- Path_Delegate.native_cubicTo(native_dst_path, points[0], points[1],
+ Path_Delegate.nCubicTo(native_dst_path, points[0], points[1],
points[2], points[3],
points[4], points[5]);
break;
case PathIterator.SEG_QUADTO:
- Path_Delegate.native_quadTo(native_dst_path, points[0], points[1],
+ Path_Delegate.nQuadTo(native_dst_path, points[0], points[1],
points[2],
points[3]);
break;
diff --git a/tools/layoutlib/bridge/src/android/graphics/Path_Delegate.java b/tools/layoutlib/bridge/src/android/graphics/Path_Delegate.java
index 219c487..579fce0 100644
--- a/tools/layoutlib/bridge/src/android/graphics/Path_Delegate.java
+++ b/tools/layoutlib/bridge/src/android/graphics/Path_Delegate.java
@@ -98,7 +98,7 @@
// ---- native methods ----
@LayoutlibDelegate
- /*package*/ static long init1() {
+ /*package*/ static long nInit() {
// create the delegate
Path_Delegate newDelegate = new Path_Delegate();
@@ -106,7 +106,7 @@
}
@LayoutlibDelegate
- /*package*/ static long init2(long nPath) {
+ /*package*/ static long nInit(long nPath) {
// create the delegate
Path_Delegate newDelegate = new Path_Delegate();
@@ -120,7 +120,7 @@
}
@LayoutlibDelegate
- /*package*/ static void native_reset(long nPath) {
+ /*package*/ static void nReset(long nPath) {
Path_Delegate pathDelegate = sManager.getDelegate(nPath);
if (pathDelegate == null) {
return;
@@ -130,20 +130,20 @@
}
@LayoutlibDelegate
- /*package*/ static void native_rewind(long nPath) {
+ /*package*/ static void nRewind(long nPath) {
// call out to reset since there's nothing to optimize in
// terms of data structs.
- native_reset(nPath);
+ nReset(nPath);
}
@LayoutlibDelegate
- /*package*/ static void native_set(long native_dst, long native_src) {
+ /*package*/ static void nSet(long native_dst, long nSrc) {
Path_Delegate pathDstDelegate = sManager.getDelegate(native_dst);
if (pathDstDelegate == null) {
return;
}
- Path_Delegate pathSrcDelegate = sManager.getDelegate(native_src);
+ Path_Delegate pathSrcDelegate = sManager.getDelegate(nSrc);
if (pathSrcDelegate == null) {
return;
}
@@ -152,14 +152,14 @@
}
@LayoutlibDelegate
- /*package*/ static boolean native_isConvex(long nPath) {
+ /*package*/ static boolean nIsConvex(long nPath) {
Bridge.getLog().fidelityWarning(LayoutLog.TAG_UNSUPPORTED,
"Path.isConvex is not supported.", null, null);
return true;
}
@LayoutlibDelegate
- /*package*/ static int native_getFillType(long nPath) {
+ /*package*/ static int nGetFillType(long nPath) {
Path_Delegate pathDelegate = sManager.getDelegate(nPath);
if (pathDelegate == null) {
return 0;
@@ -169,7 +169,7 @@
}
@LayoutlibDelegate
- public static void native_setFillType(long nPath, int ft) {
+ public static void nSetFillType(long nPath, int ft) {
Path_Delegate pathDelegate = sManager.getDelegate(nPath);
if (pathDelegate == null) {
return;
@@ -179,14 +179,14 @@
}
@LayoutlibDelegate
- /*package*/ static boolean native_isEmpty(long nPath) {
+ /*package*/ static boolean nIsEmpty(long nPath) {
Path_Delegate pathDelegate = sManager.getDelegate(nPath);
return pathDelegate == null || pathDelegate.isEmpty();
}
@LayoutlibDelegate
- /*package*/ static boolean native_isRect(long nPath, RectF rect) {
+ /*package*/ static boolean nIsRect(long nPath, RectF rect) {
Path_Delegate pathDelegate = sManager.getDelegate(nPath);
if (pathDelegate == null) {
return false;
@@ -206,7 +206,7 @@
}
@LayoutlibDelegate
- /*package*/ static void native_computeBounds(long nPath, RectF bounds) {
+ /*package*/ static void nComputeBounds(long nPath, RectF bounds) {
Path_Delegate pathDelegate = sManager.getDelegate(nPath);
if (pathDelegate == null) {
return;
@@ -216,13 +216,13 @@
}
@LayoutlibDelegate
- /*package*/ static void native_incReserve(long nPath, int extraPtCount) {
+ /*package*/ static void nIncReserve(long nPath, int extraPtCount) {
// since we use a java2D path, there's no way to pre-allocate new points,
// so we do nothing.
}
@LayoutlibDelegate
- /*package*/ static void native_moveTo(long nPath, float x, float y) {
+ /*package*/ static void nMoveTo(long nPath, float x, float y) {
Path_Delegate pathDelegate = sManager.getDelegate(nPath);
if (pathDelegate == null) {
return;
@@ -232,7 +232,7 @@
}
@LayoutlibDelegate
- /*package*/ static void native_rMoveTo(long nPath, float dx, float dy) {
+ /*package*/ static void nRMoveTo(long nPath, float dx, float dy) {
Path_Delegate pathDelegate = sManager.getDelegate(nPath);
if (pathDelegate == null) {
return;
@@ -242,7 +242,7 @@
}
@LayoutlibDelegate
- /*package*/ static void native_lineTo(long nPath, float x, float y) {
+ /*package*/ static void nLineTo(long nPath, float x, float y) {
Path_Delegate pathDelegate = sManager.getDelegate(nPath);
if (pathDelegate == null) {
return;
@@ -252,7 +252,7 @@
}
@LayoutlibDelegate
- /*package*/ static void native_rLineTo(long nPath, float dx, float dy) {
+ /*package*/ static void nRLineTo(long nPath, float dx, float dy) {
Path_Delegate pathDelegate = sManager.getDelegate(nPath);
if (pathDelegate == null) {
return;
@@ -262,7 +262,7 @@
}
@LayoutlibDelegate
- /*package*/ static void native_quadTo(long nPath, float x1, float y1, float x2, float y2) {
+ /*package*/ static void nQuadTo(long nPath, float x1, float y1, float x2, float y2) {
Path_Delegate pathDelegate = sManager.getDelegate(nPath);
if (pathDelegate == null) {
return;
@@ -272,7 +272,7 @@
}
@LayoutlibDelegate
- /*package*/ static void native_rQuadTo(long nPath, float dx1, float dy1, float dx2, float dy2) {
+ /*package*/ static void nRQuadTo(long nPath, float dx1, float dy1, float dx2, float dy2) {
Path_Delegate pathDelegate = sManager.getDelegate(nPath);
if (pathDelegate == null) {
return;
@@ -282,7 +282,7 @@
}
@LayoutlibDelegate
- /*package*/ static void native_cubicTo(long nPath, float x1, float y1,
+ /*package*/ static void nCubicTo(long nPath, float x1, float y1,
float x2, float y2, float x3, float y3) {
Path_Delegate pathDelegate = sManager.getDelegate(nPath);
if (pathDelegate == null) {
@@ -293,7 +293,7 @@
}
@LayoutlibDelegate
- /*package*/ static void native_rCubicTo(long nPath, float x1, float y1,
+ /*package*/ static void nRCubicTo(long nPath, float x1, float y1,
float x2, float y2, float x3, float y3) {
Path_Delegate pathDelegate = sManager.getDelegate(nPath);
if (pathDelegate == null) {
@@ -304,7 +304,7 @@
}
@LayoutlibDelegate
- /*package*/ static void native_arcTo(long nPath, float left, float top, float right,
+ /*package*/ static void nArcTo(long nPath, float left, float top, float right,
float bottom,
float startAngle, float sweepAngle, boolean forceMoveTo) {
Path_Delegate pathDelegate = sManager.getDelegate(nPath);
@@ -316,7 +316,7 @@
}
@LayoutlibDelegate
- /*package*/ static void native_close(long nPath) {
+ /*package*/ static void nClose(long nPath) {
Path_Delegate pathDelegate = sManager.getDelegate(nPath);
if (pathDelegate == null) {
return;
@@ -326,7 +326,7 @@
}
@LayoutlibDelegate
- /*package*/ static void native_addRect(long nPath,
+ /*package*/ static void nAddRect(long nPath,
float left, float top, float right, float bottom, int dir) {
Path_Delegate pathDelegate = sManager.getDelegate(nPath);
if (pathDelegate == null) {
@@ -337,7 +337,7 @@
}
@LayoutlibDelegate
- /*package*/ static void native_addOval(long nPath, float left, float top, float right,
+ /*package*/ static void nAddOval(long nPath, float left, float top, float right,
float bottom, int dir) {
Path_Delegate pathDelegate = sManager.getDelegate(nPath);
if (pathDelegate == null) {
@@ -349,7 +349,7 @@
}
@LayoutlibDelegate
- /*package*/ static void native_addCircle(long nPath, float x, float y, float radius, int dir) {
+ /*package*/ static void nAddCircle(long nPath, float x, float y, float radius, int dir) {
Path_Delegate pathDelegate = sManager.getDelegate(nPath);
if (pathDelegate == null) {
return;
@@ -361,7 +361,7 @@
}
@LayoutlibDelegate
- /*package*/ static void native_addArc(long nPath, float left, float top, float right,
+ /*package*/ static void nAddArc(long nPath, float left, float top, float right,
float bottom, float startAngle, float sweepAngle) {
Path_Delegate pathDelegate = sManager.getDelegate(nPath);
if (pathDelegate == null) {
@@ -375,7 +375,7 @@
}
@LayoutlibDelegate
- /*package*/ static void native_addRoundRect(long nPath, float left, float top, float right,
+ /*package*/ static void nAddRoundRect(long nPath, float left, float top, float right,
float bottom, float rx, float ry, int dir) {
Path_Delegate pathDelegate = sManager.getDelegate(nPath);
@@ -388,7 +388,7 @@
}
@LayoutlibDelegate
- /*package*/ static void native_addRoundRect(long nPath, float left, float top, float right,
+ /*package*/ static void nAddRoundRect(long nPath, float left, float top, float right,
float bottom, float[] radii, int dir) {
Path_Delegate pathDelegate = sManager.getDelegate(nPath);
@@ -405,17 +405,17 @@
}
@LayoutlibDelegate
- /*package*/ static void native_addPath(long nPath, long src, float dx, float dy) {
+ /*package*/ static void nAddPath(long nPath, long src, float dx, float dy) {
addPath(nPath, src, AffineTransform.getTranslateInstance(dx, dy));
}
@LayoutlibDelegate
- /*package*/ static void native_addPath(long nPath, long src) {
+ /*package*/ static void nAddPath(long nPath, long src) {
addPath(nPath, src, null /*transform*/);
}
@LayoutlibDelegate
- /*package*/ static void native_addPath(long nPath, long src, long matrix) {
+ /*package*/ static void nAddPath(long nPath, long src, long matrix) {
Matrix_Delegate matrixDelegate = Matrix_Delegate.getDelegate(matrix);
if (matrixDelegate == null) {
return;
@@ -425,7 +425,7 @@
}
@LayoutlibDelegate
- /*package*/ static void native_offset(long nPath, float dx, float dy) {
+ /*package*/ static void nOffset(long nPath, float dx, float dy) {
Path_Delegate pathDelegate = sManager.getDelegate(nPath);
if (pathDelegate == null) {
return;
@@ -435,7 +435,7 @@
}
@LayoutlibDelegate
- /*package*/ static void native_setLastPoint(long nPath, float dx, float dy) {
+ /*package*/ static void nSetLastPoint(long nPath, float dx, float dy) {
Path_Delegate pathDelegate = sManager.getDelegate(nPath);
if (pathDelegate == null) {
return;
@@ -446,7 +446,7 @@
}
@LayoutlibDelegate
- /*package*/ static void native_transform(long nPath, long matrix,
+ /*package*/ static void nTransform(long nPath, long matrix,
long dst_path) {
Path_Delegate pathDelegate = sManager.getDelegate(nPath);
if (pathDelegate == null) {
@@ -465,23 +465,23 @@
}
@LayoutlibDelegate
- /*package*/ static void native_transform(long nPath, long matrix) {
- native_transform(nPath, matrix, 0);
+ /*package*/ static void nTransform(long nPath, long matrix) {
+ nTransform(nPath, matrix, 0);
}
@LayoutlibDelegate
- /*package*/ static boolean native_op(long nPath1, long nPath2, int op, long result) {
+ /*package*/ static boolean nOp(long nPath1, long nPath2, int op, long result) {
Bridge.getLog().error(LayoutLog.TAG_UNSUPPORTED, "Path.op() not supported", null);
return false;
}
@LayoutlibDelegate
- /*package*/ static void finalizer(long nPath) {
+ /*package*/ static void nFinalize(long nPath) {
sManager.removeJavaReferenceFor(nPath);
}
@LayoutlibDelegate
- /*package*/ static float[] native_approximate(long nPath, float error) {
+ /*package*/ static float[] nApproximate(long nPath, float error) {
Path_Delegate pathDelegate = sManager.getDelegate(nPath);
if (pathDelegate == null) {
return null;
diff --git a/tools/layoutlib/bridge/src/android/graphics/Rasterizer_Delegate.java b/tools/layoutlib/bridge/src/android/graphics/Rasterizer_Delegate.java
deleted file mode 100644
index a742840..0000000
--- a/tools/layoutlib/bridge/src/android/graphics/Rasterizer_Delegate.java
+++ /dev/null
@@ -1,64 +0,0 @@
-/*
- * Copyright (C) 2010 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 android.graphics;
-
-import com.android.layoutlib.bridge.impl.DelegateManager;
-import com.android.tools.layoutlib.annotations.LayoutlibDelegate;
-
-/**
- * Delegate implementing the native methods of android.graphics.Rasterizer
- *
- * Through the layoutlib_create tool, the original native methods of Rasterizer have been replaced
- * by calls to methods of the same name in this delegate class.
- *
- * This class behaves like the original native implementation, but in Java, keeping previously
- * native data into its own objects and mapping them to int that are sent back and forth between
- * it and the original Rasterizer class.
- *
- * This also serve as a base class for all Rasterizer delegate classes.
- *
- * @see DelegateManager
- *
- */
-public abstract class Rasterizer_Delegate {
-
- // ---- delegate manager ----
- protected static final DelegateManager<Rasterizer_Delegate> sManager =
- new DelegateManager<Rasterizer_Delegate>(Rasterizer_Delegate.class);
-
- // ---- delegate helper data ----
-
- // ---- delegate data ----
-
- // ---- Public Helper methods ----
-
- public static Rasterizer_Delegate getDelegate(long nativeShader) {
- return sManager.getDelegate(nativeShader);
- }
-
- public abstract boolean isSupported();
- public abstract String getSupportMessage();
-
- // ---- native methods ----
-
- @LayoutlibDelegate
- /*package*/ static void finalizer(long native_instance) {
- sManager.removeJavaReferenceFor(native_instance);
- }
-
- // ---- Private delegate/helper methods ----
-}
diff --git a/tools/layoutlib/bridge/src/android/graphics/drawable/VectorDrawable_Delegate.java b/tools/layoutlib/bridge/src/android/graphics/drawable/VectorDrawable_Delegate.java
index cee679a..430607a 100644
--- a/tools/layoutlib/bridge/src/android/graphics/drawable/VectorDrawable_Delegate.java
+++ b/tools/layoutlib/bridge/src/android/graphics/drawable/VectorDrawable_Delegate.java
@@ -1197,7 +1197,7 @@
assert fillPaintDelegate != null;
fillPaintDelegate.setColorFilter(filterPtr);
fillPaintDelegate.setShader(fullPath.mFillGradient);
- Path_Delegate.native_setFillType(mRenderPath.mNativePath, fullPath.mFillType);
+ Path_Delegate.nSetFillType(mRenderPath.mNativePath, fullPath.mFillType);
BaseCanvas_Delegate.nDrawPath(canvasPtr, mRenderPath.mNativePath, fillPaint
.getNativeInstance());
}
diff --git a/tools/layoutlib/bridge/src/android/view/IWindowManagerImpl.java b/tools/layoutlib/bridge/src/android/view/IWindowManagerImpl.java
index 4b9815d..71c1117 100644
--- a/tools/layoutlib/bridge/src/android/view/IWindowManagerImpl.java
+++ b/tools/layoutlib/bridge/src/android/view/IWindowManagerImpl.java
@@ -77,14 +77,6 @@
// ---- unused implementation of IWindowManager ----
@Override
- public void addAppToken(int addPos, IApplicationToken token, int taskId,
- int requestedOrientation, boolean fullscreen, boolean showWhenLocked, int configChanges,
- boolean voiceInteraction, boolean launchTaskBehind, boolean alwaysFocusable,
- int targetSdkVersion, int rotationAnimationHint) throws RemoteException {
- // TODO Auto-generated method stub
- }
-
- @Override
public void addWindowToken(IBinder arg0, int arg1, int arg2) throws RemoteException {
// TODO Auto-generated method stub
@@ -159,12 +151,6 @@
}
@Override
- public int getAppOrientation(IApplicationToken arg0) throws RemoteException {
- // TODO Auto-generated method stub
- return 0;
- }
-
- @Override
public int getPendingAppTransition() throws RemoteException {
// TODO Auto-generated method stub
return 0;
@@ -258,12 +244,6 @@
}
@Override
- public void pauseKeyDispatching(IBinder arg0) throws RemoteException {
- // TODO Auto-generated method stub
-
- }
-
- @Override
public void prepareAppTransition(int arg0, boolean arg1) throws RemoteException {
// TODO Auto-generated method stub
@@ -276,24 +256,12 @@
}
@Override
- public void removeAppToken(IBinder arg0, int arg1) throws RemoteException {
- // TODO Auto-generated method stub
-
- }
-
- @Override
public void removeWindowToken(IBinder arg0, int arg1) throws RemoteException {
// TODO Auto-generated method stub
}
@Override
- public void resumeKeyDispatching(IBinder arg0) throws RemoteException {
- // TODO Auto-generated method stub
-
- }
-
- @Override
public boolean requestAssistScreenshot(IAssistScreenshotReceiver receiver)
throws RemoteException {
// TODO Auto-generated method stub
@@ -301,13 +269,6 @@
}
@Override
- public Bitmap screenshotApplications(IBinder appToken, int displayId, int maxWidth,
- int maxHeight, float frameScale) throws RemoteException {
- // TODO Auto-generated method stub
- return null;
- }
-
- @Override
public void setAnimationScale(int arg0, float arg1) throws RemoteException {
// TODO Auto-generated method stub
@@ -325,41 +286,6 @@
}
@Override
- public void addAppToTask(IBinder arg0, int arg1) throws RemoteException {
- // TODO Auto-generated method stub
- }
-
- @Override
- public void setAppOrientation(IApplicationToken arg0, int arg1) throws RemoteException {
- // TODO Auto-generated method stub
- }
-
- @Override
- public boolean setAppStartingWindow(IBinder arg0, String arg1, int arg2, CompatibilityInfo arg3,
- CharSequence arg4, int arg5, int arg6, int arg7, int arg8, IBinder arg9, boolean arg10)
- throws RemoteException {
- // TODO Auto-generated method stub
- return false;
- }
-
- @Override
- public void setAppVisibility(IBinder arg0, boolean arg1) throws RemoteException {
- // TODO Auto-generated method stub
-
- }
-
- @Override
- public void notifyAppResumed(IBinder token, boolean wasStopped, boolean allowSavedSurface)
- throws RemoteException {
- // TODO Auto-generated method stub
- }
-
- @Override
- public void notifyAppStopped(IBinder token) throws RemoteException {
- // TODO Auto-generated method stub
- }
-
- @Override
public void setEventDispatching(boolean arg0) throws RemoteException {
// TODO Auto-generated method stub
}
@@ -443,11 +369,6 @@
}
@Override
- public void startAppFreezingScreen(IBinder arg0, int arg1) throws RemoteException {
- // TODO Auto-generated method stub
- }
-
- @Override
public boolean startViewServer(int arg0) throws RemoteException {
// TODO Auto-generated method stub
return false;
@@ -469,11 +390,6 @@
}
@Override
- public void stopAppFreezingScreen(IBinder arg0, boolean arg1) throws RemoteException {
- // TODO Auto-generated method stub
- }
-
- @Override
public boolean stopViewServer() throws RemoteException {
// TODO Auto-generated method stub
return false;
diff --git a/tools/layoutlib/create/src/com/android/tools/layoutlib/create/CreateInfo.java b/tools/layoutlib/create/src/com/android/tools/layoutlib/create/CreateInfo.java
index a23bad6..92fd75cc 100644
--- a/tools/layoutlib/create/src/com/android/tools/layoutlib/create/CreateInfo.java
+++ b/tools/layoutlib/create/src/com/android/tools/layoutlib/create/CreateInfo.java
@@ -263,7 +263,6 @@
"android.graphics.DrawFilter",
"android.graphics.EmbossMaskFilter",
"android.graphics.FontFamily",
- "android.graphics.LayerRasterizer",
"android.graphics.LightingColorFilter",
"android.graphics.LinearGradient",
"android.graphics.MaskFilter",
@@ -277,7 +276,6 @@
"android.graphics.PathMeasure",
"android.graphics.PorterDuffColorFilter",
"android.graphics.RadialGradient",
- "android.graphics.Rasterizer",
"android.graphics.Region",
"android.graphics.Shader",
"android.graphics.SumPathEffect",
diff --git a/wifi/java/android/net/wifi/IWifiManager.aidl b/wifi/java/android/net/wifi/IWifiManager.aidl
index 9e897bf..18c1245 100644
--- a/wifi/java/android/net/wifi/IWifiManager.aidl
+++ b/wifi/java/android/net/wifi/IWifiManager.aidl
@@ -59,7 +59,7 @@
int addOrUpdateNetwork(in WifiConfiguration config);
- boolean addPasspointConfiguration(in PasspointConfiguration config);
+ boolean addOrUpdatePasspointConfiguration(in PasspointConfiguration config);
boolean removePasspointConfiguration(in String fqdn);
diff --git a/wifi/java/android/net/wifi/WifiConfiguration.java b/wifi/java/android/net/wifi/WifiConfiguration.java
index 3b7f721..958279b 100644
--- a/wifi/java/android/net/wifi/WifiConfiguration.java
+++ b/wifi/java/android/net/wifi/WifiConfiguration.java
@@ -608,6 +608,7 @@
* if there has been a report of it having no internet access, and, it never have had
* internet access in the past.
*/
+ @SystemApi
public boolean hasNoInternetAccess() {
return numNoInternetAccessReports > 0 && !validatedInternetAccess;
}
@@ -621,6 +622,17 @@
public boolean noInternetAccessExpected;
/**
+ * The WiFi configuration is expected not to have Internet access (e.g., a wireless printer, a
+ * Chromecast hotspot, etc.). This will be set if the user explicitly confirms a connection to
+ * this configuration and selects "don't ask again".
+ * @hide
+ */
+ @SystemApi
+ public boolean isNoInternetAccessExpected() {
+ return noInternetAccessExpected;
+ }
+
+ /**
* @hide
* Last time the system was connected to this configuration.
*/
diff --git a/wifi/java/android/net/wifi/WifiManager.java b/wifi/java/android/net/wifi/WifiManager.java
index 674c161..88820cd 100644
--- a/wifi/java/android/net/wifi/WifiManager.java
+++ b/wifi/java/android/net/wifi/WifiManager.java
@@ -842,31 +842,31 @@
}
/**
- * Add a Passpoint configuration. The configuration provides a credential
+ * Add or update a Passpoint configuration. The configuration provides a credential
* for connecting to Passpoint networks that are operated by the Passpoint
* service provider specified in the configuration.
*
* Each configuration is uniquely identified by its FQDN (Fully Qualified Domain
- * Name). In the case when there is an existing configuration with the same base
- * domain, the new configuration will replace the existing configuration.
+ * Name). In the case when there is an existing configuration with the same
+ * FQDN, the new configuration will replace the existing configuration.
*
* @param config The Passpoint configuration to be added
- * @return true on success or false on failure
+ * @return true on success
* @hide
*/
- public boolean addPasspointConfiguration(PasspointConfiguration config) {
+ public boolean addOrUpdatePasspointConfiguration(PasspointConfiguration config) {
try {
- return mService.addPasspointConfiguration(config);
+ return mService.addOrUpdatePasspointConfiguration(config);
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
}
/**
- * Remove a Passpoint configuration identified by its FQDN (Fully Qualified Domain Name).
+ * Remove the Passpoint configuration identified by its FQDN (Fully Qualified Domain Name).
*
* @param fqdn The FQDN of the passpoint configuration to be removed
- * @return true on success or false on failure
+ * @return true on success
* @hide
*/
public boolean removePasspointConfiguration(String fqdn) {
@@ -880,7 +880,9 @@
/**
* Return the list of installed Passpoint configurations.
*
- * @return A list of PasspointConfiguration or null
+ * An empty list will be returned when no configurations are installed.
+ *
+ * @return A list of {@link PasspointConfiguration}
* @hide
*/
public List<PasspointConfiguration> getPasspointConfigurations() {
@@ -1763,6 +1765,7 @@
* Interface for callback invocation on an application action
* @hide
*/
+ @SystemApi
public interface ActionListener {
/** The operation succeeded */
public void onSuccess();
@@ -1974,6 +1977,7 @@
*
* @hide
*/
+ @SystemApi
public void connect(WifiConfiguration config, ActionListener listener) {
if (config == null) throw new IllegalArgumentException("config cannot be null");
// Use INVALID_NETWORK_ID for arg1 when passing a config object
diff --git a/wifi/java/android/net/wifi/aware/WifiAwareAttachCallback.java b/wifi/java/android/net/wifi/aware/AttachCallback.java
similarity index 78%
rename from wifi/java/android/net/wifi/aware/WifiAwareAttachCallback.java
rename to wifi/java/android/net/wifi/aware/AttachCallback.java
index 1e8dbd9..90216f3 100644
--- a/wifi/java/android/net/wifi/aware/WifiAwareAttachCallback.java
+++ b/wifi/java/android/net/wifi/aware/AttachCallback.java
@@ -18,16 +18,16 @@
/**
* Base class for Aware attach callbacks. Should be extended by applications and set when calling
- * {@link WifiAwareManager#attach(WifiAwareAttachCallback, android.os.Handler)}. These are callbacks
+ * {@link WifiAwareManager#attach(AttachCallback, android.os.Handler)}. These are callbacks
* applying to the Aware connection as a whole - not to specific publish or subscribe sessions -
- * for that see {@link WifiAwareDiscoverySessionCallback}.
+ * for that see {@link DiscoverySessionCallback}.
*
* @hide PROPOSED_AWARE_API
*/
-public class WifiAwareAttachCallback {
+public class AttachCallback {
/**
* Called when Aware attach operation
- * {@link WifiAwareManager#attach(WifiAwareAttachCallback, android.os.Handler)}
+ * {@link WifiAwareManager#attach(AttachCallback, android.os.Handler)}
* is completed and that we can now start discovery sessions or connections.
*
* @param session The Aware object on which we can execute further Aware operations - e.g.
@@ -39,7 +39,7 @@
/**
* Called when Aware attach operation
- * {@link WifiAwareManager#attach(WifiAwareAttachCallback, android.os.Handler)} failed.
+ * {@link WifiAwareManager#attach(AttachCallback, android.os.Handler)} failed.
*/
public void onAttachFailed() {
/* empty */
diff --git a/wifi/java/android/net/wifi/aware/WifiAwareCharacteristics.aidl b/wifi/java/android/net/wifi/aware/Characteristics.aidl
similarity index 94%
rename from wifi/java/android/net/wifi/aware/WifiAwareCharacteristics.aidl
rename to wifi/java/android/net/wifi/aware/Characteristics.aidl
index a35e71d..77305e9 100644
--- a/wifi/java/android/net/wifi/aware/WifiAwareCharacteristics.aidl
+++ b/wifi/java/android/net/wifi/aware/Characteristics.aidl
@@ -16,4 +16,4 @@
package android.net.wifi.aware;
-parcelable WifiAwareCharacteristics;
+parcelable Characteristics;
diff --git a/wifi/java/android/net/wifi/aware/WifiAwareCharacteristics.java b/wifi/java/android/net/wifi/aware/Characteristics.java
similarity index 83%
rename from wifi/java/android/net/wifi/aware/WifiAwareCharacteristics.java
rename to wifi/java/android/net/wifi/aware/Characteristics.java
index 092aa34..1c3e390 100644
--- a/wifi/java/android/net/wifi/aware/WifiAwareCharacteristics.java
+++ b/wifi/java/android/net/wifi/aware/Characteristics.java
@@ -25,7 +25,7 @@
*
* @hide PROPOSED_AWARE_API
*/
-public class WifiAwareCharacteristics implements Parcelable {
+public class Characteristics implements Parcelable {
/** @hide */
public static final String KEY_MAX_SERVICE_NAME_LENGTH = "key_max_service_name_length";
/** @hide */
@@ -37,7 +37,7 @@
private Bundle mCharacteristics = new Bundle();
/** @hide : should not be created by apps */
- public WifiAwareCharacteristics(Bundle characteristics) {
+ public Characteristics(Bundle characteristics) {
mCharacteristics = characteristics;
}
@@ -58,7 +58,7 @@
* message exchange. Restricts the parameters of the
* {@link PublishConfig.Builder#setServiceSpecificInfo(byte[])},
* {@link SubscribeConfig.Builder#setServiceSpecificInfo(byte[])}, and
- * {@link WifiAwareDiscoveryBaseSession#sendMessage(WifiAwareManager.PeerHandle, int, byte[])}
+ * {@link DiscoverySession#sendMessage(PeerHandle, int, byte[])}
* variants.
*
* @return A positive integer, maximum length of byte array for Aware messaging.
@@ -89,17 +89,17 @@
return 0;
}
- public static final Creator<WifiAwareCharacteristics> CREATOR =
- new Creator<WifiAwareCharacteristics>() {
+ public static final Creator<Characteristics> CREATOR =
+ new Creator<Characteristics>() {
@Override
- public WifiAwareCharacteristics createFromParcel(Parcel in) {
- WifiAwareCharacteristics c = new WifiAwareCharacteristics(in.readBundle());
+ public Characteristics createFromParcel(Parcel in) {
+ Characteristics c = new Characteristics(in.readBundle());
return c;
}
@Override
- public WifiAwareCharacteristics[] newArray(int size) {
- return new WifiAwareCharacteristics[size];
+ public Characteristics[] newArray(int size) {
+ return new Characteristics[size];
}
};
}
diff --git a/wifi/java/android/net/wifi/aware/ConfigRequest.java b/wifi/java/android/net/wifi/aware/ConfigRequest.java
index 4b21b15..6a5957b 100644
--- a/wifi/java/android/net/wifi/aware/ConfigRequest.java
+++ b/wifi/java/android/net/wifi/aware/ConfigRequest.java
@@ -22,7 +22,7 @@
/**
* Defines a request object to configure a Wi-Fi Aware network. Built using
* {@link ConfigRequest.Builder}. Configuration is requested using
- * {@link WifiAwareManager#attach(WifiAwareAttachCallback, android.os.Handler)}.
+ * {@link WifiAwareManager#attach(AttachCallback, android.os.Handler)}.
* Note that the actual achieved configuration may be different from the
* requested configuration - since different applications may request different
* configurations.
diff --git a/wifi/java/android/net/wifi/aware/WifiAwareDiscoveryBaseSession.java b/wifi/java/android/net/wifi/aware/DiscoverySession.java
similarity index 79%
rename from wifi/java/android/net/wifi/aware/WifiAwareDiscoveryBaseSession.java
rename to wifi/java/android/net/wifi/aware/DiscoverySession.java
index 2812ad4..c89718f 100644
--- a/wifi/java/android/net/wifi/aware/WifiAwareDiscoveryBaseSession.java
+++ b/wifi/java/android/net/wifi/aware/DiscoverySession.java
@@ -29,21 +29,21 @@
/**
* A class representing a single publish or subscribe Aware session. This object
* will not be created directly - only its child classes are available:
- * {@link WifiAwarePublishDiscoverySession} and {@link WifiAwareSubscribeDiscoverySession}. This
+ * {@link PublishDiscoverySession} and {@link SubscribeDiscoverySession}. This
* class provides functionality common to both publish and subscribe discovery sessions:
* <ul>
- * <li>Sending messages: {@link #sendMessage(WifiAwareManager.PeerHandle, int, byte[])} or
- * {@link #sendMessage(WifiAwareManager.PeerHandle, int, byte[], int)} methods.
+ * <li>Sending messages: {@link #sendMessage(PeerHandle, int, byte[])} or
+ * {@link #sendMessage(PeerHandle, int, byte[], int)} methods.
* <li>Creating a network-specifier when requesting a Aware connection:
- * {@link #createNetworkSpecifier(WifiAwareManager.PeerHandle, byte[])}.
+ * {@link #createNetworkSpecifier(PeerHandle, byte[])}.
* </ul>
* The {@link #destroy()} method must be called to destroy discovery sessions once they are
* no longer needed.
*
* @hide PROPOSED_AWARE_API
*/
-public class WifiAwareDiscoveryBaseSession {
- private static final String TAG = "WifiAwareDiscBaseSsn";
+public class DiscoverySession {
+ private static final String TAG = "DiscoverySession";
private static final boolean DBG = false;
private static final boolean VDBG = false; // STOPSHIP if true
@@ -62,7 +62,7 @@
/**
* Return the maximum permitted retry count when sending messages using
- * {@link #sendMessage(WifiAwareManager.PeerHandle, int, byte[], int)}.
+ * {@link #sendMessage(PeerHandle, int, byte[], int)}.
*
* @return Maximum retry count when sending messages.
*/
@@ -71,7 +71,7 @@
}
/** @hide */
- public WifiAwareDiscoveryBaseSession(WifiAwareManager manager, int clientId, int sessionId) {
+ public DiscoverySession(WifiAwareManager manager, int clientId, int sessionId) {
if (VDBG) {
Log.v(TAG, "New discovery session created: manager=" + manager + ", clientId="
+ clientId + ", sessionId=" + sessionId);
@@ -93,7 +93,7 @@
* This operation must be done on a session which is no longer needed. Otherwise system
* resources will continue to be utilized until the application exits. The only
* exception is a session for which we received a termination callback,
- * {@link WifiAwareDiscoverySessionCallback#onSessionTerminated(int)}.
+ * {@link DiscoverySessionCallback#onSessionTerminated()}.
*/
public void destroy() {
WifiAwareManager mgr = mMgr.get();
@@ -139,23 +139,23 @@
/**
* Sends a message to the specified destination. Aware messages are transmitted in the context
* of a discovery session - executed subsequent to a publish/subscribe
- * {@link WifiAwareDiscoverySessionCallback#onServiceDiscovered(WifiAwareManager.PeerHandle,
+ * {@link DiscoverySessionCallback#onServiceDiscovered(PeerHandle,
* byte[], java.util.List)} event.
* <p>
* Aware messages are not guaranteed delivery. Callbacks on
- * {@link WifiAwareDiscoverySessionCallback} indicate message was transmitted successfully,
- * {@link WifiAwareDiscoverySessionCallback#onMessageSendSucceeded(int)}, or transmission
+ * {@link DiscoverySessionCallback} indicate message was transmitted successfully,
+ * {@link DiscoverySessionCallback#onMessageSendSucceeded(int)}, or transmission
* failed (possibly after several retries) -
- * {@link WifiAwareDiscoverySessionCallback#onMessageSendFailed(int)}.
+ * {@link DiscoverySessionCallback#onMessageSendFailed(int)}.
* <p>
* The peer will get a callback indicating a message was received using
- * {@link WifiAwareDiscoverySessionCallback#onMessageReceived(WifiAwareManager.PeerHandle,
+ * {@link DiscoverySessionCallback#onMessageReceived(PeerHandle,
* byte[])}.
*
* @param peerHandle The peer's handle for the message. Must be a result of an
- * {@link WifiAwareDiscoverySessionCallback#onServiceDiscovered(WifiAwareManager.PeerHandle,
+ * {@link DiscoverySessionCallback#onServiceDiscovered(PeerHandle,
* byte[], java.util.List)} or
- * {@link WifiAwareDiscoverySessionCallback#onMessageReceived(WifiAwareManager.PeerHandle,
+ * {@link DiscoverySessionCallback#onMessageReceived(PeerHandle,
* byte[])} events.
* @param messageId An arbitrary integer used by the caller to identify the message. The same
* integer ID will be returned in the callbacks indicating message send success or
@@ -167,7 +167,7 @@
* (note: no retransmissions are attempted in other failure cases). A value of 0
* indicates no retries. Max permitted value is {@link #getMaxSendRetryCount()}.
*/
- public void sendMessage(@NonNull WifiAwareManager.PeerHandle peerHandle, int messageId,
+ public void sendMessage(@NonNull PeerHandle peerHandle, int messageId,
@Nullable byte[] message, int retryCount) {
if (mTerminated) {
Log.w(TAG, "sendMessage: called on terminated session");
@@ -186,25 +186,25 @@
/**
* Sends a message to the specified destination. Aware messages are transmitted in the context
* of a discovery session - executed subsequent to a publish/subscribe
- * {@link WifiAwareDiscoverySessionCallback#onServiceDiscovered(WifiAwareManager.PeerHandle,
+ * {@link DiscoverySessionCallback#onServiceDiscovered(PeerHandle,
* byte[], java.util.List)} event.
* <p>
* Aware messages are not guaranteed delivery. Callbacks on
- * {@link WifiAwareDiscoverySessionCallback} indicate message was transmitted successfully,
- * {@link WifiAwareDiscoverySessionCallback#onMessageSendSucceeded(int)}, or transmission
+ * {@link DiscoverySessionCallback} indicate message was transmitted successfully,
+ * {@link DiscoverySessionCallback#onMessageSendSucceeded(int)}, or transmission
* failed (possibly after several retries) -
- * {@link WifiAwareDiscoverySessionCallback#onMessageSendFailed(int)}.
+ * {@link DiscoverySessionCallback#onMessageSendFailed(int)}.
* <p>
* The peer will get a callback indicating a message was received using
- * {@link WifiAwareDiscoverySessionCallback#onMessageReceived(WifiAwareManager.PeerHandle,
+ * {@link DiscoverySessionCallback#onMessageReceived(PeerHandle,
* byte[])}.
- * Equivalent to {@link #sendMessage(WifiAwareManager.PeerHandle, int, byte[], int)}
+ * Equivalent to {@link #sendMessage(PeerHandle, int, byte[], int)}
* with a {@code retryCount} of 0.
*
* @param peerHandle The peer's handle for the message. Must be a result of an
- * {@link WifiAwareDiscoverySessionCallback#onServiceDiscovered(WifiAwareManager.PeerHandle,
+ * {@link DiscoverySessionCallback#onServiceDiscovered(PeerHandle,
* byte[], java.util.List)} or
- * {@link WifiAwareDiscoverySessionCallback#onMessageReceived(WifiAwareManager.PeerHandle,
+ * {@link DiscoverySessionCallback#onMessageReceived(PeerHandle,
* byte[])} events.
* @param messageId An arbitrary integer used by the caller to identify the message. The same
* integer ID will be returned in the callbacks indicating message send success or
@@ -212,16 +212,16 @@
* can be arbitrary and non-unique.
* @param message The message to be transmitted.
*/
- public void sendMessage(@NonNull WifiAwareManager.PeerHandle peerHandle, int messageId,
+ public void sendMessage(@NonNull PeerHandle peerHandle, int messageId,
@Nullable byte[] message) {
sendMessage(peerHandle, messageId, message, 0);
}
/**
* Start a ranging operation with the specified peers. The peer IDs are obtained from an
- * {@link WifiAwareDiscoverySessionCallback#onServiceDiscovered(WifiAwareManager.PeerHandle,
+ * {@link DiscoverySessionCallback#onServiceDiscovered(PeerHandle,
* byte[], java.util.List)} or
- * {@link WifiAwareDiscoverySessionCallback#onMessageReceived(WifiAwareManager.PeerHandle,
+ * {@link DiscoverySessionCallback#onMessageReceived(PeerHandle,
* byte[])} operation - can
* only range devices which are part of an ongoing discovery session.
*
@@ -265,9 +265,9 @@
* and a Publisher is a RESPONDER.
*
* @param peerHandle The peer's handle obtained through
- * {@link WifiAwareDiscoverySessionCallback#onServiceDiscovered(WifiAwareManager.PeerHandle,
+ * {@link DiscoverySessionCallback#onServiceDiscovered(PeerHandle,
* byte[], java.util.List)} or
- * {@link WifiAwareDiscoverySessionCallback#onMessageReceived(WifiAwareManager.PeerHandle,
+ * {@link DiscoverySessionCallback#onMessageReceived(PeerHandle,
* byte[])}. On a RESPONDER this value is used to gate the acceptance of a connection request
* from only that peer. A RESPONDER may specified a null - indicating that
* it will accept connection requests from any device.
@@ -283,7 +283,7 @@
* android.net.ConnectivityManager.NetworkCallback)}
* [or other varieties of that API].
*/
- public String createNetworkSpecifier(@Nullable WifiAwareManager.PeerHandle peerHandle,
+ public String createNetworkSpecifier(@Nullable PeerHandle peerHandle,
@Nullable byte[] token) {
if (mTerminated) {
Log.w(TAG, "createNetworkSpecifier: called on terminated session");
@@ -295,7 +295,7 @@
return null;
}
- int role = this instanceof WifiAwareSubscribeDiscoverySession
+ int role = this instanceof SubscribeDiscoverySession
? WifiAwareManager.WIFI_AWARE_DATA_PATH_ROLE_INITIATOR
: WifiAwareManager.WIFI_AWARE_DATA_PATH_ROLE_RESPONDER;
diff --git a/wifi/java/android/net/wifi/aware/DiscoverySessionCallback.java b/wifi/java/android/net/wifi/aware/DiscoverySessionCallback.java
new file mode 100644
index 0000000..1fe449f
--- /dev/null
+++ b/wifi/java/android/net/wifi/aware/DiscoverySessionCallback.java
@@ -0,0 +1,156 @@
+/*
+ * Copyright (C) 2016 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 android.net.wifi.aware;
+
+import android.annotation.NonNull;
+
+import java.util.List;
+
+/**
+ * Base class for Aware session events callbacks. Should be extended by
+ * applications wanting notifications. The callbacks are set when a
+ * publish or subscribe session is created using
+ * {@link WifiAwareSession#publish(PublishConfig, DiscoverySessionCallback,
+ * android.os.Handler)} or
+ * {@link WifiAwareSession#subscribe(SubscribeConfig, DiscoverySessionCallback,
+ * android.os.Handler)}.
+ * <p>
+ * A single callback is set at session creation - it cannot be replaced.
+ *
+ * @hide PROPOSED_AWARE_API
+ */
+public class DiscoverySessionCallback {
+ /**
+ * Called when a publish operation is started successfully in response to a
+ * {@link WifiAwareSession#publish(PublishConfig, DiscoverySessionCallback,
+ * android.os.Handler)} operation.
+ *
+ * @param session The {@link PublishDiscoverySession} used to control the
+ * discovery session.
+ */
+ public void onPublishStarted(@NonNull PublishDiscoverySession session) {
+ /* empty */
+ }
+
+ /**
+ * Called when a subscribe operation is started successfully in response to a
+ * {@link WifiAwareSession#subscribe(SubscribeConfig, DiscoverySessionCallback,
+ * android.os.Handler)} operation.
+ *
+ * @param session The {@link SubscribeDiscoverySession} used to control the
+ * discovery session.
+ */
+ public void onSubscribeStarted(@NonNull SubscribeDiscoverySession session) {
+ /* empty */
+ }
+
+ /**
+ * Called when a publish or subscribe discovery session configuration update request
+ * succeeds. Called in response to
+ * {@link PublishDiscoverySession#updatePublish(PublishConfig)} or
+ * {@link SubscribeDiscoverySession#updateSubscribe(SubscribeConfig)}.
+ */
+ public void onSessionConfigUpdated() {
+ /* empty */
+ }
+
+ /**
+ * Called when a publish or subscribe discovery session cannot be created:
+ * {@link WifiAwareSession#publish(PublishConfig, DiscoverySessionCallback,
+ * android.os.Handler)} or
+ * {@link WifiAwareSession#subscribe(SubscribeConfig, DiscoverySessionCallback,
+ * android.os.Handler)}, or when a configuration update fails:
+ * {@link PublishDiscoverySession#updatePublish(PublishConfig)} or
+ * {@link SubscribeDiscoverySession#updateSubscribe(SubscribeConfig)}.
+ * <p>
+ * For discovery session updates failure leaves the session running with its previous
+ * configuration - the discovery session is not terminated.
+ */
+ public void onSessionConfigFailed() {
+ /* empty */
+ }
+
+ /**
+ * Called when a discovery session (publish or subscribe) terminates. Termination may be due
+ * to user-request (either directly through {@link DiscoverySession#destroy()} or
+ * application-specified expiration, e.g. {@link PublishConfig.Builder#setPublishCount(int)}
+ * or {@link SubscribeConfig.Builder#setTtlSec(int)}).
+ */
+ public void onSessionTerminated() {
+ /* empty */
+ }
+
+ /**
+ * Called when a discovery (publish or subscribe) operation results in a
+ * service discovery.
+ *
+ * @param peerHandle An opaque handle to the peer matching our discovery operation.
+ * @param serviceSpecificInfo The service specific information (arbitrary
+ * byte array) provided by the peer as part of its discovery
+ * configuration.
+ * @param matchFilter The filter which resulted in this service discovery.
+ */
+ public void onServiceDiscovered(PeerHandle peerHandle,
+ byte[] serviceSpecificInfo, List<byte[]> matchFilter) {
+ /* empty */
+ }
+
+ /**
+ * Called in response to
+ * {@link DiscoverySession#sendMessage(PeerHandle, int, byte[])}
+ * when a message is transmitted successfully - i.e. when it was received successfully by the
+ * peer (corresponds to an ACK being received).
+ * <p>
+ * Note that either this callback or
+ * {@link DiscoverySessionCallback#onMessageSendFailed(int)} will be
+ * received - never both.
+ *
+ * @param messageId The arbitrary message ID specified when sending the message.
+ */
+ public void onMessageSendSucceeded(@SuppressWarnings("unused") int messageId) {
+ /* empty */
+ }
+
+ /**
+ * Called when message transmission fails - when no ACK is received from the peer.
+ * Retries when ACKs are not received are done by hardware, MAC, and in the Aware stack (using
+ * the {@link DiscoverySession#sendMessage(PeerHandle, int,
+ * byte[], int)} method) - this event is received after all retries are exhausted.
+ * <p>
+ * Note that either this callback or
+ * {@link DiscoverySessionCallback#onMessageSendSucceeded(int)} will be received
+ * - never both.
+ *
+ * @param messageId The arbitrary message ID specified when sending the message.
+ */
+ public void onMessageSendFailed(@SuppressWarnings("unused") int messageId) {
+ /* empty */
+ }
+
+ /**
+ * Called when a message is received from a discovery session peer - in response to the
+ * peer's {@link DiscoverySession#sendMessage(PeerHandle, int,
+ * byte[])} or {@link DiscoverySession#sendMessage(PeerHandle,
+ * int, byte[], int)}.
+ *
+ * @param peerHandle An opaque handle to the peer matching our discovery operation.
+ * @param message A byte array containing the message.
+ */
+ public void onMessageReceived(PeerHandle peerHandle, byte[] message) {
+ /* empty */
+ }
+}
diff --git a/wifi/java/android/net/wifi/aware/IWifiAwareManager.aidl b/wifi/java/android/net/wifi/aware/IWifiAwareManager.aidl
index 9c92807..794c142 100644
--- a/wifi/java/android/net/wifi/aware/IWifiAwareManager.aidl
+++ b/wifi/java/android/net/wifi/aware/IWifiAwareManager.aidl
@@ -23,7 +23,7 @@
import android.net.wifi.aware.IWifiAwareEventCallback;
import android.net.wifi.aware.PublishConfig;
import android.net.wifi.aware.SubscribeConfig;
-import android.net.wifi.aware.WifiAwareCharacteristics;
+import android.net.wifi.aware.Characteristics;
import android.net.wifi.RttManager;
/**
@@ -37,7 +37,7 @@
void enableUsage();
void disableUsage();
boolean isUsageEnabled();
- WifiAwareCharacteristics getCharacteristics();
+ Characteristics getCharacteristics();
// client API
void connect(in IBinder binder, in String callingPackage, in IWifiAwareEventCallback callback,
diff --git a/wifi/java/android/net/wifi/aware/WifiAwareIdentityChangedListener.java b/wifi/java/android/net/wifi/aware/IdentityChangedListener.java
similarity index 97%
rename from wifi/java/android/net/wifi/aware/WifiAwareIdentityChangedListener.java
rename to wifi/java/android/net/wifi/aware/IdentityChangedListener.java
index e8f52cd4..b0f97bd 100644
--- a/wifi/java/android/net/wifi/aware/WifiAwareIdentityChangedListener.java
+++ b/wifi/java/android/net/wifi/aware/IdentityChangedListener.java
@@ -28,7 +28,7 @@
*
* @hide PROPOSED_AWARE_API
*/
-public class WifiAwareIdentityChangedListener {
+public class IdentityChangedListener {
/**
* @param mac The MAC address of the Aware discovery interface. The application must have the
* {@link android.Manifest.permission#ACCESS_COARSE_LOCATION} to get the actual MAC address,
diff --git a/wifi/java/android/net/wifi/aware/PeerHandle.java b/wifi/java/android/net/wifi/aware/PeerHandle.java
new file mode 100644
index 0000000..777d9a3
--- /dev/null
+++ b/wifi/java/android/net/wifi/aware/PeerHandle.java
@@ -0,0 +1,36 @@
+/*
+ * Copyright (C) 2016 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 android.net.wifi.aware;
+
+/**
+ * Opaque object used to represent a Wi-Fi Aware peer. Obtained from discovery sessions in
+ * {@link DiscoverySessionCallback#onServiceDiscovered(PeerHandle, byte[], java.util.List)}, used
+ * when sending messages e,g, {@link PublishDiscoverySession#sendMessage(PeerHandle, int, byte[])},
+ * or when configuring a network link to a peer, e.g.
+ * {@link PublishDiscoverySession#createNetworkSpecifier(PeerHandle, byte[])}.
+ *
+ * @hide PROPOSED_AWARE_API
+ */
+public class PeerHandle {
+ /** @hide */
+ public PeerHandle(int peerId) {
+ this.peerId = peerId;
+ }
+
+ /** @hide */
+ public int peerId;
+}
diff --git a/wifi/java/android/net/wifi/aware/PublishConfig.java b/wifi/java/android/net/wifi/aware/PublishConfig.java
index 3925bd7..1b8ef84 100644
--- a/wifi/java/android/net/wifi/aware/PublishConfig.java
+++ b/wifi/java/android/net/wifi/aware/PublishConfig.java
@@ -33,9 +33,9 @@
/**
* Defines the configuration of a Aware publish session. Built using
* {@link PublishConfig.Builder}. A publish session is created using
- * {@link WifiAwareSession#publish(PublishConfig, WifiAwareDiscoverySessionCallback,
+ * {@link WifiAwareSession#publish(PublishConfig, DiscoverySessionCallback,
* android.os.Handler)} or updated using
- * {@link WifiAwarePublishDiscoverySession#updatePublish(PublishConfig)}.
+ * {@link PublishDiscoverySession#updatePublish(PublishConfig)}.
*
* @hide PROPOSED_AWARE_API
*/
@@ -184,7 +184,7 @@
*
* @hide
*/
- public void assertValid(WifiAwareCharacteristics characteristics)
+ public void assertValid(Characteristics characteristics)
throws IllegalArgumentException {
WifiAwareUtils.validateServiceName(mServiceName);
@@ -322,12 +322,11 @@
* Sets the number of times an unsolicited (configured using
* {@link PublishConfig.Builder#setPublishType(int)}) publish session
* will be broadcast. When the count is reached an event will be
- * generated for {@link WifiAwareDiscoverySessionCallback#onSessionTerminated(int)}
- * with {@link WifiAwareDiscoverySessionCallback#TERMINATE_REASON_DONE} [unless
- * {@link #setTerminateNotificationEnabled(boolean)} disables the callback].
+ * generated for {@link DiscoverySessionCallback#onSessionTerminated()}
+ * [unless {@link #setTerminateNotificationEnabled(boolean)} disables the callback].
* <p>
* Optional. 0 by default - indicating the session doesn't terminate on its own.
- * Session will be terminated when {@link WifiAwareDiscoveryBaseSession#destroy()} is
+ * Session will be terminated when {@link DiscoverySession#destroy()} is
* called.
*
* @param publishCount Number of publish packets to broadcast.
@@ -348,12 +347,11 @@
* {@link PublishConfig.Builder#setPublishType(int)}) publish session
* will be alive - broadcasting a packet. When the TTL is reached
* an event will be generated for
- * {@link WifiAwareDiscoverySessionCallback#onSessionTerminated(int)} with
- * {@link WifiAwareDiscoverySessionCallback#TERMINATE_REASON_DONE} [unless
+ * {@link DiscoverySessionCallback#onSessionTerminated()} [unless
* {@link #setTerminateNotificationEnabled(boolean)} disables the callback].
* <p>
* Optional. 0 by default - indicating the session doesn't terminate on its own.
- * Session will be terminated when {@link WifiAwareDiscoveryBaseSession#destroy()} is
+ * Session will be terminated when {@link DiscoverySession#destroy()} is
* called.
*
* @param ttlSec Lifetime of a publish session in seconds.
@@ -371,7 +369,7 @@
/**
* Configure whether a publish terminate notification
- * {@link WifiAwareDiscoverySessionCallback#onSessionTerminated(int)} is reported
+ * {@link DiscoverySessionCallback#onSessionTerminated()} is reported
* back to the callback.
*
* @param enable If true the terminate callback will be called when the
diff --git a/wifi/java/android/net/wifi/aware/WifiAwarePublishDiscoverySession.java b/wifi/java/android/net/wifi/aware/PublishDiscoverySession.java
similarity index 70%
rename from wifi/java/android/net/wifi/aware/WifiAwarePublishDiscoverySession.java
rename to wifi/java/android/net/wifi/aware/PublishDiscoverySession.java
index 68786d1..f2355b3 100644
--- a/wifi/java/android/net/wifi/aware/WifiAwarePublishDiscoverySession.java
+++ b/wifi/java/android/net/wifi/aware/PublishDiscoverySession.java
@@ -21,32 +21,32 @@
/**
* A class representing a Aware publish session. Created when
- * {@link WifiAwareSession#publish(PublishConfig, WifiAwareDiscoverySessionCallback,
+ * {@link WifiAwareSession#publish(PublishConfig, DiscoverySessionCallback,
* android.os.Handler)} is called and a discovery session is created and returned in
- * {@link WifiAwareDiscoverySessionCallback#onPublishStarted(WifiAwarePublishDiscoverySession)}. See
- * baseline functionality of all discovery sessions in {@link WifiAwareDiscoveryBaseSession}. This
+ * {@link DiscoverySessionCallback#onPublishStarted(PublishDiscoverySession)}. See
+ * baseline functionality of all discovery sessions in {@link DiscoverySession}. This
* object allows updating an existing/running publish discovery session using
* {@link #updatePublish(PublishConfig)}.
*
* @hide PROPOSED_AWARE_API
*/
-public class WifiAwarePublishDiscoverySession extends WifiAwareDiscoveryBaseSession {
- private static final String TAG = "WifiAwarePublishDiscSsn";
+public class PublishDiscoverySession extends DiscoverySession {
+ private static final String TAG = "PublishDiscoverySession";
/** @hide */
- public WifiAwarePublishDiscoverySession(WifiAwareManager manager, int clientId, int sessionId) {
+ public PublishDiscoverySession(WifiAwareManager manager, int clientId, int sessionId) {
super(manager, clientId, sessionId);
}
/**
* Re-configure the currently active publish session. The
- * {@link WifiAwareDiscoverySessionCallback} is not replaced - the same listener used
+ * {@link DiscoverySessionCallback} is not replaced - the same listener used
* at creation is still used. The results of the configuration are returned using
- * {@link WifiAwareDiscoverySessionCallback}:
+ * {@link DiscoverySessionCallback}:
* <ul>
- * <li>{@link WifiAwareDiscoverySessionCallback#onSessionConfigUpdated()}: configuration
+ * <li>{@link DiscoverySessionCallback#onSessionConfigUpdated()}: configuration
* update succeeded.
- * <li>{@link WifiAwareDiscoverySessionCallback#onSessionConfigFailed()}: configuration
+ * <li>{@link DiscoverySessionCallback#onSessionConfigFailed()}: configuration
* update failed. The publish discovery session is still running using its previous
* configuration (i.e. update failure does not terminate the session).
* </ul>
diff --git a/wifi/java/android/net/wifi/aware/SubscribeConfig.java b/wifi/java/android/net/wifi/aware/SubscribeConfig.java
index 0fe69a8..a54a4f5 100644
--- a/wifi/java/android/net/wifi/aware/SubscribeConfig.java
+++ b/wifi/java/android/net/wifi/aware/SubscribeConfig.java
@@ -33,9 +33,9 @@
/**
* Defines the configuration of a Aware subscribe session. Built using
* {@link SubscribeConfig.Builder}. Subscribe is done using
- * {@link WifiAwareSession#subscribe(SubscribeConfig, WifiAwareDiscoverySessionCallback,
+ * {@link WifiAwareSession#subscribe(SubscribeConfig, DiscoverySessionCallback,
* android.os.Handler)} or
- * {@link WifiAwareSubscribeDiscoverySession#updateSubscribe(SubscribeConfig)}.
+ * {@link SubscribeDiscoverySession#updateSubscribe(SubscribeConfig)}.
*
* @hide PROPOSED_AWARE_API
*/
@@ -212,7 +212,7 @@
*
* @hide
*/
- public void assertValid(WifiAwareCharacteristics characteristics)
+ public void assertValid(Characteristics characteristics)
throws IllegalArgumentException {
WifiAwareUtils.validateServiceName(mServiceName);
@@ -355,11 +355,10 @@
* Sets the number of times an active (
* {@link SubscribeConfig.Builder#setSubscribeType(int)}) subscribe session
* will broadcast. When the count is reached an event will be
- * generated for {@link WifiAwareDiscoverySessionCallback#onSessionTerminated(int)}
- * with {@link WifiAwareDiscoverySessionCallback#TERMINATE_REASON_DONE}.
+ * generated for {@link DiscoverySessionCallback#onSessionTerminated()}.
* <p>
* Optional. 0 by default - indicating the session doesn't terminate on its own.
- * Session will be terminated when {@link WifiAwareDiscoveryBaseSession#destroy()} is
+ * Session will be terminated when {@link DiscoverySession#destroy()} is
* called.
*
* @param subscribeCount Number of subscribe packets to broadcast.
@@ -380,11 +379,10 @@
* {@link SubscribeConfig.Builder#setSubscribeType(int)}) subscribe session
* will be alive - i.e. broadcasting a packet. When the TTL is reached
* an event will be generated for
- * {@link WifiAwareDiscoverySessionCallback#onSessionTerminated(int)} with
- * {@link WifiAwareDiscoverySessionCallback#TERMINATE_REASON_DONE}.
+ * {@link DiscoverySessionCallback#onSessionTerminated()}.
* <p>
* Optional. 0 by default - indicating the session doesn't terminate on its own.
- * Session will be terminated when {@link WifiAwareDiscoveryBaseSession#destroy()} is
+ * Session will be terminated when {@link DiscoverySession#destroy()} is
* called.
*
* @param ttlSec Lifetime of a subscribe session in seconds.
@@ -404,8 +402,8 @@
* Sets the match style of the subscription - how are matches from a
* single match session (corresponding to the same publish action on the
* peer) reported to the host (using the
- * {@link WifiAwareDiscoverySessionCallback#onServiceDiscovered(WifiAwareManager.PeerHandle,
- * byte[], List)}). The options are: only report the first match and ignore the rest
+ * {@link DiscoverySessionCallback#onServiceDiscovered(PeerHandle, byte[],
+ * java.util.List)}). The options are: only report the first match and ignore the rest
* {@link SubscribeConfig#MATCH_STYLE_FIRST_ONLY} or report every single
* match {@link SubscribeConfig#MATCH_STYLE_ALL} (the default).
*
@@ -424,7 +422,7 @@
/**
* Configure whether a subscribe terminate notification
- * {@link WifiAwareDiscoverySessionCallback#onSessionTerminated(int)} is reported
+ * {@link DiscoverySessionCallback#onSessionTerminated()} is reported
* back to the callback.
*
* @param enable If true the terminate callback will be called when the
diff --git a/wifi/java/android/net/wifi/aware/WifiAwareSubscribeDiscoverySession.java b/wifi/java/android/net/wifi/aware/SubscribeDiscoverySession.java
similarity index 75%
rename from wifi/java/android/net/wifi/aware/WifiAwareSubscribeDiscoverySession.java
rename to wifi/java/android/net/wifi/aware/SubscribeDiscoverySession.java
index a0ec809..39db1c7 100644
--- a/wifi/java/android/net/wifi/aware/WifiAwareSubscribeDiscoverySession.java
+++ b/wifi/java/android/net/wifi/aware/SubscribeDiscoverySession.java
@@ -22,35 +22,35 @@
/**
* A class representing a Aware subscribe session. Created when
* {@link WifiAwareSession#subscribe(SubscribeConfig,
- * WifiAwareDiscoverySessionCallback, android.os.Handler)}
+ * DiscoverySessionCallback, android.os.Handler)}
* is called and a discovery session is created and returned in
- * {@link WifiAwareDiscoverySessionCallback#onSubscribeStarted(WifiAwareSubscribeDiscoverySession)}.
- * See baseline functionality of all discovery sessions in {@link WifiAwareDiscoveryBaseSession}.
+ * {@link DiscoverySessionCallback#onSubscribeStarted(SubscribeDiscoverySession)}.
+ * See baseline functionality of all discovery sessions in {@link DiscoverySession}.
* This object allows updating an existing/running subscribe discovery session using
* {@link #updateSubscribe(SubscribeConfig)}.
*
* @hide PROPOSED_AWARE_API
*/
-public class WifiAwareSubscribeDiscoverySession extends WifiAwareDiscoveryBaseSession {
- private static final String TAG = "WifiAwareSubsDiscSsn";
+public class SubscribeDiscoverySession extends DiscoverySession {
+ private static final String TAG = "SubscribeDiscSession";
/**
* {@hide}
*/
- public WifiAwareSubscribeDiscoverySession(WifiAwareManager manager, int clientId,
+ public SubscribeDiscoverySession(WifiAwareManager manager, int clientId,
int sessionId) {
super(manager, clientId, sessionId);
}
/**
* Re-configure the currently active subscribe session. The
- * {@link WifiAwareDiscoverySessionCallback} is not replaced - the same listener used
+ * {@link DiscoverySessionCallback} is not replaced - the same listener used
* at creation is still used. The results of the configuration are returned using
- * {@link WifiAwareDiscoverySessionCallback}:
+ * {@link DiscoverySessionCallback}:
* <ul>
- * <li>{@link WifiAwareDiscoverySessionCallback#onSessionConfigUpdated()}: configuration
+ * <li>{@link DiscoverySessionCallback#onSessionConfigUpdated()}: configuration
* update succeeded.
- * <li>{@link WifiAwareDiscoverySessionCallback#onSessionConfigFailed()}: configuration
+ * <li>{@link DiscoverySessionCallback#onSessionConfigFailed()}: configuration
* update failed. The subscribe discovery session is still running using its previous
* configuration (i.e. update failure does not terminate the session).
* </ul>
diff --git a/wifi/java/android/net/wifi/aware/WifiAwareDiscoverySessionCallback.java b/wifi/java/android/net/wifi/aware/WifiAwareDiscoverySessionCallback.java
deleted file mode 100644
index fdf0d01..0000000
--- a/wifi/java/android/net/wifi/aware/WifiAwareDiscoverySessionCallback.java
+++ /dev/null
@@ -1,185 +0,0 @@
-/*
- * Copyright (C) 2016 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 android.net.wifi.aware;
-
-import android.annotation.IntDef;
-import android.annotation.NonNull;
-
-import java.lang.annotation.Retention;
-import java.lang.annotation.RetentionPolicy;
-import java.util.List;
-
-/**
- * Base class for Aware session events callbacks. Should be extended by
- * applications wanting notifications. The callbacks are set when a
- * publish or subscribe session is created using
- * {@link WifiAwareSession#publish(PublishConfig, WifiAwareDiscoverySessionCallback,
- * android.os.Handler)} or
- * {@link WifiAwareSession#subscribe(SubscribeConfig, WifiAwareDiscoverySessionCallback,
- * android.os.Handler)}.
- * <p>
- * A single callback is set at session creation - it cannot be replaced.
- *
- * @hide PROPOSED_AWARE_API
- */
-public class WifiAwareDiscoverySessionCallback {
- /** @hide */
- @IntDef({
- TERMINATE_REASON_DONE, TERMINATE_REASON_FAIL })
- @Retention(RetentionPolicy.SOURCE)
- public @interface SessionTerminateCodes {
- }
-
- /**
- * Indicates that publish or subscribe session is done - all the
- * requested operations (per {@link PublishConfig} or
- * {@link SubscribeConfig}) have been executed. Failure reason flag for
- * {@link WifiAwareDiscoverySessionCallback#onSessionTerminated(int)} callback.
- */
- public static final int TERMINATE_REASON_DONE = 100;
-
- /**
- * Indicates that publish or subscribe session is terminated due to a
- * failure.
- * Failure reason flag for
- * {@link WifiAwareDiscoverySessionCallback#onSessionTerminated(int)} callback.
- */
- public static final int TERMINATE_REASON_FAIL = 101;
-
- /**
- * Called when a publish operation is started successfully in response to a
- * {@link WifiAwareSession#publish(PublishConfig, WifiAwareDiscoverySessionCallback,
- * android.os.Handler)} operation.
- *
- * @param session The {@link WifiAwarePublishDiscoverySession} used to control the
- * discovery session.
- */
- public void onPublishStarted(@NonNull WifiAwarePublishDiscoverySession session) {
- /* empty */
- }
-
- /**
- * Called when a subscribe operation is started successfully in response to a
- * {@link WifiAwareSession#subscribe(SubscribeConfig, WifiAwareDiscoverySessionCallback,
- * android.os.Handler)} operation.
- *
- * @param session The {@link WifiAwareSubscribeDiscoverySession} used to control the
- * discovery session.
- */
- public void onSubscribeStarted(@NonNull WifiAwareSubscribeDiscoverySession session) {
- /* empty */
- }
-
- /**
- * Called when a publish or subscribe discovery session configuration update request
- * succeeds. Called in response to
- * {@link WifiAwarePublishDiscoverySession#updatePublish(PublishConfig)} or
- * {@link WifiAwareSubscribeDiscoverySession#updateSubscribe(SubscribeConfig)}.
- */
- public void onSessionConfigUpdated() {
- /* empty */
- }
-
- /**
- * Called when a publish or subscribe discovery session cannot be created:
- * {@link WifiAwareSession#publish(PublishConfig, WifiAwareDiscoverySessionCallback,
- * android.os.Handler)} or
- * {@link WifiAwareSession#subscribe(SubscribeConfig, WifiAwareDiscoverySessionCallback,
- * android.os.Handler)}, or when a configuration update fails:
- * {@link WifiAwarePublishDiscoverySession#updatePublish(PublishConfig)} or
- * {@link WifiAwareSubscribeDiscoverySession#updateSubscribe(SubscribeConfig)}.
- * <p>
- * For discovery session updates failure leaves the session running with its previous
- * configuration - the discovery session is not terminated.
- */
- public void onSessionConfigFailed() {
- /* empty */
- }
-
- /**
- * Called when a discovery session (publish or subscribe) terminates. Termination may be due
- * to user-request (either directly through {@link WifiAwareDiscoveryBaseSession#destroy()} or
- * application-specified expiration, e.g. {@link PublishConfig.Builder#setPublishCount(int)}
- * or {@link SubscribeConfig.Builder#setTtlSec(int)}) or due to a failure.
- *
- * @param reason The termination reason using
- * {@code WifiAwareDiscoverySessionCallback.TERMINATE_*} codes.
- */
- public void onSessionTerminated(@SessionTerminateCodes int reason) {
- /* empty */
- }
-
- /**
- * Called when a discovery (publish or subscribe) operation results in a
- * service discovery.
- *
- * @param peerHandle An opaque handle to the peer matching our discovery operation.
- * @param serviceSpecificInfo The service specific information (arbitrary
- * byte array) provided by the peer as part of its discovery
- * configuration.
- * @param matchFilter The filter which resulted in this service discovery.
- */
- public void onServiceDiscovered(WifiAwareManager.PeerHandle peerHandle,
- byte[] serviceSpecificInfo, List<byte[]> matchFilter) {
- /* empty */
- }
-
- /**
- * Called in response to
- * {@link WifiAwareDiscoveryBaseSession#sendMessage(WifiAwareManager.PeerHandle, int, byte[])}
- * when a message is transmitted successfully - i.e. when it was received successfully by the
- * peer (corresponds to an ACK being received).
- * <p>
- * Note that either this callback or
- * {@link WifiAwareDiscoverySessionCallback#onMessageSendFailed(int)} will be
- * received - never both.
- *
- * @param messageId The arbitrary message ID specified when sending the message.
- */
- public void onMessageSendSucceeded(@SuppressWarnings("unused") int messageId) {
- /* empty */
- }
-
- /**
- * Called when message transmission fails - when no ACK is received from the peer.
- * Retries when ACKs are not received are done by hardware, MAC, and in the Aware stack (using
- * the {@link WifiAwareDiscoveryBaseSession#sendMessage(WifiAwareManager.PeerHandle, int,
- * byte[], int)} method) - this event is received after all retries are exhausted.
- * <p>
- * Note that either this callback or
- * {@link WifiAwareDiscoverySessionCallback#onMessageSendSucceeded(int)} will be received
- * - never both.
- *
- * @param messageId The arbitrary message ID specified when sending the message.
- */
- public void onMessageSendFailed(@SuppressWarnings("unused") int messageId) {
- /* empty */
- }
-
- /**
- * Called when a message is received from a discovery session peer - in response to the
- * peer's {@link WifiAwareDiscoveryBaseSession#sendMessage(WifiAwareManager.PeerHandle, int,
- * byte[])} or {@link WifiAwareDiscoveryBaseSession#sendMessage(WifiAwareManager.PeerHandle,
- * int, byte[], int)}.
- *
- * @param peerHandle An opaque handle to the peer matching our discovery operation.
- * @param message A byte array containing the message.
- */
- public void onMessageReceived(WifiAwareManager.PeerHandle peerHandle, byte[] message) {
- /* empty */
- }
-}
diff --git a/wifi/java/android/net/wifi/aware/WifiAwareManager.java b/wifi/java/android/net/wifi/aware/WifiAwareManager.java
index 029794d..8c0a3a0 100644
--- a/wifi/java/android/net/wifi/aware/WifiAwareManager.java
+++ b/wifi/java/android/net/wifi/aware/WifiAwareManager.java
@@ -58,14 +58,14 @@
* The class provides access to:
* <ul>
* <li>Initialize a Aware cluster (peer-to-peer synchronization). Refer to
- * {@link #attach(WifiAwareAttachCallback, Handler)}.
+ * {@link #attach(AttachCallback, Handler)}.
* <li>Create discovery sessions (publish or subscribe sessions). Refer to
- * {@link WifiAwareSession#publish(PublishConfig, WifiAwareDiscoverySessionCallback, Handler)} and
- * {@link WifiAwareSession#subscribe(SubscribeConfig, WifiAwareDiscoverySessionCallback, Handler)}.
+ * {@link WifiAwareSession#publish(PublishConfig, DiscoverySessionCallback, Handler)} and
+ * {@link WifiAwareSession#subscribe(SubscribeConfig, DiscoverySessionCallback, Handler)}.
* <li>Create a Aware network specifier to be used with
* {@link ConnectivityManager#requestNetwork(NetworkRequest, ConnectivityManager.NetworkCallback)}
* to set-up a Aware connection with a peer. Refer to
- * {@link WifiAwareDiscoveryBaseSession#createNetworkSpecifier(PeerHandle, byte[])} and
+ * {@link DiscoverySession#createNetworkSpecifier(PeerHandle, byte[])} and
* {@link WifiAwareSession#createNetworkSpecifier(int, byte[], byte[])}.
* </ul>
* <p>
@@ -75,37 +75,37 @@
* broadcast. Note that this broadcast is not sticky - you should register for it and then
* check the above API to avoid a race condition.
* <p>
- * An application must use {@link #attach(WifiAwareAttachCallback, Handler)} to initialize a
+ * An application must use {@link #attach(AttachCallback, Handler)} to initialize a
* Aware cluster - before making any other Aware operation. Aware cluster membership is a
* device-wide operation - the API guarantees that the device is in a cluster or joins a
* Aware cluster (or starts one if none can be found). Information about attach success (or
- * failure) are returned in callbacks of {@link WifiAwareAttachCallback}. Proceed with Aware
+ * failure) are returned in callbacks of {@link AttachCallback}. Proceed with Aware
* discovery or connection setup only after receiving confirmation that Aware attach
- * succeeded - {@link WifiAwareAttachCallback#onAttached(WifiAwareSession)}. When an
+ * succeeded - {@link AttachCallback#onAttached(WifiAwareSession)}. When an
* application is finished using Aware it <b>must</b> use the
* {@link WifiAwareSession#destroy()} API to indicate to the Aware service that the device
* may detach from the Aware cluster. The device will actually disable Aware once the last
* application detaches.
* <p>
* Once a Aware attach is confirmed use the
- * {@link WifiAwareSession#publish(PublishConfig, WifiAwareDiscoverySessionCallback, Handler)}
+ * {@link WifiAwareSession#publish(PublishConfig, DiscoverySessionCallback, Handler)}
* or
- * {@link WifiAwareSession#subscribe(SubscribeConfig, WifiAwareDiscoverySessionCallback,
+ * {@link WifiAwareSession#subscribe(SubscribeConfig, DiscoverySessionCallback,
* Handler)} to create publish or subscribe Aware discovery sessions. Events are called on the
- * provided callback object {@link WifiAwareDiscoverySessionCallback}. Specifically, the
- * {@link WifiAwareDiscoverySessionCallback#onPublishStarted(WifiAwarePublishDiscoverySession)}
+ * provided callback object {@link DiscoverySessionCallback}. Specifically, the
+ * {@link DiscoverySessionCallback#onPublishStarted(PublishDiscoverySession)}
* and
- * {@link WifiAwareDiscoverySessionCallback#onSubscribeStarted(
- * WifiAwareSubscribeDiscoverySession)}
- * return {@link WifiAwarePublishDiscoverySession} and
- * {@link WifiAwareSubscribeDiscoverySession}
+ * {@link DiscoverySessionCallback#onSubscribeStarted(
+ *SubscribeDiscoverySession)}
+ * return {@link PublishDiscoverySession} and
+ * {@link SubscribeDiscoverySession}
* objects respectively on which additional session operations can be performed, e.g. updating
- * the session {@link WifiAwarePublishDiscoverySession#updatePublish(PublishConfig)} and
- * {@link WifiAwareSubscribeDiscoverySession#updateSubscribe(SubscribeConfig)}. Sessions can
+ * the session {@link PublishDiscoverySession#updatePublish(PublishConfig)} and
+ * {@link SubscribeDiscoverySession#updateSubscribe(SubscribeConfig)}. Sessions can
* also be used to send messages using the
- * {@link WifiAwareDiscoveryBaseSession#sendMessage(PeerHandle, int, byte[])} APIs. When an
+ * {@link DiscoverySession#sendMessage(PeerHandle, int, byte[])} APIs. When an
* application is finished with a discovery session it <b>must</b> terminate it using the
- * {@link WifiAwareDiscoveryBaseSession#destroy()} API.
+ * {@link DiscoverySession#destroy()} API.
* <p>
* Creating connections between Aware devices is managed by the standard
* {@link ConnectivityManager#requestNetwork(NetworkRequest,
@@ -116,7 +116,7 @@
* {@link android.net.NetworkCapabilities#TRANSPORT_WIFI_AWARE}.
* <li>{@link NetworkRequest.Builder#setNetworkSpecifier(String)} using
* {@link WifiAwareSession#createNetworkSpecifier(int, byte[], byte[])} or
- * {@link WifiAwareDiscoveryBaseSession#createNetworkSpecifier(PeerHandle, byte[])}.
+ * {@link DiscoverySession#createNetworkSpecifier(PeerHandle, byte[])}.
* </ul>
*
* @hide PROPOSED_AWARE_API
@@ -226,7 +226,7 @@
* Connection creation role is that of INITIATOR. Used to create a network specifier string
* when requesting a Aware network.
*
- * @see WifiAwareDiscoveryBaseSession#createNetworkSpecifier(PeerHandle, byte[])
+ * @see DiscoverySession#createNetworkSpecifier(PeerHandle, byte[])
* @see WifiAwareSession#createNetworkSpecifier(int, byte[], byte[])
*/
public static final int WIFI_AWARE_DATA_PATH_ROLE_INITIATOR = 0;
@@ -235,7 +235,7 @@
* Connection creation role is that of RESPONDER. Used to create a network specifier string
* when requesting a Aware network.
*
- * @see WifiAwareDiscoveryBaseSession#createNetworkSpecifier(PeerHandle, byte[])
+ * @see DiscoverySession#createNetworkSpecifier(PeerHandle, byte[])
* @see WifiAwareSession#createNetworkSpecifier(int, byte[], byte[])
*/
public static final int WIFI_AWARE_DATA_PATH_ROLE_RESPONDER = 1;
@@ -307,7 +307,7 @@
* @return An object specifying configuration limitations of Aware.
* @hide PROPOSED_AWARE_API
*/
- public WifiAwareCharacteristics getCharacteristics() {
+ public Characteristics getCharacteristics() {
try {
return mService.getCharacteristics();
} catch (RemoteException e) {
@@ -328,12 +328,12 @@
* attachCallback}.
*
* @param attachCallback A callback for attach events, extended from
- * {@link WifiAwareAttachCallback}.
+ * {@link AttachCallback}.
* @param handler The Handler on whose thread to execute the callbacks of the {@code
* attachCallback} object. If a null is provided then the application's main thread will be
* used.
*/
- public void attach(@NonNull WifiAwareAttachCallback attachCallback, @Nullable Handler handler) {
+ public void attach(@NonNull AttachCallback attachCallback, @Nullable Handler handler) {
attach(handler, null, attachCallback, null);
}
@@ -353,28 +353,28 @@
* on startup and whenever it is updated (it is randomized at regular intervals for privacy).
* The application must have the {@link android.Manifest.permission#ACCESS_COARSE_LOCATION}
* permission to execute this attach request. Otherwise, use the
- * {@link #attach(WifiAwareAttachCallback, Handler)} version. Note that aside from permission
+ * {@link #attach(AttachCallback, Handler)} version. Note that aside from permission
* requirements this listener will wake up the host at regular intervals causing higher power
* consumption, do not use it unless the information is necessary (e.g. for OOB discovery).
*
* @param attachCallback A callback for attach events, extended from
- * {@link WifiAwareAttachCallback}.
+ * {@link AttachCallback}.
* @param identityChangedListener A listener for changed identity, extended from
- * {@link WifiAwareIdentityChangedListener}.
+ * {@link IdentityChangedListener}.
* @param handler The Handler on whose thread to execute the callbacks of the {@code
* attachCallback} and {@code identityChangedListener} objects. If a null is provided then the
* application's main thread will be used.
*/
- public void attach(@NonNull WifiAwareAttachCallback attachCallback,
- @NonNull WifiAwareIdentityChangedListener identityChangedListener,
+ public void attach(@NonNull AttachCallback attachCallback,
+ @NonNull IdentityChangedListener identityChangedListener,
@Nullable Handler handler) {
attach(handler, null, attachCallback, identityChangedListener);
}
/** @hide */
public void attach(Handler handler, ConfigRequest configRequest,
- WifiAwareAttachCallback attachCallback,
- WifiAwareIdentityChangedListener identityChangedListener) {
+ AttachCallback attachCallback,
+ IdentityChangedListener identityChangedListener) {
if (VDBG) {
Log.v(TAG, "attach(): handler=" + handler + ", callback=" + attachCallback
+ ", configRequest=" + configRequest + ", identityChangedListener="
@@ -409,7 +409,7 @@
/** @hide */
public void publish(int clientId, Looper looper, PublishConfig publishConfig,
- WifiAwareDiscoverySessionCallback callback) {
+ DiscoverySessionCallback callback) {
if (VDBG) Log.v(TAG, "publish(): clientId=" + clientId + ", config=" + publishConfig);
try {
@@ -437,7 +437,7 @@
/** @hide */
public void subscribe(int clientId, Looper looper, SubscribeConfig subscribeConfig,
- WifiAwareDiscoverySessionCallback callback) {
+ DiscoverySessionCallback callback) {
if (VDBG) {
if (VDBG) {
Log.v(TAG,
@@ -672,14 +672,14 @@
}
/**
- * Constructs a {@link WifiAwareAttachCallback} using the specified looper.
+ * Constructs a {@link AttachCallback} using the specified looper.
* All callbacks will delivered on the thread of the specified looper.
*
* @param looper The looper on which to execute the callbacks.
*/
WifiAwareEventCallbackProxy(WifiAwareManager mgr, Looper looper, Binder binder,
- final WifiAwareAttachCallback attachCallback,
- final WifiAwareIdentityChangedListener identityChangedListener) {
+ final AttachCallback attachCallback,
+ final IdentityChangedListener identityChangedListener) {
mAwareManager = new WeakReference<>(mgr);
mLooper = looper;
mBinder = binder;
@@ -828,14 +828,14 @@
private final WeakReference<WifiAwareManager> mAwareManager;
private final boolean mIsPublish;
- private final WifiAwareDiscoverySessionCallback mOriginalCallback;
+ private final DiscoverySessionCallback mOriginalCallback;
private final int mClientId;
private final Handler mHandler;
- private WifiAwareDiscoveryBaseSession mSession;
+ private DiscoverySession mSession;
WifiAwareDiscoverySessionCallbackProxy(WifiAwareManager mgr, Looper looper,
- boolean isPublish, WifiAwareDiscoverySessionCallback originalCallback,
+ boolean isPublish, DiscoverySessionCallback originalCallback,
int clientId) {
mAwareManager = new WeakReference<>(mgr);
mIsPublish = isPublish;
@@ -1006,13 +1006,13 @@
}
if (mIsPublish) {
- WifiAwarePublishDiscoverySession session = new WifiAwarePublishDiscoverySession(mgr,
+ PublishDiscoverySession session = new PublishDiscoverySession(mgr,
mClientId, sessionId);
mSession = session;
mOriginalCallback.onPublishStarted(session);
} else {
- WifiAwareSubscribeDiscoverySession
- session = new WifiAwareSubscribeDiscoverySession(mgr, mClientId, sessionId);
+ SubscribeDiscoverySession
+ session = new SubscribeDiscoverySession(mgr, mClientId, sessionId);
mSession = session;
mOriginalCallback.onSubscribeStarted(session);
}
@@ -1027,18 +1027,7 @@
Log.w(TAG, "Proxy: onSessionTerminated called but mSession is null!?");
}
mAwareManager.clear();
- mOriginalCallback.onSessionTerminated(reason);
+ mOriginalCallback.onSessionTerminated();
}
}
-
- /** @hide PROPOSED_AWARE_API */
- public static class PeerHandle {
- /** @hide */
- public PeerHandle(int peerId) {
- this.peerId = peerId;
- }
-
- /** @hide */
- public int peerId;
- }
}
diff --git a/wifi/java/android/net/wifi/aware/WifiAwareSession.java b/wifi/java/android/net/wifi/aware/WifiAwareSession.java
index 005895a..e3ebe86 100644
--- a/wifi/java/android/net/wifi/aware/WifiAwareSession.java
+++ b/wifi/java/android/net/wifi/aware/WifiAwareSession.java
@@ -65,7 +65,7 @@
* session-wide destroy.
* <p>
* An application may re-attach after a destroy using
- * {@link WifiAwareManager#attach(WifiAwareAttachCallback, Handler)} .
+ * {@link WifiAwareManager#attach(AttachCallback, Handler)} .
*/
public void destroy() {
WifiAwareManager mgr = mMgr.get();
@@ -95,22 +95,22 @@
/**
* Issue a request to the Aware service to create a new Aware publish discovery session, using
* the specified {@code publishConfig} configuration. The results of the publish operation
- * are routed to the callbacks of {@link WifiAwareDiscoverySessionCallback}:
+ * are routed to the callbacks of {@link DiscoverySessionCallback}:
* <ul>
* <li>
- * {@link WifiAwareDiscoverySessionCallback#onPublishStarted(
- * WifiAwarePublishDiscoverySession)}
+ * {@link DiscoverySessionCallback#onPublishStarted(
+ *PublishDiscoverySession)}
* is called when the publish session is created and provides a handle to the session.
* Further operations on the publish session can be executed on that object.
- * <li>{@link WifiAwareDiscoverySessionCallback#onSessionConfigFailed()} is called if the
+ * <li>{@link DiscoverySessionCallback#onSessionConfigFailed()} is called if the
* publish operation failed.
* </ul>
* <p>
* Other results of the publish session operations will also be routed to callbacks
* on the {@code callback} object. The resulting publish session can be modified using
- * {@link WifiAwarePublishDiscoverySession#updatePublish(PublishConfig)}.
+ * {@link PublishDiscoverySession#updatePublish(PublishConfig)}.
* <p>
- * An application must use the {@link WifiAwareDiscoveryBaseSession#destroy()} to
+ * An application must use the {@link DiscoverySession#destroy()} to
* terminate the publish discovery session once it isn't needed. This will free
* resources as well terminate any on-air transmissions.
* <p>The application must have the {@link android.Manifest.permission#ACCESS_COARSE_LOCATION}
@@ -118,13 +118,13 @@
*
* @param publishConfig The {@link PublishConfig} specifying the
* configuration of the requested publish session.
- * @param callback A {@link WifiAwareDiscoverySessionCallback} derived object to be used for
+ * @param callback A {@link DiscoverySessionCallback} derived object to be used for
* session event callbacks.
* @param handler The Handler on whose thread to execute the callbacks of the {@code
* callback} object. If a null is provided then the application's main thread will be used.
*/
public void publish(@NonNull PublishConfig publishConfig,
- @NonNull WifiAwareDiscoverySessionCallback callback, @Nullable Handler handler) {
+ @NonNull DiscoverySessionCallback callback, @Nullable Handler handler) {
WifiAwareManager mgr = mMgr.get();
if (mgr == null) {
Log.e(TAG, "publish: called post GC on WifiAwareManager");
@@ -141,22 +141,22 @@
/**
* Issue a request to the Aware service to create a new Aware subscribe discovery session, using
* the specified {@code subscribeConfig} configuration. The results of the subscribe
- * operation are routed to the callbacks of {@link WifiAwareDiscoverySessionCallback}:
+ * operation are routed to the callbacks of {@link DiscoverySessionCallback}:
* <ul>
* <li>
- * {@link WifiAwareDiscoverySessionCallback#onSubscribeStarted(
- * WifiAwareSubscribeDiscoverySession)}
+ * {@link DiscoverySessionCallback#onSubscribeStarted(
+ *SubscribeDiscoverySession)}
* is called when the subscribe session is created and provides a handle to the session.
* Further operations on the subscribe session can be executed on that object.
- * <li>{@link WifiAwareDiscoverySessionCallback#onSessionConfigFailed()} is called if the
+ * <li>{@link DiscoverySessionCallback#onSessionConfigFailed()} is called if the
* subscribe operation failed.
* </ul>
* <p>
* Other results of the subscribe session operations will also be routed to callbacks
* on the {@code callback} object. The resulting subscribe session can be modified using
- * {@link WifiAwareSubscribeDiscoverySession#updateSubscribe(SubscribeConfig)}.
+ * {@link SubscribeDiscoverySession#updateSubscribe(SubscribeConfig)}.
* <p>
- * An application must use the {@link WifiAwareDiscoveryBaseSession#destroy()} to
+ * An application must use the {@link DiscoverySession#destroy()} to
* terminate the subscribe discovery session once it isn't needed. This will free
* resources as well terminate any on-air transmissions.
* <p>The application must have the {@link android.Manifest.permission#ACCESS_COARSE_LOCATION}
@@ -164,13 +164,13 @@
*
* @param subscribeConfig The {@link SubscribeConfig} specifying the
* configuration of the requested subscribe session.
- * @param callback A {@link WifiAwareDiscoverySessionCallback} derived object to be used for
+ * @param callback A {@link DiscoverySessionCallback} derived object to be used for
* session event callbacks.
* @param handler The Handler on whose thread to execute the callbacks of the {@code
* callback} object. If a null is provided then the application's main thread will be used.
*/
public void subscribe(@NonNull SubscribeConfig subscribeConfig,
- @NonNull WifiAwareDiscoverySessionCallback callback, @Nullable Handler handler) {
+ @NonNull DiscoverySessionCallback callback, @Nullable Handler handler) {
WifiAwareManager mgr = mMgr.get();
if (mgr == null) {
Log.e(TAG, "publish: called post GC on WifiAwareManager");
@@ -193,7 +193,7 @@
* This API is targeted for applications which can obtain the peer MAC address using OOB
* (out-of-band) discovery. Aware discovery does not provide the MAC address of the peer -
* when using Aware discovery use the alternative network specifier method -
- * {@link WifiAwareDiscoveryBaseSession#createNetworkSpecifier(WifiAwareManager.PeerHandle,
+ * {@link DiscoverySession#createNetworkSpecifier(PeerHandle,
* byte[])}.
*
* @param role The role of this device:
diff --git a/wifi/tests/src/android/net/wifi/aware/WifiAwareManagerTest.java b/wifi/tests/src/android/net/wifi/aware/WifiAwareManagerTest.java
index 24c0127..a396d87 100644
--- a/wifi/tests/src/android/net/wifi/aware/WifiAwareManagerTest.java
+++ b/wifi/tests/src/android/net/wifi/aware/WifiAwareManagerTest.java
@@ -67,19 +67,19 @@
public Context mockContext;
@Mock
- public WifiAwareAttachCallback mockCallback;
+ public AttachCallback mockCallback;
@Mock
- public WifiAwareDiscoverySessionCallback mockSessionCallback;
+ public DiscoverySessionCallback mockSessionCallback;
@Mock
public IWifiAwareManager mockAwareService;
@Mock
- public WifiAwarePublishDiscoverySession mockPublishSession;
+ public PublishDiscoverySession mockPublishSession;
@Mock
- public WifiAwareSubscribeDiscoverySession mockSubscribeSession;
+ public SubscribeDiscoverySession mockSubscribeSession;
@Mock
public RttManager.RttListener mockRttListener;
@@ -276,7 +276,7 @@
final int sessionId = 123;
final ConfigRequest configRequest = new ConfigRequest.Builder().build();
final PublishConfig publishConfig = new PublishConfig.Builder().build();
- final WifiAwareManager.PeerHandle peerHandle = new WifiAwareManager.PeerHandle(873);
+ final PeerHandle peerHandle = new PeerHandle(873);
final String string1 = "hey from here...";
final byte[] matchFilter = { 1, 12, 2, 31, 32 };
final int messageId = 2123;
@@ -290,10 +290,9 @@
.forClass(IWifiAwareEventCallback.class);
ArgumentCaptor<IWifiAwareDiscoverySessionCallback> sessionProxyCallback = ArgumentCaptor
.forClass(IWifiAwareDiscoverySessionCallback.class);
- ArgumentCaptor<WifiAwarePublishDiscoverySession> publishSession = ArgumentCaptor
- .forClass(WifiAwarePublishDiscoverySession.class);
- ArgumentCaptor<WifiAwareManager.PeerHandle> peerIdCaptor = ArgumentCaptor.forClass(
- WifiAwareManager.PeerHandle.class);
+ ArgumentCaptor<PublishDiscoverySession> publishSession = ArgumentCaptor
+ .forClass(PublishDiscoverySession.class);
+ ArgumentCaptor<PeerHandle> peerIdCaptor = ArgumentCaptor.forClass(PeerHandle.class);
ArgumentCaptor<List<byte[]>> matchFilterCaptor = ArgumentCaptor.forClass(
(Class) List.class);
@@ -377,7 +376,6 @@
final int sessionId = 123;
final ConfigRequest configRequest = new ConfigRequest.Builder().build();
final PublishConfig publishConfig = new PublishConfig.Builder().build();
- final int reason = WifiAwareDiscoverySessionCallback.TERMINATE_REASON_DONE;
InOrder inOrder = inOrder(mockCallback, mockSessionCallback, mockAwareService,
mockPublishSession);
@@ -387,8 +385,8 @@
.forClass(IWifiAwareEventCallback.class);
ArgumentCaptor<IWifiAwareDiscoverySessionCallback> sessionProxyCallback = ArgumentCaptor
.forClass(IWifiAwareDiscoverySessionCallback.class);
- ArgumentCaptor<WifiAwarePublishDiscoverySession> publishSession = ArgumentCaptor
- .forClass(WifiAwarePublishDiscoverySession.class);
+ ArgumentCaptor<PublishDiscoverySession> publishSession = ArgumentCaptor
+ .forClass(PublishDiscoverySession.class);
// (1) connect successfully
mDut.attach(mMockLooperHandler, configRequest, mockCallback, null);
@@ -404,10 +402,10 @@
inOrder.verify(mockAwareService).publish(eq(clientId), eq(publishConfig),
sessionProxyCallback.capture());
sessionProxyCallback.getValue().onSessionStarted(sessionId);
- sessionProxyCallback.getValue().onSessionTerminated(reason);
+ sessionProxyCallback.getValue().onSessionTerminated(0);
mMockLooper.dispatchAll();
inOrder.verify(mockSessionCallback).onPublishStarted(publishSession.capture());
- inOrder.verify(mockSessionCallback).onSessionTerminated(reason);
+ inOrder.verify(mockSessionCallback).onSessionTerminated();
// (3) failure when trying to update: NOP
publishSession.getValue().updatePublish(publishConfig);
@@ -428,7 +426,7 @@
final int sessionId = 123;
final ConfigRequest configRequest = new ConfigRequest.Builder().build();
final SubscribeConfig subscribeConfig = new SubscribeConfig.Builder().build();
- final WifiAwareManager.PeerHandle peerHandle = new WifiAwareManager.PeerHandle(873);
+ final PeerHandle peerHandle = new PeerHandle(873);
final String string1 = "hey from here...";
final byte[] matchFilter = { 1, 12, 3, 31, 32 }; // bad data!
final int messageId = 2123;
@@ -442,10 +440,9 @@
.forClass(IWifiAwareEventCallback.class);
ArgumentCaptor<IWifiAwareDiscoverySessionCallback> sessionProxyCallback = ArgumentCaptor
.forClass(IWifiAwareDiscoverySessionCallback.class);
- ArgumentCaptor<WifiAwareSubscribeDiscoverySession> subscribeSession = ArgumentCaptor
- .forClass(WifiAwareSubscribeDiscoverySession.class);
- ArgumentCaptor<WifiAwareManager.PeerHandle> peerIdCaptor = ArgumentCaptor.forClass(
- WifiAwareManager.PeerHandle.class);
+ ArgumentCaptor<SubscribeDiscoverySession> subscribeSession = ArgumentCaptor
+ .forClass(SubscribeDiscoverySession.class);
+ ArgumentCaptor<PeerHandle> peerIdCaptor = ArgumentCaptor.forClass(PeerHandle.class);
// (0) connect + success
mDut.attach(mMockLooperHandler, configRequest, mockCallback, null);
@@ -516,7 +513,6 @@
final int sessionId = 123;
final ConfigRequest configRequest = new ConfigRequest.Builder().build();
final SubscribeConfig subscribeConfig = new SubscribeConfig.Builder().build();
- final int reason = WifiAwareDiscoverySessionCallback.TERMINATE_REASON_DONE;
InOrder inOrder = inOrder(mockCallback, mockSessionCallback, mockAwareService,
mockSubscribeSession);
@@ -526,8 +522,8 @@
.forClass(IWifiAwareEventCallback.class);
ArgumentCaptor<IWifiAwareDiscoverySessionCallback> sessionProxyCallback = ArgumentCaptor
.forClass(IWifiAwareDiscoverySessionCallback.class);
- ArgumentCaptor<WifiAwareSubscribeDiscoverySession> subscribeSession = ArgumentCaptor
- .forClass(WifiAwareSubscribeDiscoverySession.class);
+ ArgumentCaptor<SubscribeDiscoverySession> subscribeSession = ArgumentCaptor
+ .forClass(SubscribeDiscoverySession.class);
// (1) connect successfully
mDut.attach(mMockLooperHandler, configRequest, mockCallback, null);
@@ -543,10 +539,10 @@
inOrder.verify(mockAwareService).subscribe(eq(clientId), eq(subscribeConfig),
sessionProxyCallback.capture());
sessionProxyCallback.getValue().onSessionStarted(sessionId);
- sessionProxyCallback.getValue().onSessionTerminated(reason);
+ sessionProxyCallback.getValue().onSessionTerminated(0);
mMockLooper.dispatchAll();
inOrder.verify(mockSessionCallback).onSubscribeStarted(subscribeSession.capture());
- inOrder.verify(mockSessionCallback).onSessionTerminated(reason);
+ inOrder.verify(mockSessionCallback).onSessionTerminated();
// (3) failure when trying to update: NOP
subscribeSession.getValue().updateSubscribe(subscribeConfig);
@@ -892,8 +888,8 @@
.forClass(IWifiAwareEventCallback.class);
ArgumentCaptor<IWifiAwareDiscoverySessionCallback> sessionProxyCallback = ArgumentCaptor
.forClass(IWifiAwareDiscoverySessionCallback.class);
- ArgumentCaptor<WifiAwarePublishDiscoverySession> publishSession = ArgumentCaptor
- .forClass(WifiAwarePublishDiscoverySession.class);
+ ArgumentCaptor<PublishDiscoverySession> publishSession = ArgumentCaptor
+ .forClass(PublishDiscoverySession.class);
ArgumentCaptor<RttManager.ParcelableRttParams> rttParamCaptor = ArgumentCaptor
.forClass(RttManager.ParcelableRttParams.class);
ArgumentCaptor<RttManager.RttResult[]> rttResultsCaptor = ArgumentCaptor
@@ -953,7 +949,7 @@
public void testNetworkSpecifierWithClient() throws Exception {
final int clientId = 4565;
final int sessionId = 123;
- final WifiAwareManager.PeerHandle peerHandle = new WifiAwareManager.PeerHandle(123412);
+ final PeerHandle peerHandle = new PeerHandle(123412);
final int role = WifiAwareManager.WIFI_AWARE_DATA_PATH_ROLE_RESPONDER;
final String token = "Some arbitrary token string - can really be anything";
final ConfigRequest configRequest = new ConfigRequest.Builder().build();
@@ -967,8 +963,8 @@
.forClass(IWifiAwareEventCallback.class);
ArgumentCaptor<IWifiAwareDiscoverySessionCallback> sessionProxyCallback = ArgumentCaptor
.forClass(IWifiAwareDiscoverySessionCallback.class);
- ArgumentCaptor<WifiAwarePublishDiscoverySession> publishSession = ArgumentCaptor
- .forClass(WifiAwarePublishDiscoverySession.class);
+ ArgumentCaptor<PublishDiscoverySession> publishSession = ArgumentCaptor
+ .forClass(PublishDiscoverySession.class);
InOrder inOrder = inOrder(mockCallback, mockSessionCallback, mockAwareService,
mockPublishSession, mockRttListener);