Merge "Add more javadoc to ConnectEvent and DnsEvent"
diff --git a/api/current.txt b/api/current.txt
index 0bda570..38bb68b 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -11872,6 +11872,7 @@
method public void beginTransactionWithListenerNonExclusive(android.database.sqlite.SQLiteTransactionListener);
method public android.database.sqlite.SQLiteStatement compileStatement(java.lang.String) throws android.database.SQLException;
method public static android.database.sqlite.SQLiteDatabase create(android.database.sqlite.SQLiteDatabase.CursorFactory);
+ method public static android.database.sqlite.SQLiteDatabase createInMemory(android.database.sqlite.SQLiteDatabase.OpenParams);
method public int delete(java.lang.String, java.lang.String, java.lang.String[]);
method public static boolean deleteDatabase(java.io.File);
method public void disableWriteAheadLogging();
@@ -11901,6 +11902,7 @@
method public boolean needUpgrade(int);
method protected void onAllReferencesReleased();
method public static android.database.sqlite.SQLiteDatabase openDatabase(java.lang.String, android.database.sqlite.SQLiteDatabase.CursorFactory, int);
+ method public static android.database.sqlite.SQLiteDatabase openDatabase(java.lang.String, android.database.sqlite.SQLiteDatabase.OpenParams);
method public static android.database.sqlite.SQLiteDatabase openDatabase(java.lang.String, android.database.sqlite.SQLiteDatabase.CursorFactory, int, android.database.DatabaseErrorHandler);
method public static android.database.sqlite.SQLiteDatabase openOrCreateDatabase(java.io.File, android.database.sqlite.SQLiteDatabase.CursorFactory);
method public static android.database.sqlite.SQLiteDatabase openOrCreateDatabase(java.lang.String, android.database.sqlite.SQLiteDatabase.CursorFactory);
@@ -11951,6 +11953,26 @@
method public abstract android.database.Cursor newCursor(android.database.sqlite.SQLiteDatabase, android.database.sqlite.SQLiteCursorDriver, java.lang.String, android.database.sqlite.SQLiteQuery);
}
+ public static final class SQLiteDatabase.OpenParams {
+ method public android.database.sqlite.SQLiteDatabase.CursorFactory getCursorFactory();
+ method public android.database.DatabaseErrorHandler getErrorHandler();
+ method public int getLookasideSlotCount();
+ method public int getLookasideSlotSize();
+ method public int getOpenFlags();
+ }
+
+ public static final class SQLiteDatabase.OpenParams.Builder {
+ ctor public SQLiteDatabase.OpenParams.Builder();
+ ctor public SQLiteDatabase.OpenParams.Builder(android.database.sqlite.SQLiteDatabase.OpenParams);
+ method public android.database.sqlite.SQLiteDatabase.OpenParams.Builder addOpenFlags(int);
+ method public android.database.sqlite.SQLiteDatabase.OpenParams build();
+ method public android.database.sqlite.SQLiteDatabase.OpenParams.Builder removeOpenFlags(int);
+ method public android.database.sqlite.SQLiteDatabase.OpenParams.Builder setCursorFactory(android.database.sqlite.SQLiteDatabase.CursorFactory);
+ method public android.database.sqlite.SQLiteDatabase.OpenParams.Builder setErrorHandler(android.database.DatabaseErrorHandler);
+ method public android.database.sqlite.SQLiteDatabase.OpenParams.Builder setLookasideConfig(int, int);
+ method public android.database.sqlite.SQLiteDatabase.OpenParams.Builder setOpenFlags(int);
+ }
+
public class SQLiteDatabaseCorruptException extends android.database.sqlite.SQLiteException {
ctor public SQLiteDatabaseCorruptException();
ctor public SQLiteDatabaseCorruptException(java.lang.String);
@@ -12004,6 +12026,7 @@
method public void onDowngrade(android.database.sqlite.SQLiteDatabase, int, int);
method public void onOpen(android.database.sqlite.SQLiteDatabase);
method public abstract void onUpgrade(android.database.sqlite.SQLiteDatabase, int, int);
+ method public void setLookasideConfig(int, int);
method public void setWriteAheadLoggingEnabled(boolean);
}
@@ -44110,7 +44133,6 @@
field public static final int KEYBOARD_TAP = 3; // 0x3
field public static final int LONG_PRESS = 0; // 0x0
field public static final int VIRTUAL_KEY = 1; // 0x1
- field public static final int VIRTUAL_KEY_RELEASE = 7; // 0x7
}
public class InflateException extends java.lang.RuntimeException {
@@ -71714,6 +71736,8 @@
public class JSONException extends java.lang.Exception {
ctor public JSONException(java.lang.String);
+ ctor public JSONException(java.lang.String, java.lang.Throwable);
+ ctor public JSONException(java.lang.Throwable);
}
public class JSONObject {
diff --git a/api/system-current.txt b/api/system-current.txt
index 12d3d96..d98319c 100644
--- a/api/system-current.txt
+++ b/api/system-current.txt
@@ -120,6 +120,7 @@
field public static final java.lang.String GRANT_RUNTIME_PERMISSIONS = "android.permission.GRANT_RUNTIME_PERMISSIONS";
field public static final java.lang.String HARDWARE_TEST = "android.permission.HARDWARE_TEST";
field public static final java.lang.String HDMI_CEC = "android.permission.HDMI_CEC";
+ field public static final java.lang.String HIDE_NON_SYSTEM_OVERLAY_WINDOWS = "android.permission.HIDE_NON_SYSTEM_OVERLAY_WINDOWS";
field public static final java.lang.String INJECT_EVENTS = "android.permission.INJECT_EVENTS";
field public static final java.lang.String INSTALL_GRANT_RUNTIME_PERMISSIONS = "android.permission.INSTALL_GRANT_RUNTIME_PERMISSIONS";
field public static final java.lang.String INSTALL_LOCATION_PROVIDER = "android.permission.INSTALL_LOCATION_PROVIDER";
@@ -178,6 +179,7 @@
field public static final java.lang.String READ_CALENDAR = "android.permission.READ_CALENDAR";
field public static final java.lang.String READ_CALL_LOG = "android.permission.READ_CALL_LOG";
field public static final java.lang.String READ_CONTACTS = "android.permission.READ_CONTACTS";
+ field public static final java.lang.String READ_CONTENT_RATING_SYSTEMS = "android.permission.READ_CONTENT_RATING_SYSTEMS";
field public static final java.lang.String READ_DREAM_STATE = "android.permission.READ_DREAM_STATE";
field public static final java.lang.String READ_EXTERNAL_STORAGE = "android.permission.READ_EXTERNAL_STORAGE";
field public static final java.lang.String READ_FRAME_BUFFER = "android.permission.READ_FRAME_BUFFER";
@@ -12659,6 +12661,7 @@
method public void beginTransactionWithListenerNonExclusive(android.database.sqlite.SQLiteTransactionListener);
method public android.database.sqlite.SQLiteStatement compileStatement(java.lang.String) throws android.database.SQLException;
method public static android.database.sqlite.SQLiteDatabase create(android.database.sqlite.SQLiteDatabase.CursorFactory);
+ method public static android.database.sqlite.SQLiteDatabase createInMemory(android.database.sqlite.SQLiteDatabase.OpenParams);
method public int delete(java.lang.String, java.lang.String, java.lang.String[]);
method public static boolean deleteDatabase(java.io.File);
method public void disableWriteAheadLogging();
@@ -12688,6 +12691,7 @@
method public boolean needUpgrade(int);
method protected void onAllReferencesReleased();
method public static android.database.sqlite.SQLiteDatabase openDatabase(java.lang.String, android.database.sqlite.SQLiteDatabase.CursorFactory, int);
+ method public static android.database.sqlite.SQLiteDatabase openDatabase(java.lang.String, android.database.sqlite.SQLiteDatabase.OpenParams);
method public static android.database.sqlite.SQLiteDatabase openDatabase(java.lang.String, android.database.sqlite.SQLiteDatabase.CursorFactory, int, android.database.DatabaseErrorHandler);
method public static android.database.sqlite.SQLiteDatabase openOrCreateDatabase(java.io.File, android.database.sqlite.SQLiteDatabase.CursorFactory);
method public static android.database.sqlite.SQLiteDatabase openOrCreateDatabase(java.lang.String, android.database.sqlite.SQLiteDatabase.CursorFactory);
@@ -12738,6 +12742,26 @@
method public abstract android.database.Cursor newCursor(android.database.sqlite.SQLiteDatabase, android.database.sqlite.SQLiteCursorDriver, java.lang.String, android.database.sqlite.SQLiteQuery);
}
+ public static final class SQLiteDatabase.OpenParams {
+ method public android.database.sqlite.SQLiteDatabase.CursorFactory getCursorFactory();
+ method public android.database.DatabaseErrorHandler getErrorHandler();
+ method public int getLookasideSlotCount();
+ method public int getLookasideSlotSize();
+ method public int getOpenFlags();
+ }
+
+ public static final class SQLiteDatabase.OpenParams.Builder {
+ ctor public SQLiteDatabase.OpenParams.Builder();
+ ctor public SQLiteDatabase.OpenParams.Builder(android.database.sqlite.SQLiteDatabase.OpenParams);
+ method public android.database.sqlite.SQLiteDatabase.OpenParams.Builder addOpenFlags(int);
+ method public android.database.sqlite.SQLiteDatabase.OpenParams build();
+ method public android.database.sqlite.SQLiteDatabase.OpenParams.Builder removeOpenFlags(int);
+ method public android.database.sqlite.SQLiteDatabase.OpenParams.Builder setCursorFactory(android.database.sqlite.SQLiteDatabase.CursorFactory);
+ method public android.database.sqlite.SQLiteDatabase.OpenParams.Builder setErrorHandler(android.database.DatabaseErrorHandler);
+ method public android.database.sqlite.SQLiteDatabase.OpenParams.Builder setLookasideConfig(int, int);
+ method public android.database.sqlite.SQLiteDatabase.OpenParams.Builder setOpenFlags(int);
+ }
+
public class SQLiteDatabaseCorruptException extends android.database.sqlite.SQLiteException {
ctor public SQLiteDatabaseCorruptException();
ctor public SQLiteDatabaseCorruptException(java.lang.String);
@@ -12791,6 +12815,7 @@
method public void onDowngrade(android.database.sqlite.SQLiteDatabase, int, int);
method public void onOpen(android.database.sqlite.SQLiteDatabase);
method public abstract void onUpgrade(android.database.sqlite.SQLiteDatabase, int, int);
+ method public void setLookasideConfig(int, int);
method public void setWriteAheadLoggingEnabled(boolean);
}
@@ -47660,7 +47685,6 @@
field public static final int KEYBOARD_TAP = 3; // 0x3
field public static final int LONG_PRESS = 0; // 0x0
field public static final int VIRTUAL_KEY = 1; // 0x1
- field public static final int VIRTUAL_KEY_RELEASE = 7; // 0x7
}
public class InflateException extends java.lang.RuntimeException {
@@ -75637,6 +75661,8 @@
public class JSONException extends java.lang.Exception {
ctor public JSONException(java.lang.String);
+ ctor public JSONException(java.lang.String, java.lang.Throwable);
+ ctor public JSONException(java.lang.Throwable);
}
public class JSONObject {
diff --git a/api/test-current.txt b/api/test-current.txt
index 6d401e1..94bfe84 100644
--- a/api/test-current.txt
+++ b/api/test-current.txt
@@ -10673,6 +10673,7 @@
method public abstract int getPackageUid(java.lang.String, int) throws android.content.pm.PackageManager.NameNotFoundException;
method public abstract java.lang.String[] getPackagesForUid(int);
method public abstract java.util.List<android.content.pm.PackageInfo> getPackagesHoldingPermissions(java.lang.String[], int);
+ method public abstract java.lang.String getPermissionControllerPackageName();
method public abstract android.content.pm.PermissionGroupInfo getPermissionGroupInfo(java.lang.String, int) throws android.content.pm.PackageManager.NameNotFoundException;
method public abstract android.content.pm.PermissionInfo getPermissionInfo(java.lang.String, int) throws android.content.pm.PackageManager.NameNotFoundException;
method public abstract int getPreferredActivities(java.util.List<android.content.IntentFilter>, java.util.List<android.content.ComponentName>, java.lang.String);
@@ -11915,6 +11916,7 @@
method public void beginTransactionWithListenerNonExclusive(android.database.sqlite.SQLiteTransactionListener);
method public android.database.sqlite.SQLiteStatement compileStatement(java.lang.String) throws android.database.SQLException;
method public static android.database.sqlite.SQLiteDatabase create(android.database.sqlite.SQLiteDatabase.CursorFactory);
+ method public static android.database.sqlite.SQLiteDatabase createInMemory(android.database.sqlite.SQLiteDatabase.OpenParams);
method public int delete(java.lang.String, java.lang.String, java.lang.String[]);
method public static boolean deleteDatabase(java.io.File);
method public void disableWriteAheadLogging();
@@ -11944,6 +11946,7 @@
method public boolean needUpgrade(int);
method protected void onAllReferencesReleased();
method public static android.database.sqlite.SQLiteDatabase openDatabase(java.lang.String, android.database.sqlite.SQLiteDatabase.CursorFactory, int);
+ method public static android.database.sqlite.SQLiteDatabase openDatabase(java.lang.String, android.database.sqlite.SQLiteDatabase.OpenParams);
method public static android.database.sqlite.SQLiteDatabase openDatabase(java.lang.String, android.database.sqlite.SQLiteDatabase.CursorFactory, int, android.database.DatabaseErrorHandler);
method public static android.database.sqlite.SQLiteDatabase openOrCreateDatabase(java.io.File, android.database.sqlite.SQLiteDatabase.CursorFactory);
method public static android.database.sqlite.SQLiteDatabase openOrCreateDatabase(java.lang.String, android.database.sqlite.SQLiteDatabase.CursorFactory);
@@ -11994,6 +11997,26 @@
method public abstract android.database.Cursor newCursor(android.database.sqlite.SQLiteDatabase, android.database.sqlite.SQLiteCursorDriver, java.lang.String, android.database.sqlite.SQLiteQuery);
}
+ public static final class SQLiteDatabase.OpenParams {
+ method public android.database.sqlite.SQLiteDatabase.CursorFactory getCursorFactory();
+ method public android.database.DatabaseErrorHandler getErrorHandler();
+ method public int getLookasideSlotCount();
+ method public int getLookasideSlotSize();
+ method public int getOpenFlags();
+ }
+
+ public static final class SQLiteDatabase.OpenParams.Builder {
+ ctor public SQLiteDatabase.OpenParams.Builder();
+ ctor public SQLiteDatabase.OpenParams.Builder(android.database.sqlite.SQLiteDatabase.OpenParams);
+ method public android.database.sqlite.SQLiteDatabase.OpenParams.Builder addOpenFlags(int);
+ method public android.database.sqlite.SQLiteDatabase.OpenParams build();
+ method public android.database.sqlite.SQLiteDatabase.OpenParams.Builder removeOpenFlags(int);
+ method public android.database.sqlite.SQLiteDatabase.OpenParams.Builder setCursorFactory(android.database.sqlite.SQLiteDatabase.CursorFactory);
+ method public android.database.sqlite.SQLiteDatabase.OpenParams.Builder setErrorHandler(android.database.DatabaseErrorHandler);
+ method public android.database.sqlite.SQLiteDatabase.OpenParams.Builder setLookasideConfig(int, int);
+ method public android.database.sqlite.SQLiteDatabase.OpenParams.Builder setOpenFlags(int);
+ }
+
public class SQLiteDatabaseCorruptException extends android.database.sqlite.SQLiteException {
ctor public SQLiteDatabaseCorruptException();
ctor public SQLiteDatabaseCorruptException(java.lang.String);
@@ -12047,6 +12070,7 @@
method public void onDowngrade(android.database.sqlite.SQLiteDatabase, int, int);
method public void onOpen(android.database.sqlite.SQLiteDatabase);
method public abstract void onUpgrade(android.database.sqlite.SQLiteDatabase, int, int);
+ method public void setLookasideConfig(int, int);
method public void setWriteAheadLoggingEnabled(boolean);
}
@@ -41203,6 +41227,7 @@
method public int getPackageUid(java.lang.String, int) throws android.content.pm.PackageManager.NameNotFoundException;
method public java.lang.String[] getPackagesForUid(int);
method public java.util.List<android.content.pm.PackageInfo> getPackagesHoldingPermissions(java.lang.String[], int);
+ method public java.lang.String getPermissionControllerPackageName();
method public android.content.pm.PermissionGroupInfo getPermissionGroupInfo(java.lang.String, int) throws android.content.pm.PackageManager.NameNotFoundException;
method public android.content.pm.PermissionInfo getPermissionInfo(java.lang.String, int) throws android.content.pm.PackageManager.NameNotFoundException;
method public int getPreferredActivities(java.util.List<android.content.IntentFilter>, java.util.List<android.content.ComponentName>, java.lang.String);
@@ -44509,7 +44534,6 @@
field public static final int KEYBOARD_TAP = 3; // 0x3
field public static final int LONG_PRESS = 0; // 0x0
field public static final int VIRTUAL_KEY = 1; // 0x1
- field public static final int VIRTUAL_KEY_RELEASE = 7; // 0x7
}
public class InflateException extends java.lang.RuntimeException {
@@ -72150,6 +72174,8 @@
public class JSONException extends java.lang.Exception {
ctor public JSONException(java.lang.String);
+ ctor public JSONException(java.lang.String, java.lang.Throwable);
+ ctor public JSONException(java.lang.Throwable);
}
public class JSONObject {
diff --git a/core/java/android/app/ActivityThread.java b/core/java/android/app/ActivityThread.java
index 074cdef..cb648d5 100644
--- a/core/java/android/app/ActivityThread.java
+++ b/core/java/android/app/ActivityThread.java
@@ -100,6 +100,7 @@
import android.util.EventLog;
import android.util.Log;
import android.util.LogPrinter;
+import android.util.LogWriter;
import android.util.Pair;
import android.util.PrintWriterPrinter;
import android.util.Slog;
@@ -125,6 +126,7 @@
import com.android.internal.os.SomeArgs;
import com.android.internal.util.ArrayUtils;
import com.android.internal.util.FastPrintWriter;
+import com.android.internal.util.IndentingPrintWriter;
import com.android.org.conscrypt.OpenSSLSocketImpl;
import com.android.org.conscrypt.TrustedCertificateStore;
@@ -133,8 +135,6 @@
import dalvik.system.VMDebug;
import dalvik.system.VMRuntime;
-import com.google.android.collect.Lists;
-
import libcore.io.DropBox;
import libcore.io.EventLogger;
import libcore.io.IoUtils;
@@ -152,6 +152,7 @@
import java.net.InetAddress;
import java.text.DateFormat;
import java.util.ArrayList;
+import java.util.Arrays;
import java.util.List;
import java.util.Locale;
import java.util.Map;
@@ -3052,7 +3053,7 @@
public void handleInstallProvider(ProviderInfo info) {
final StrictMode.ThreadPolicy oldPolicy = StrictMode.allowThreadDiskWrites();
try {
- installContentProviders(mInitialApplication, Lists.newArrayList(info));
+ installContentProviders(mInitialApplication, Arrays.asList(info));
} finally {
StrictMode.setThreadPolicy(oldPolicy);
}
@@ -3935,6 +3936,14 @@
ActivityManager.getService().activityStopped(
activity.token, state, persistentState, description);
} catch (RemoteException ex) {
+ // Dump statistics about bundle to help developers debug
+ final LogWriter writer = new LogWriter(Log.WARN, TAG);
+ final IndentingPrintWriter pw = new IndentingPrintWriter(writer, " ");
+ pw.println("Bundle stats:");
+ Bundle.dumpStats(pw, state);
+ pw.println("PersistableBundle stats:");
+ Bundle.dumpStats(pw, persistentState);
+
if (ex instanceof TransactionTooLargeException
&& activity.packageInfo.getTargetSdkVersion() < Build.VERSION_CODES.N) {
Log.e(TAG, "App sent too much data in instance state, so it was ignored", ex);
diff --git a/core/java/android/app/IWallpaperManager.aidl b/core/java/android/app/IWallpaperManager.aidl
index 411d0e2..0e33934 100644
--- a/core/java/android/app/IWallpaperManager.aidl
+++ b/core/java/android/app/IWallpaperManager.aidl
@@ -60,7 +60,7 @@
/**
* Get the wallpaper for a given user.
*/
- ParcelFileDescriptor getWallpaper(IWallpaperManagerCallback cb, int which,
+ ParcelFileDescriptor getWallpaper(String callingPkg, IWallpaperManagerCallback cb, int which,
out Bundle outParams, int userId);
/**
diff --git a/core/java/android/app/SystemServiceRegistry.java b/core/java/android/app/SystemServiceRegistry.java
index 9a019b8..f18aa58 100644
--- a/core/java/android/app/SystemServiceRegistry.java
+++ b/core/java/android/app/SystemServiceRegistry.java
@@ -39,6 +39,7 @@
import android.content.RestrictionsManager;
import android.content.pm.IShortcutService;
import android.content.pm.LauncherApps;
+import android.content.pm.PackageManager;
import android.content.pm.ShortcutManager;
import android.content.res.Resources;
import android.hardware.ConsumerIrManager;
@@ -651,25 +652,30 @@
new CachedServiceFetcher<PrintManager>() {
@Override
public PrintManager createService(ContextImpl ctx) throws ServiceNotFoundException {
- // Get the services without throwing as this is an optional feature
- IBinder iBinder = ServiceManager.getService(Context.PRINT_SERVICE);
- IPrintManager service = IPrintManager.Stub.asInterface(iBinder);
+ IPrintManager service = null;
+ // If the feature not present, don't try to look up every time
+ if (ctx.getPackageManager().hasSystemFeature(PackageManager.FEATURE_PRINTING)) {
+ service = IPrintManager.Stub.asInterface(ServiceManager
+ .getServiceOrThrow(Context.PRINT_SERVICE));
+ }
return new PrintManager(ctx.getOuterContext(), service, UserHandle.myUserId(),
UserHandle.getAppId(Process.myUid()));
}});
registerService(Context.COMPANION_DEVICE_SERVICE, CompanionDeviceManager.class,
new CachedServiceFetcher<CompanionDeviceManager>() {
- @Override
- public CompanionDeviceManager createService(ContextImpl ctx)
- throws ServiceNotFoundException {
- // Get the services without throwing as this is an optional feature
- IBinder iBinder =
- ServiceManager.getService(Context.COMPANION_DEVICE_SERVICE);
- ICompanionDeviceManager service =
- ICompanionDeviceManager.Stub.asInterface(iBinder);
- return new CompanionDeviceManager(service, ctx.getOuterContext());
- }});
+ @Override
+ public CompanionDeviceManager createService(ContextImpl ctx)
+ throws ServiceNotFoundException {
+ ICompanionDeviceManager service = null;
+ // If the feature not present, don't try to look up every time
+ if (ctx.getPackageManager().hasSystemFeature(
+ PackageManager.FEATURE_COMPANION_DEVICE_SETUP)) {
+ service = ICompanionDeviceManager.Stub.asInterface(
+ ServiceManager.getServiceOrThrow(Context.COMPANION_DEVICE_SERVICE));
+ }
+ return new CompanionDeviceManager(service, ctx.getOuterContext());
+ }});
registerService(Context.CONSUMER_IR_SERVICE, ConsumerIrManager.class,
new CachedServiceFetcher<ConsumerIrManager>() {
diff --git a/core/java/android/app/WallpaperManager.java b/core/java/android/app/WallpaperManager.java
index 0b8b689..0398b47 100644
--- a/core/java/android/app/WallpaperManager.java
+++ b/core/java/android/app/WallpaperManager.java
@@ -48,6 +48,7 @@
import android.graphics.drawable.BitmapDrawable;
import android.graphics.drawable.Drawable;
import android.net.Uri;
+import android.os.Build;
import android.os.Bundle;
import android.os.DeadSystemException;
import android.os.Handler;
@@ -404,10 +405,18 @@
mCachedWallpaper = null;
mCachedWallpaperUserId = 0;
try {
- mCachedWallpaper = getCurrentWallpaperLocked(userId);
+ mCachedWallpaper = getCurrentWallpaperLocked(context, userId);
mCachedWallpaperUserId = userId;
} catch (OutOfMemoryError e) {
- Log.w(TAG, "No memory load current wallpaper", e);
+ Log.w(TAG, "Out of memory loading the current wallpaper: " + e);
+ } catch (SecurityException e) {
+ if (context.getApplicationInfo().targetSdkVersion <= Build.VERSION_CODES.O) {
+ Log.w(TAG, "No permission to access wallpaper, suppressing"
+ + " exception to avoid crashing legacy app.");
+ } else {
+ // Post-O apps really most sincerely need the permission.
+ throw e;
+ }
}
if (mCachedWallpaper != null) {
return mCachedWallpaper;
@@ -434,7 +443,7 @@
}
}
- private Bitmap getCurrentWallpaperLocked(int userId) {
+ private Bitmap getCurrentWallpaperLocked(Context context, int userId) {
if (mService == null) {
Log.w(TAG, "WallpaperService not running");
return null;
@@ -442,8 +451,8 @@
try {
Bundle params = new Bundle();
- ParcelFileDescriptor fd = mService.getWallpaper(this, FLAG_SYSTEM,
- params, userId);
+ ParcelFileDescriptor fd = mService.getWallpaper(context.getOpPackageName(),
+ this, FLAG_SYSTEM, params, userId);
if (fd != null) {
try {
BitmapFactory.Options options = new BitmapFactory.Options();
@@ -775,6 +784,7 @@
*
* @return Returns a Drawable object that will draw the wallpaper.
*/
+ @RequiresPermission(android.Manifest.permission.READ_EXTERNAL_STORAGE)
public Drawable getFastDrawable() {
Bitmap bm = sGlobals.peekWallpaperBitmap(mContext, true, FLAG_SYSTEM);
if (bm != null) {
@@ -790,6 +800,7 @@
* @return Returns an optimized Drawable object that will draw the
* wallpaper or a null pointer if these is none.
*/
+ @RequiresPermission(android.Manifest.permission.READ_EXTERNAL_STORAGE)
public Drawable peekFastDrawable() {
Bitmap bm = sGlobals.peekWallpaperBitmap(mContext, false, FLAG_SYSTEM);
if (bm != null) {
@@ -827,10 +838,14 @@
* @param which The wallpaper whose image file is to be retrieved. Must be a single
* defined kind of wallpaper, either {@link #FLAG_SYSTEM} or
* {@link #FLAG_LOCK}.
+ * @return An open, readable file desriptor to the requested wallpaper image file;
+ * or {@code null} if no such wallpaper is configured or if the calling app does
+ * not have permission to read the current wallpaper.
*
* @see #FLAG_LOCK
* @see #FLAG_SYSTEM
*/
+ @RequiresPermission(android.Manifest.permission.READ_EXTERNAL_STORAGE)
public ParcelFileDescriptor getWallpaperFile(@SetWallpaperFlags int which) {
return getWallpaperFile(which, mContext.getUserId());
}
@@ -900,9 +915,18 @@
} else {
try {
Bundle outParams = new Bundle();
- return sGlobals.mService.getWallpaper(null, which, outParams, userId);
+ return sGlobals.mService.getWallpaper(mContext.getOpPackageName(), null, which,
+ outParams, userId);
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
+ } catch (SecurityException e) {
+ if (mContext.getApplicationInfo().targetSdkVersion <= Build.VERSION_CODES.O) {
+ Log.w(TAG, "No permission to access wallpaper, suppressing"
+ + " exception to avoid crashing legacy app.");
+ return null;
+ } else {
+ throw e;
+ }
}
}
}
@@ -1042,6 +1066,7 @@
* @throws IOException If an error occurs reverting to the built-in
* wallpaper.
*/
+ @RequiresPermission(android.Manifest.permission.SET_WALLPAPER)
public void setResource(@RawRes int resid) throws IOException {
setResource(resid, FLAG_SYSTEM | FLAG_LOCK);
}
@@ -1060,6 +1085,7 @@
*
* @throws IOException
*/
+ @RequiresPermission(android.Manifest.permission.SET_WALLPAPER)
public int setResource(@RawRes int resid, @SetWallpaperFlags int which)
throws IOException {
if (sGlobals.mService == null) {
@@ -1115,6 +1141,7 @@
* @throws IOException If an error occurs when attempting to set the wallpaper
* to the provided image.
*/
+ @RequiresPermission(android.Manifest.permission.SET_WALLPAPER)
public void setBitmap(Bitmap bitmap) throws IOException {
setBitmap(bitmap, null, true);
}
@@ -1147,6 +1174,7 @@
* @throws IllegalArgumentException If the {@code visibleCropHint} rectangle is
* empty or invalid.
*/
+ @RequiresPermission(android.Manifest.permission.SET_WALLPAPER)
public int setBitmap(Bitmap fullImage, Rect visibleCropHint, boolean allowBackup)
throws IOException {
return setBitmap(fullImage, visibleCropHint, allowBackup, FLAG_SYSTEM | FLAG_LOCK);
@@ -1172,6 +1200,7 @@
*
* @throws IOException
*/
+ @RequiresPermission(android.Manifest.permission.SET_WALLPAPER)
public int setBitmap(Bitmap fullImage, Rect visibleCropHint,
boolean allowBackup, @SetWallpaperFlags int which)
throws IOException {
@@ -1243,6 +1272,7 @@
* @throws IOException If an error occurs when attempting to set the wallpaper
* based on the provided image data.
*/
+ @RequiresPermission(android.Manifest.permission.SET_WALLPAPER)
public void setStream(InputStream bitmapData) throws IOException {
setStream(bitmapData, null, true);
}
@@ -1285,6 +1315,7 @@
* @throws IllegalArgumentException If the {@code visibleCropHint} rectangle is
* empty or invalid.
*/
+ @RequiresPermission(android.Manifest.permission.SET_WALLPAPER)
public int setStream(InputStream bitmapData, Rect visibleCropHint, boolean allowBackup)
throws IOException {
return setStream(bitmapData, visibleCropHint, allowBackup, FLAG_SYSTEM | FLAG_LOCK);
@@ -1311,6 +1342,7 @@
*
* @throws IOException
*/
+ @RequiresPermission(android.Manifest.permission.SET_WALLPAPER)
public int setStream(InputStream bitmapData, Rect visibleCropHint,
boolean allowBackup, @SetWallpaperFlags int which)
throws IOException {
@@ -1572,6 +1604,7 @@
*
* @hide
*/
+ @RequiresPermission(android.Manifest.permission.SET_WALLPAPER_COMPONENT)
public boolean setWallpaperComponent(ComponentName name, int userId) {
if (sGlobals.mService == null) {
Log.w(TAG, "WallpaperService not running");
@@ -1716,6 +1749,7 @@
* @throws IOException If an error occurs reverting to the built-in
* wallpaper.
*/
+ @RequiresPermission(android.Manifest.permission.SET_WALLPAPER)
public void clear() throws IOException {
setStream(openDefaultWallpaper(mContext, FLAG_SYSTEM), null, false);
}
@@ -1730,6 +1764,7 @@
* {@link #FLAG_LOCK}
* @throws IOException If an error occurs reverting to the built-in wallpaper.
*/
+ @RequiresPermission(android.Manifest.permission.SET_WALLPAPER)
public void clear(@SetWallpaperFlags int which) throws IOException {
if ((which & FLAG_SYSTEM) != 0) {
clear();
diff --git a/core/java/android/app/job/JobParameters.java b/core/java/android/app/job/JobParameters.java
index 98bdde8..a6f6be2 100644
--- a/core/java/android/app/job/JobParameters.java
+++ b/core/java/android/app/job/JobParameters.java
@@ -45,6 +45,18 @@
/** @hide */
public static final int REASON_DEVICE_IDLE = 4;
+ /** @hide */
+ public static String getReasonName(int reason) {
+ switch (reason) {
+ case REASON_CANCELED: return "canceled";
+ case REASON_CONSTRAINTS_NOT_SATISFIED: return "constraints";
+ case REASON_PREEMPT: return "preempt";
+ case REASON_TIMEOUT: return "timeout";
+ case REASON_DEVICE_IDLE: return "device_idle";
+ default: return "unknown:" + reason;
+ }
+ }
+
private final int jobId;
private final PersistableBundle extras;
private final Bundle transientExtras;
diff --git a/core/java/android/app/timezone/DistroRulesVersion.java b/core/java/android/app/timezone/DistroRulesVersion.java
index 5503ce1..1eb9f45 100644
--- a/core/java/android/app/timezone/DistroRulesVersion.java
+++ b/core/java/android/app/timezone/DistroRulesVersion.java
@@ -125,4 +125,8 @@
+ ", mRevision='" + mRevision + '\''
+ '}';
}
+
+ public String toDumpString() {
+ return mRulesVersion + "," + mRevision;
+ }
}
diff --git a/core/java/android/content/pm/PackageManager.java b/core/java/android/content/pm/PackageManager.java
index 712d37f..b8e751e 100644
--- a/core/java/android/content/pm/PackageManager.java
+++ b/core/java/android/content/pm/PackageManager.java
@@ -3305,6 +3305,7 @@
*
* @hide
*/
+ @TestApi
public abstract String getPermissionControllerPackageName();
/**
diff --git a/core/java/android/content/res/Configuration.java b/core/java/android/content/res/Configuration.java
index 6834ba8..be31d1b 100644
--- a/core/java/android/content/res/Configuration.java
+++ b/core/java/android/content/res/Configuration.java
@@ -42,6 +42,9 @@
import java.util.ArrayList;
import java.util.Locale;
+import static android.view.Surface.ROTATION_0;
+import static android.view.Surface.ROTATION_UNDEFINED;
+
/**
* This class describes all device configuration information that can
* impact the resources the application retrieves. This includes both
@@ -597,6 +600,13 @@
*/
public int orientation;
+ /**
+ * The mRotation used at the time orientation was determined.
+ * TODO(b/36812336): Move mRotation out of {@link Configuration}.
+ * {@hide}
+ */
+ private int mRotation;
+
/** Constant for {@link #uiMode}: bits that encode the mode type. */
public static final int UI_MODE_TYPE_MASK = 0x0f;
/** Constant for {@link #uiMode}: a {@link #UI_MODE_TYPE_MASK}
@@ -884,6 +894,7 @@
navigation = o.navigation;
navigationHidden = o.navigationHidden;
orientation = o.orientation;
+ mRotation = o.mRotation;
screenLayout = o.screenLayout;
colorMode = o.colorMode;
uiMode = o.uiMode;
@@ -1074,6 +1085,7 @@
navigation = NAVIGATION_UNDEFINED;
navigationHidden = NAVIGATIONHIDDEN_UNDEFINED;
orientation = ORIENTATION_UNDEFINED;
+ mRotation = ROTATION_UNDEFINED;
screenLayout = SCREENLAYOUT_UNDEFINED;
colorMode = COLOR_MODE_UNDEFINED;
uiMode = UI_MODE_TYPE_UNDEFINED;
@@ -1182,6 +1194,11 @@
changed |= ActivityInfo.CONFIG_ORIENTATION;
orientation = delta.orientation;
}
+ if (delta.mRotation != ROTATION_UNDEFINED
+ && mRotation != delta.mRotation) {
+ changed |= ActivityInfo.CONFIG_ORIENTATION;
+ mRotation = delta.mRotation;
+ }
if (((delta.screenLayout & SCREENLAYOUT_SIZE_MASK) != SCREENLAYOUT_SIZE_UNDEFINED)
&& (delta.screenLayout & SCREENLAYOUT_SIZE_MASK)
@@ -1376,6 +1393,10 @@
&& orientation != delta.orientation) {
changed |= ActivityInfo.CONFIG_ORIENTATION;
}
+ if ((compareUndefined || delta.mRotation != ROTATION_UNDEFINED)
+ && mRotation != delta.mRotation) {
+ changed |= ActivityInfo.CONFIG_ORIENTATION;
+ }
if ((compareUndefined || getScreenLayoutNoDirection(delta.screenLayout) !=
(SCREENLAYOUT_SIZE_UNDEFINED | SCREENLAYOUT_LONG_UNDEFINED))
&& getScreenLayoutNoDirection(screenLayout) !=
@@ -1512,6 +1533,7 @@
dest.writeInt(navigation);
dest.writeInt(navigationHidden);
dest.writeInt(orientation);
+ dest.writeInt(mRotation);
dest.writeInt(screenLayout);
dest.writeInt(colorMode);
dest.writeInt(uiMode);
@@ -1548,6 +1570,7 @@
navigation = source.readInt();
navigationHidden = source.readInt();
orientation = source.readInt();
+ mRotation = source.readInt();
screenLayout = source.readInt();
colorMode = source.readInt();
uiMode = source.readInt();
@@ -1632,6 +1655,8 @@
if (n != 0) return n;
n = this.orientation - that.orientation;
if (n != 0) return n;
+ n = this.mRotation - that.mRotation;
+ if (n != 0) return n;
n = this.colorMode - that.colorMode;
if (n != 0) return n;
n = this.screenLayout - that.screenLayout;
@@ -1763,6 +1788,24 @@
/**
* @hide
*
+ * Setter for orientation converts from {@link Surface} values to internal representation.
+ */
+ public void setRotation(int rotation) {
+ this.mRotation = rotation;
+ }
+
+ /**
+ * @hide
+ *
+ * Getter for orientation. Converts from internal representation to {@link Surface} values.
+ */
+ public int getRotation() {
+ return mRotation != ROTATION_UNDEFINED ? mRotation : ROTATION_0;
+ }
+
+ /**
+ * @hide
+ *
* Clears the locale without changing layout direction.
*/
public void clearLocales() {
@@ -2193,6 +2236,10 @@
delta.orientation = change.orientation;
}
+ if (base.mRotation != change.mRotation) {
+ base.mRotation = change.mRotation;
+ }
+
if ((base.screenLayout & SCREENLAYOUT_SIZE_MASK) !=
(change.screenLayout & SCREENLAYOUT_SIZE_MASK)) {
delta.screenLayout |= change.screenLayout & SCREENLAYOUT_SIZE_MASK;
@@ -2264,6 +2311,7 @@
private static final String XML_ATTR_NAVIGATION = "nav";
private static final String XML_ATTR_NAVIGATION_HIDDEN = "navHid";
private static final String XML_ATTR_ORIENTATION = "ori";
+ private static final String XML_ATTR_ROTATION = "rot";
private static final String XML_ATTR_SCREEN_LAYOUT = "scrLay";
private static final String XML_ATTR_COLOR_MODE = "clrMod";
private static final String XML_ATTR_UI_MODE = "ui";
@@ -2323,6 +2371,8 @@
DENSITY_DPI_UNDEFINED);
configOut.appBounds =
Rect.unflattenFromString(XmlUtils.readStringAttribute(parser, XML_ATTR_APP_BOUNDS));
+ configOut.mRotation = XmlUtils.readIntAttribute(parser, XML_ATTR_ROTATION,
+ ROTATION_UNDEFINED);
// For persistence, we don't care about assetsSeq, so do not read it out.
}
@@ -2399,6 +2449,10 @@
config.appBounds.flattenToString());
}
+ if (config.mRotation != ROTATION_UNDEFINED) {
+ XmlUtils.writeIntAttribute(xml, XML_ATTR_ROTATION, config.mRotation);
+ }
+
// For persistence, we do not care about assetsSeq, so do not write it out.
}
}
diff --git a/core/java/android/database/sqlite/SQLiteConnection.java b/core/java/android/database/sqlite/SQLiteConnection.java
index 34a9523..f894f05 100644
--- a/core/java/android/database/sqlite/SQLiteConnection.java
+++ b/core/java/android/database/sqlite/SQLiteConnection.java
@@ -16,9 +16,6 @@
package android.database.sqlite;
-import dalvik.system.BlockGuard;
-import dalvik.system.CloseGuard;
-
import android.database.Cursor;
import android.database.CursorWindow;
import android.database.DatabaseUtils;
@@ -32,11 +29,14 @@
import android.util.LruCache;
import android.util.Printer;
+import dalvik.system.BlockGuard;
+import dalvik.system.CloseGuard;
+
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.Map;
-import java.util.regex.Pattern;
+
/**
* Represents a SQLite database connection.
@@ -118,7 +118,8 @@
private int mCancellationSignalAttachCount;
private static native long nativeOpen(String path, int openFlags, String label,
- boolean enableTrace, boolean enableProfile);
+ boolean enableTrace, boolean enableProfile, int lookasideSlotSize,
+ int lookasideSlotCount);
private static native void nativeClose(long connectionPtr);
private static native void nativeRegisterCustomFunction(long connectionPtr,
SQLiteCustomFunction function);
@@ -208,8 +209,8 @@
private void open() {
mConnectionPtr = nativeOpen(mConfiguration.path, mConfiguration.openFlags,
mConfiguration.label,
- SQLiteDebug.DEBUG_SQL_STATEMENTS, SQLiteDebug.DEBUG_SQL_TIME);
-
+ SQLiteDebug.DEBUG_SQL_STATEMENTS, SQLiteDebug.DEBUG_SQL_TIME,
+ mConfiguration.lookasideSlotSize, mConfiguration.lookasideSlotCount);
setPageSize();
setForeignKeyModeFromConfiguration();
setWalModeFromConfiguration();
diff --git a/core/java/android/database/sqlite/SQLiteDatabase.java b/core/java/android/database/sqlite/SQLiteDatabase.java
index fe849b8..7406b3f 100644
--- a/core/java/android/database/sqlite/SQLiteDatabase.java
+++ b/core/java/android/database/sqlite/SQLiteDatabase.java
@@ -16,6 +16,8 @@
package android.database.sqlite;
+import android.annotation.IntDef;
+import android.annotation.IntRange;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.content.ContentValues;
@@ -34,10 +36,14 @@
import android.util.Pair;
import android.util.Printer;
+import com.android.internal.util.Preconditions;
+
import dalvik.system.CloseGuard;
import java.io.File;
import java.io.FileFilter;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
@@ -253,11 +259,14 @@
*/
public static final int MAX_SQL_CACHE_SIZE = 100;
- private SQLiteDatabase(String path, int openFlags, CursorFactory cursorFactory,
- DatabaseErrorHandler errorHandler) {
+ private SQLiteDatabase(final String path, final int openFlags,
+ CursorFactory cursorFactory, DatabaseErrorHandler errorHandler,
+ int lookasideSlotSize, int lookasideSlotCount) {
mCursorFactory = cursorFactory;
mErrorHandler = errorHandler != null ? errorHandler : new DefaultDatabaseErrorHandler();
mConfigurationLocked = new SQLiteDatabaseConfiguration(path, openFlags);
+ mConfigurationLocked.lookasideSlotSize = lookasideSlotSize;
+ mConfigurationLocked.lookasideSlotCount = lookasideSlotCount;
}
@Override
@@ -667,11 +676,30 @@
* @return the newly opened database
* @throws SQLiteException if the database cannot be opened
*/
- public static SQLiteDatabase openDatabase(String path, CursorFactory factory, int flags) {
+ public static SQLiteDatabase openDatabase(@NonNull String path, @Nullable CursorFactory factory,
+ @DatabaseOpenFlags int flags) {
return openDatabase(path, factory, flags, null);
}
/**
+ * Open the database according to the specified {@link OpenParams parameters}
+ *
+ * @param path to database file to open and/or create
+ * @param openParams configuration parameters that are used for opening {@link SQLiteDatabase}
+ * @return the newly opened database
+ * @throws SQLiteException if the database cannot be opened
+ */
+ public static SQLiteDatabase openDatabase(@NonNull String path,
+ @NonNull OpenParams openParams) {
+ Preconditions.checkArgument(openParams != null, "OpenParams cannot be null");
+ SQLiteDatabase db = new SQLiteDatabase(path, openParams.mOpenFlags,
+ openParams.mCursorFactory, openParams.mErrorHandler,
+ openParams.mLookasideSlotSize, openParams.mLookasideSlotCount);
+ db.open();
+ return db;
+ }
+
+ /**
* Open the database according to the flags {@link #OPEN_READWRITE}
* {@link #OPEN_READONLY} {@link #CREATE_IF_NECESSARY} and/or {@link #NO_LOCALIZED_COLLATORS}.
*
@@ -690,9 +718,9 @@
* @return the newly opened database
* @throws SQLiteException if the database cannot be opened
*/
- public static SQLiteDatabase openDatabase(String path, CursorFactory factory, int flags,
- DatabaseErrorHandler errorHandler) {
- SQLiteDatabase db = new SQLiteDatabase(path, flags, factory, errorHandler);
+ public static SQLiteDatabase openDatabase(@NonNull String path, @Nullable CursorFactory factory,
+ @DatabaseOpenFlags int flags, @Nullable DatabaseErrorHandler errorHandler) {
+ SQLiteDatabase db = new SQLiteDatabase(path, flags, factory, errorHandler, -1, -1);
db.open();
return db;
}
@@ -700,22 +728,24 @@
/**
* Equivalent to openDatabase(file.getPath(), factory, CREATE_IF_NECESSARY).
*/
- public static SQLiteDatabase openOrCreateDatabase(File file, CursorFactory factory) {
+ public static SQLiteDatabase openOrCreateDatabase(@NonNull File file,
+ @Nullable CursorFactory factory) {
return openOrCreateDatabase(file.getPath(), factory);
}
/**
* Equivalent to openDatabase(path, factory, CREATE_IF_NECESSARY).
*/
- public static SQLiteDatabase openOrCreateDatabase(String path, CursorFactory factory) {
+ public static SQLiteDatabase openOrCreateDatabase(@NonNull String path,
+ @Nullable CursorFactory factory) {
return openDatabase(path, factory, CREATE_IF_NECESSARY, null);
}
/**
* Equivalent to openDatabase(path, factory, CREATE_IF_NECESSARY, errorHandler).
*/
- public static SQLiteDatabase openOrCreateDatabase(String path, CursorFactory factory,
- DatabaseErrorHandler errorHandler) {
+ public static SQLiteDatabase openOrCreateDatabase(@NonNull String path,
+ @Nullable CursorFactory factory, @Nullable DatabaseErrorHandler errorHandler) {
return openDatabase(path, factory, CREATE_IF_NECESSARY, errorHandler);
}
@@ -726,7 +756,7 @@
* @param file The database file path.
* @return True if the database was successfully deleted.
*/
- public static boolean deleteDatabase(File file) {
+ public static boolean deleteDatabase(@NonNull File file) {
if (file == null) {
throw new IllegalArgumentException("file must not be null");
}
@@ -825,13 +855,29 @@
* cursor when query is called
* @return a SQLiteDatabase object, or null if the database can't be created
*/
- public static SQLiteDatabase create(CursorFactory factory) {
+ @NonNull
+ public static SQLiteDatabase create(@Nullable CursorFactory factory) {
// This is a magic string with special meaning for SQLite.
return openDatabase(SQLiteDatabaseConfiguration.MEMORY_DB_PATH,
factory, CREATE_IF_NECESSARY);
}
/**
+ * Create a memory backed SQLite database. Its contents will be destroyed
+ * when the database is closed.
+ *
+ * <p>Sets the locale of the database to the the system's current locale.
+ * Call {@link #setLocale} if you would like something else.</p>
+ * @param openParams configuration parameters that are used for opening SQLiteDatabase
+ * @return a SQLiteDatabase object, or null if the database can't be created
+ */
+ @NonNull
+ public static SQLiteDatabase createInMemory(@NonNull OpenParams openParams) {
+ return openDatabase(SQLiteDatabaseConfiguration.MEMORY_DB_PATH,
+ openParams.toBuilder().addOpenFlags(CREATE_IF_NECESSARY).build());
+ }
+
+ /**
* Registers a CustomFunction callback as a function that can be called from
* SQLite database triggers.
*
@@ -2210,4 +2256,238 @@
public interface CustomFunction {
public void callback(String[] args);
}
+
+ /**
+ * Wrapper for configuration parameters that are used for opening {@link SQLiteDatabase}
+ */
+ public static final class OpenParams {
+ private final int mOpenFlags;
+ private final CursorFactory mCursorFactory;
+ private final DatabaseErrorHandler mErrorHandler;
+ private final int mLookasideSlotSize;
+ private final int mLookasideSlotCount;
+
+ private OpenParams(int openFlags, CursorFactory cursorFactory,
+ DatabaseErrorHandler errorHandler, int lookasideSlotSize, int lookasideSlotCount) {
+ mOpenFlags = openFlags;
+ mCursorFactory = cursorFactory;
+ mErrorHandler = errorHandler;
+ mLookasideSlotSize = lookasideSlotSize;
+ mLookasideSlotCount = lookasideSlotCount;
+ }
+
+ /**
+ * Returns size in bytes of each lookaside slot or -1 if not set.
+ *
+ * @see Builder#setLookasideConfig(int, int)
+ */
+ @IntRange(from = -1)
+ public int getLookasideSlotSize() {
+ return mLookasideSlotSize;
+ }
+
+ /**
+ * Returns total number of lookaside memory slots per database connection or -1 if not
+ * set.
+ *
+ * @see Builder#setLookasideConfig(int, int)
+ */
+ @IntRange(from = -1)
+ public int getLookasideSlotCount() {
+ return mLookasideSlotCount;
+ }
+
+ /**
+ * Returns flags to control database access mode
+ *
+ * @see Builder#setOpenFlags(int)
+ */
+ @DatabaseOpenFlags
+ public int getOpenFlags() {
+ return mOpenFlags;
+ }
+
+ /**
+ * Returns an optional factory class that is called to instantiate a cursor when query
+ * is called
+ *
+ * @see Builder#setCursorFactory(CursorFactory)
+ */
+ @Nullable
+ public CursorFactory getCursorFactory() {
+ return mCursorFactory;
+ }
+
+ /**
+ * Returns handler for database corruption errors
+ *
+ * @see Builder#setErrorHandler(DatabaseErrorHandler)
+ */
+ @Nullable
+ public DatabaseErrorHandler getErrorHandler() {
+ return mErrorHandler;
+ }
+
+ /**
+ * Creates a new instance of builder {@link Builder#Builder(OpenParams) initialized} with
+ * {@code this} parameters.
+ * @hide
+ */
+ @NonNull
+ public Builder toBuilder() {
+ return new Builder(this);
+ }
+
+ /**
+ * Builder for {@link OpenParams}.
+ */
+ public static final class Builder {
+ private int mLookasideSlotSize = -1;
+ private int mLookasideSlotCount = -1;
+ private int mOpenFlags;
+ private CursorFactory mCursorFactory;
+ private DatabaseErrorHandler mErrorHandler;
+
+ public Builder() {
+ }
+
+ public Builder(OpenParams params) {
+ mLookasideSlotSize = params.mLookasideSlotSize;
+ mLookasideSlotCount = params.mLookasideSlotCount;
+ mOpenFlags = params.mOpenFlags;
+ mCursorFactory = params.mCursorFactory;
+ mErrorHandler = params.mErrorHandler;
+ }
+
+ /**
+ * Configures
+ * <a href="https://sqlite.org/malloc.html#lookaside">lookaside memory allocator</a>
+ *
+ * <p>SQLite default settings will be used, if this method isn't called.
+ * Use {@code setLookasideConfig(0,0)} to disable lookaside
+ *
+ * @param slotSize The size in bytes of each lookaside slot.
+ * @param slotCount The total number of lookaside memory slots per database connection.
+ */
+ public Builder setLookasideConfig(@IntRange(from = 0) final int slotSize,
+ @IntRange(from = 0) final int slotCount) {
+ Preconditions.checkArgument(slotSize >= 0,
+ "lookasideSlotCount cannot be negative");
+ Preconditions.checkArgument(slotCount >= 0,
+ "lookasideSlotSize cannot be negative");
+ Preconditions.checkArgument(
+ (slotSize > 0 && slotCount > 0) || (slotCount == 0 && slotSize == 0),
+ "Invalid configuration: " + slotSize + ", " + slotCount);
+
+ mLookasideSlotSize = slotSize;
+ mLookasideSlotCount = slotCount;
+ return this;
+ }
+
+ /**
+ * Returns true if {@link #ENABLE_WRITE_AHEAD_LOGGING} flag is set
+ * @hide
+ */
+ public boolean isWriteAheadLoggingEnabled() {
+ return (mOpenFlags & ENABLE_WRITE_AHEAD_LOGGING) != 0;
+ }
+
+ /**
+ * Sets flags to control database access mode
+ * @param openFlags The new flags to set
+ * @see #OPEN_READWRITE
+ * @see #OPEN_READONLY
+ * @see #CREATE_IF_NECESSARY
+ * @see #NO_LOCALIZED_COLLATORS
+ * @see #ENABLE_WRITE_AHEAD_LOGGING
+ * @return same builder instance for chaining multiple calls into a single statement
+ */
+ @NonNull
+ public Builder setOpenFlags(@DatabaseOpenFlags int openFlags) {
+ mOpenFlags = openFlags;
+ return this;
+ }
+
+ /**
+ * Adds flags to control database access mode
+ *
+ * @param openFlags The new flags to add
+ * @return same builder instance for chaining multiple calls into a single statement
+ */
+ @NonNull
+ public Builder addOpenFlags(@DatabaseOpenFlags int openFlags) {
+ mOpenFlags |= openFlags;
+ return this;
+ }
+
+ /**
+ * Removes database access mode flags
+ *
+ * @param openFlags Flags to remove
+ * @return same builder instance for chaining multiple calls into a single statement
+ */
+ @NonNull
+ public Builder removeOpenFlags(@DatabaseOpenFlags int openFlags) {
+ mOpenFlags &= ~openFlags;
+ return this;
+ }
+
+ /**
+ * Sets {@link #ENABLE_WRITE_AHEAD_LOGGING} flag if {@code enabled} is {@code true},
+ * unsets otherwise
+ * @hide
+ */
+ public void setWriteAheadLoggingEnabled(boolean enabled) {
+ if (enabled) {
+ addOpenFlags(ENABLE_WRITE_AHEAD_LOGGING);
+ } else {
+ removeOpenFlags(ENABLE_WRITE_AHEAD_LOGGING);
+ }
+ }
+
+ /**
+ * Set an optional factory class that is called to instantiate a cursor when query
+ * is called.
+ *
+ * @param cursorFactory instance
+ * @return same builder instance for chaining multiple calls into a single statement
+ */
+ @NonNull
+ public Builder setCursorFactory(@Nullable CursorFactory cursorFactory) {
+ mCursorFactory = cursorFactory;
+ return this;
+ }
+
+
+ /**
+ * Sets {@link DatabaseErrorHandler} object to handle db corruption errors
+ */
+ @NonNull
+ public Builder setErrorHandler(@Nullable DatabaseErrorHandler errorHandler) {
+ mErrorHandler = errorHandler;
+ return this;
+ }
+
+ /**
+ * Creates an instance of {@link OpenParams} with the options that were previously set
+ * on this builder
+ */
+ @NonNull
+ public OpenParams build() {
+ return new OpenParams(mOpenFlags, mCursorFactory, mErrorHandler, mLookasideSlotSize,
+ mLookasideSlotCount);
+ }
+ }
+ }
+
+ /** @hide */
+ @IntDef(flag = true, prefix = {"OPEN_", "CREATE_", "NO_", "ENABLE_"}, value = {
+ OPEN_READWRITE,
+ OPEN_READONLY,
+ CREATE_IF_NECESSARY,
+ NO_LOCALIZED_COLLATORS,
+ ENABLE_WRITE_AHEAD_LOGGING
+ })
+ @Retention(RetentionPolicy.SOURCE)
+ public @interface DatabaseOpenFlags {}
}
diff --git a/core/java/android/database/sqlite/SQLiteDatabaseConfiguration.java b/core/java/android/database/sqlite/SQLiteDatabaseConfiguration.java
index 549ab90..1435c83 100644
--- a/core/java/android/database/sqlite/SQLiteDatabaseConfiguration.java
+++ b/core/java/android/database/sqlite/SQLiteDatabaseConfiguration.java
@@ -90,6 +90,20 @@
new ArrayList<SQLiteCustomFunction>();
/**
+ * The size in bytes of each lookaside slot
+ *
+ * <p>If negative, the default lookaside configuration will be used
+ */
+ public int lookasideSlotSize;
+
+ /**
+ * The total number of lookaside memory slots per database connection
+ *
+ * <p>If negative, the default lookaside configuration will be used
+ */
+ public int lookasideSlotCount;
+
+ /**
* Creates a database configuration with the required parameters for opening a
* database and default values for all other parameters.
*
@@ -108,6 +122,8 @@
// Set default values for optional parameters.
maxSqlCacheSize = 25;
locale = Locale.getDefault();
+ lookasideSlotSize = -1;
+ lookasideSlotCount = -1;
}
/**
@@ -146,6 +162,8 @@
foreignKeyConstraintsEnabled = other.foreignKeyConstraintsEnabled;
customFunctions.clear();
customFunctions.addAll(other.customFunctions);
+ lookasideSlotSize = other.lookasideSlotSize;
+ lookasideSlotCount = other.lookasideSlotCount;
}
/**
diff --git a/core/java/android/database/sqlite/SQLiteOpenHelper.java b/core/java/android/database/sqlite/SQLiteOpenHelper.java
index bb8d9ff..44a72dd 100644
--- a/core/java/android/database/sqlite/SQLiteOpenHelper.java
+++ b/core/java/android/database/sqlite/SQLiteOpenHelper.java
@@ -16,10 +16,14 @@
package android.database.sqlite;
+import android.annotation.IntRange;
import android.content.Context;
import android.database.DatabaseErrorHandler;
+import android.database.SQLException;
import android.database.sqlite.SQLiteDatabase.CursorFactory;
+import android.os.FileUtils;
import android.util.Log;
+
import java.io.File;
/**
@@ -43,24 +47,14 @@
public abstract class SQLiteOpenHelper {
private static final String TAG = SQLiteOpenHelper.class.getSimpleName();
- // When true, getReadableDatabase returns a read-only database if it is just being opened.
- // The database handle is reopened in read/write mode when getWritableDatabase is called.
- // We leave this behavior disabled in production because it is inefficient and breaks
- // many applications. For debugging purposes it can be useful to turn on strict
- // read-only semantics to catch applications that call getReadableDatabase when they really
- // wanted getWritableDatabase.
- private static final boolean DEBUG_STRICT_READONLY = false;
-
private final Context mContext;
private final String mName;
- private final CursorFactory mFactory;
private final int mNewVersion;
private final int mMinimumSupportedVersion;
private SQLiteDatabase mDatabase;
private boolean mIsInitializing;
- private boolean mEnableWriteAheadLogging;
- private final DatabaseErrorHandler mErrorHandler;
+ private final SQLiteDatabase.OpenParams.Builder mOpenParamsBuilder;
/**
* Create a helper object to create, open, and/or manage a database.
@@ -130,10 +124,12 @@
mContext = context;
mName = name;
- mFactory = factory;
mNewVersion = version;
- mErrorHandler = errorHandler;
mMinimumSupportedVersion = Math.max(0, minimumSupportedVersion);
+ mOpenParamsBuilder = new SQLiteDatabase.OpenParams.Builder();
+ mOpenParamsBuilder.setCursorFactory(factory);
+ mOpenParamsBuilder.setErrorHandler(errorHandler);
+ mOpenParamsBuilder.addOpenFlags(SQLiteDatabase.CREATE_IF_NECESSARY);
}
/**
@@ -157,7 +153,7 @@
*/
public void setWriteAheadLoggingEnabled(boolean enabled) {
synchronized (this) {
- if (mEnableWriteAheadLogging != enabled) {
+ if (mOpenParamsBuilder.isWriteAheadLoggingEnabled() != enabled) {
if (mDatabase != null && mDatabase.isOpen() && !mDatabase.isReadOnly()) {
if (enabled) {
mDatabase.enableWriteAheadLogging();
@@ -165,12 +161,36 @@
mDatabase.disableWriteAheadLogging();
}
}
- mEnableWriteAheadLogging = enabled;
+ mOpenParamsBuilder.setWriteAheadLoggingEnabled(enabled);
}
}
}
/**
+ * Configures <a href="https://sqlite.org/malloc.html#lookaside">lookaside memory allocator</a>
+ *
+ * <p>This method should be called from the constructor of the subclass,
+ * before opening the database, since lookaside memory configuration can only be changed
+ * when no connection is using it
+ *
+ * <p>SQLite default settings will be used, if this method isn't called.
+ * Use {@code setLookasideConfig(0,0)} to disable lookaside
+ *
+ * @param slotSize The size in bytes of each lookaside slot.
+ * @param slotCount The total number of lookaside memory slots per database connection.
+ */
+ public void setLookasideConfig(@IntRange(from = 0) final int slotSize,
+ @IntRange(from = 0) final int slotCount) {
+ synchronized (this) {
+ if (mDatabase != null && mDatabase.isOpen()) {
+ throw new IllegalStateException(
+ "Lookaside memory config cannot be changed after opening the database");
+ }
+ mOpenParamsBuilder.setLookasideConfig(slotSize, slotCount);
+ }
+ }
+
+ /**
* Create and/or open a database that will be used for reading and writing.
* The first time this is called, the database will be opened and
* {@link #onCreate}, {@link #onUpgrade} and/or {@link #onOpen} will be
@@ -243,27 +263,22 @@
db.reopenReadWrite();
}
} else if (mName == null) {
- db = SQLiteDatabase.create(null);
+ db = SQLiteDatabase.createInMemory(mOpenParamsBuilder.build());
} else {
+ final String path = mContext.getDatabasePath(mName).getPath();
+ SQLiteDatabase.OpenParams params = mOpenParamsBuilder.build();
try {
- if (DEBUG_STRICT_READONLY && !writable) {
- final String path = mContext.getDatabasePath(mName).getPath();
- db = SQLiteDatabase.openDatabase(path, mFactory,
- SQLiteDatabase.OPEN_READONLY, mErrorHandler);
- } else {
- db = mContext.openOrCreateDatabase(mName, mEnableWriteAheadLogging ?
- Context.MODE_ENABLE_WRITE_AHEAD_LOGGING : 0,
- mFactory, mErrorHandler);
- }
- } catch (SQLiteException ex) {
+ db = SQLiteDatabase.openDatabase(path, params);
+ // Keep pre-O-MR1 behavior by resetting file permissions to 660
+ setFilePermissionsForDb(path);
+ } catch (SQLException ex) {
if (writable) {
throw ex;
}
Log.e(TAG, "Couldn't open " + mName
+ " for writing (will try read-only):", ex);
- final String path = mContext.getDatabasePath(mName).getPath();
- db = SQLiteDatabase.openDatabase(path, mFactory,
- SQLiteDatabase.OPEN_READONLY, mErrorHandler);
+ params = params.toBuilder().addOpenFlags(SQLiteDatabase.OPEN_READONLY).build();
+ db = SQLiteDatabase.openDatabase(path, params);
}
}
@@ -323,6 +338,11 @@
}
}
+ private static void setFilePermissionsForDb(String dbPath) {
+ int perms = FileUtils.S_IRUSR | FileUtils.S_IWUSR | FileUtils.S_IRGRP | FileUtils.S_IWGRP;
+ FileUtils.setPermissions(dbPath, perms, -1, -1);
+ }
+
/**
* Close any open database object.
*/
diff --git a/core/java/android/hardware/radio/RadioMetadata.java b/core/java/android/hardware/radio/RadioMetadata.java
index 07dd5db..d11e8b0 100644
--- a/core/java/android/hardware/radio/RadioMetadata.java
+++ b/core/java/android/hardware/radio/RadioMetadata.java
@@ -106,7 +106,7 @@
static {
METADATA_KEYS_TYPE = new ArrayMap<String, Integer>();
- METADATA_KEYS_TYPE.put(METADATA_KEY_RDS_PI, METADATA_TYPE_TEXT);
+ METADATA_KEYS_TYPE.put(METADATA_KEY_RDS_PI, METADATA_TYPE_INT);
METADATA_KEYS_TYPE.put(METADATA_KEY_RDS_PS, METADATA_TYPE_TEXT);
METADATA_KEYS_TYPE.put(METADATA_KEY_RDS_PTY, METADATA_TYPE_INT);
METADATA_KEYS_TYPE.put(METADATA_KEY_RBDS_PTY, METADATA_TYPE_INT);
@@ -385,7 +385,6 @@
* the METADATA_KEYs defined in this class are used they may only be one
* of the following:
* <ul>
- * <li>{@link #METADATA_KEY_RDS_PI}</li>
* <li>{@link #METADATA_KEY_RDS_PS}</li>
* <li>{@link #METADATA_KEY_RDS_RT}</li>
* <li>{@link #METADATA_KEY_TITLE}</li>
@@ -413,6 +412,7 @@
* the METADATA_KEYs defined in this class are used they may only be one
* of the following:
* <ul>
+ * <li>{@link #METADATA_KEY_RDS_PI}</li>
* <li>{@link #METADATA_KEY_RDS_PTY}</li>
* <li>{@link #METADATA_KEY_RBDS_PTY}</li>
* </ul>
diff --git a/core/java/android/net/ConnectivityManager.java b/core/java/android/net/ConnectivityManager.java
index 5e9b02a..2979cd8 100644
--- a/core/java/android/net/ConnectivityManager.java
+++ b/core/java/android/net/ConnectivityManager.java
@@ -582,6 +582,8 @@
/** {@hide} */
public static final int MAX_NETWORK_TYPE = TYPE_VPN;
+ private static final int MIN_NETWORK_TYPE = TYPE_MOBILE;
+
/**
* If you want to set the default network preference,you can directly
* change the networkAttributes array in framework's config.xml.
@@ -640,7 +642,7 @@
*/
@Deprecated
public static boolean isNetworkTypeValid(int networkType) {
- return networkType >= 0 && networkType <= MAX_NETWORK_TYPE;
+ return MIN_NETWORK_TYPE <= networkType && networkType <= MAX_NETWORK_TYPE;
}
/**
@@ -653,6 +655,8 @@
*/
public static String getNetworkTypeName(int type) {
switch (type) {
+ case TYPE_NONE:
+ return "NONE";
case TYPE_MOBILE:
return "MOBILE";
case TYPE_WIFI:
diff --git a/core/java/android/net/NetworkCapabilities.java b/core/java/android/net/NetworkCapabilities.java
index 2dd7f75..76646b8 100644
--- a/core/java/android/net/NetworkCapabilities.java
+++ b/core/java/android/net/NetworkCapabilities.java
@@ -21,6 +21,7 @@
import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.util.BitUtils;
+import com.android.internal.util.Preconditions;
import java.util.Objects;
@@ -429,6 +430,11 @@
/** @hide */
public static final int MAX_TRANSPORT = TRANSPORT_LOWPAN;
+ /** @hide */
+ public static boolean isValidTransport(int transportType) {
+ return (MIN_TRANSPORT <= transportType) && (transportType <= MAX_TRANSPORT);
+ }
+
private static final String[] TRANSPORT_NAMES = {
"CELLULAR",
"WIFI",
@@ -453,9 +459,7 @@
* @hide
*/
public NetworkCapabilities addTransportType(int transportType) {
- if (transportType < MIN_TRANSPORT || transportType > MAX_TRANSPORT) {
- throw new IllegalArgumentException("TransportType out of range");
- }
+ checkValidTransportType(transportType);
mTransportTypes |= 1 << transportType;
setNetworkSpecifier(mNetworkSpecifier); // used for exception checking
return this;
@@ -469,9 +473,7 @@
* @hide
*/
public NetworkCapabilities removeTransportType(int transportType) {
- if (transportType < MIN_TRANSPORT || transportType > MAX_TRANSPORT) {
- throw new IllegalArgumentException("TransportType out of range");
- }
+ checkValidTransportType(transportType);
mTransportTypes &= ~(1 << transportType);
setNetworkSpecifier(mNetworkSpecifier); // used for exception checking
return this;
@@ -495,10 +497,7 @@
* @return {@code true} if set on this instance.
*/
public boolean hasTransport(int transportType) {
- if (transportType < MIN_TRANSPORT || transportType > MAX_TRANSPORT) {
- return false;
- }
- return ((mTransportTypes & (1 << transportType)) != 0);
+ return isValidTransport(transportType) && ((mTransportTypes & (1 << transportType)) != 0);
}
private void combineTransportTypes(NetworkCapabilities nc) {
@@ -906,9 +905,14 @@
* @hide
*/
public static String transportNameOf(int transport) {
- if (transport < 0 || TRANSPORT_NAMES.length <= transport) {
+ if (!isValidTransport(transport)) {
return "UNKNOWN";
}
return TRANSPORT_NAMES[transport];
}
+
+ private static void checkValidTransportType(int transport) {
+ Preconditions.checkArgument(
+ isValidTransport(transport), "Invalid TransportType " + transport);
+ }
}
diff --git a/core/java/android/net/NetworkInfo.java b/core/java/android/net/NetworkInfo.java
index 42f5feb..84c32be 100644
--- a/core/java/android/net/NetworkInfo.java
+++ b/core/java/android/net/NetworkInfo.java
@@ -127,7 +127,8 @@
* @hide
*/
public NetworkInfo(int type, int subtype, String typeName, String subtypeName) {
- if (!ConnectivityManager.isNetworkTypeValid(type)) {
+ if (!ConnectivityManager.isNetworkTypeValid(type)
+ && type != ConnectivityManager.TYPE_NONE) {
throw new IllegalArgumentException("Invalid network type: " + type);
}
mNetworkType = type;
diff --git a/core/java/android/os/BaseBundle.java b/core/java/android/os/BaseBundle.java
index 8d85880..a5763ef 100644
--- a/core/java/android/os/BaseBundle.java
+++ b/core/java/android/os/BaseBundle.java
@@ -21,6 +21,9 @@
import android.util.Log;
import android.util.MathUtils;
import android.util.Slog;
+import android.util.SparseArray;
+
+import com.android.internal.util.IndentingPrintWriter;
import java.io.Serializable;
import java.util.ArrayList;
@@ -1555,4 +1558,49 @@
mParcelledData = p;
}
+
+ /** {@hide} */
+ public static void dumpStats(IndentingPrintWriter pw, String key, Object value) {
+ final Parcel tmp = Parcel.obtain();
+ tmp.writeValue(value);
+ final int size = tmp.dataPosition();
+ tmp.recycle();
+
+ // We only really care about logging large values
+ if (size > 1024) {
+ pw.println(key + " [size=" + size + "]");
+ if (value instanceof BaseBundle) {
+ dumpStats(pw, (BaseBundle) value);
+ } else if (value instanceof SparseArray) {
+ dumpStats(pw, (SparseArray) value);
+ }
+ }
+ }
+
+ /** {@hide} */
+ public static void dumpStats(IndentingPrintWriter pw, SparseArray array) {
+ pw.increaseIndent();
+ if (array == null) {
+ pw.println("[null]");
+ return;
+ }
+ for (int i = 0; i < array.size(); i++) {
+ dumpStats(pw, "0x" + Integer.toHexString(array.keyAt(i)), array.valueAt(i));
+ }
+ pw.decreaseIndent();
+ }
+
+ /** {@hide} */
+ public static void dumpStats(IndentingPrintWriter pw, BaseBundle bundle) {
+ pw.increaseIndent();
+ if (bundle == null) {
+ pw.println("[null]");
+ return;
+ }
+ final ArrayMap<String, Object> map = bundle.getMap();
+ for (int i = 0; i < map.size(); i++) {
+ dumpStats(pw, map.keyAt(i), map.valueAt(i));
+ }
+ pw.decreaseIndent();
+ }
}
diff --git a/core/java/android/os/BatteryStats.java b/core/java/android/os/BatteryStats.java
index cf4fd99..a34668c 100644
--- a/core/java/android/os/BatteryStats.java
+++ b/core/java/android/os/BatteryStats.java
@@ -25,6 +25,7 @@
import java.util.List;
import java.util.Map;
+import android.app.job.JobParameters;
import android.content.Context;
import android.content.pm.ApplicationInfo;
import android.telephony.SignalStrength;
@@ -238,6 +239,7 @@
private static final String AGGREGATED_WAKELOCK_DATA = "awl";
private static final String SYNC_DATA = "sy";
private static final String JOB_DATA = "jb";
+ private static final String JOB_COMPLETION_DATA = "jbc";
private static final String KERNEL_WAKELOCK_DATA = "kwl";
private static final String WAKEUP_REASON_DATA = "wr";
private static final String NETWORK_DATA = "nt";
@@ -498,6 +500,13 @@
public abstract ArrayMap<String, ? extends Timer> getJobStats();
/**
+ * Returns statistics about how jobs have completed.
+ *
+ * @return A Map of String job names to completion type -> count mapping.
+ */
+ public abstract ArrayMap<String, SparseIntArray> getJobCompletionStats();
+
+ /**
* The statistics associated with a particular wake lock.
*/
public static abstract class Wakelock {
@@ -3557,6 +3566,20 @@
}
}
+ final ArrayMap<String, SparseIntArray> completions = u.getJobCompletionStats();
+ for (int ic=completions.size()-1; ic>=0; ic--) {
+ SparseIntArray types = completions.valueAt(ic);
+ if (types != null) {
+ dumpLine(pw, uid, category, JOB_COMPLETION_DATA,
+ "\"" + completions.keyAt(ic) + "\"",
+ types.get(JobParameters.REASON_CANCELED, 0),
+ types.get(JobParameters.REASON_CONSTRAINTS_NOT_SATISFIED, 0),
+ types.get(JobParameters.REASON_PREEMPT, 0),
+ types.get(JobParameters.REASON_TIMEOUT, 0),
+ types.get(JobParameters.REASON_DEVICE_IDLE, 0));
+ }
+ }
+
dumpTimer(pw, uid, category, FLASHLIGHT_DATA, u.getFlashlightTurnedOnTimer(),
rawRealtime, which);
dumpTimer(pw, uid, category, CAMERA_DATA, u.getCameraTurnedOnTimer(),
@@ -4979,6 +5002,25 @@
uidActivity = true;
}
+ final ArrayMap<String, SparseIntArray> completions = u.getJobCompletionStats();
+ for (int ic=completions.size()-1; ic>=0; ic--) {
+ SparseIntArray types = completions.valueAt(ic);
+ if (types != null) {
+ pw.print(prefix);
+ pw.print(" Job Completions ");
+ pw.print(completions.keyAt(ic));
+ pw.print(":");
+ for (int it=0; it<types.size(); it++) {
+ pw.print(" ");
+ pw.print(JobParameters.getReasonName(types.keyAt(it)));
+ pw.print("(");
+ pw.print(types.valueAt(it));
+ pw.print("x)");
+ }
+ pw.println();
+ }
+ }
+
uidActivity |= printTimer(pw, sb, u.getFlashlightTurnedOnTimer(), rawRealtime, which,
prefix, "Flashlight");
uidActivity |= printTimer(pw, sb, u.getCameraTurnedOnTimer(), rawRealtime, which,
diff --git a/core/java/android/os/PowerManager.java b/core/java/android/os/PowerManager.java
index 1c676b3..3f5b611 100644
--- a/core/java/android/os/PowerManager.java
+++ b/core/java/android/os/PowerManager.java
@@ -266,7 +266,13 @@
* {@link #PROXIMITY_SCREEN_OFF_WAKE_LOCK} wake lock until the proximity sensor
* indicates that an object is not in close proximity.
*/
- public static final int RELEASE_FLAG_WAIT_FOR_NO_PROXIMITY = 1;
+ public static final int RELEASE_FLAG_WAIT_FOR_NO_PROXIMITY = 1 << 0;
+
+ /**
+ * Flag for {@link WakeLock#release(int)} when called due to timeout.
+ * @hide
+ */
+ public static final int RELEASE_FLAG_TIMEOUT = 1 << 16;
/**
* Brightness value for fully on.
@@ -1242,7 +1248,8 @@
private String mTag;
private final String mPackageName;
private final IBinder mToken;
- private int mCount;
+ private int mInternalCount;
+ private int mExternalCount;
private boolean mRefCounted = true;
private boolean mHeld;
private WorkSource mWorkSource;
@@ -1251,7 +1258,7 @@
private final Runnable mReleaser = new Runnable() {
public void run() {
- release();
+ release(RELEASE_FLAG_TIMEOUT);
}
};
@@ -1328,7 +1335,9 @@
}
private void acquireLocked() {
- if (!mRefCounted || mCount++ == 0) {
+ mInternalCount++;
+ mExternalCount++;
+ if (!mRefCounted || mInternalCount == 1) {
// Do this even if the wake lock is already thought to be held (mHeld == true)
// because non-reference counted wake locks are not always properly released.
// For example, the keyguard's wake lock might be forcibly released by the
@@ -1373,7 +1382,11 @@
*/
public void release(int flags) {
synchronized (mToken) {
- if (!mRefCounted || --mCount == 0) {
+ mInternalCount--;
+ if ((flags & RELEASE_FLAG_TIMEOUT) == 0) {
+ mExternalCount--;
+ }
+ if (!mRefCounted || mInternalCount == 0) {
mHandler.removeCallbacks(mReleaser);
if (mHeld) {
Trace.asyncTraceEnd(Trace.TRACE_TAG_POWER, mTraceName, 0);
@@ -1385,7 +1398,7 @@
mHeld = false;
}
}
- if (mCount < 0) {
+ if (mRefCounted && mExternalCount < 0) {
throw new RuntimeException("WakeLock under-locked " + mTag);
}
}
@@ -1469,7 +1482,7 @@
synchronized (mToken) {
return "WakeLock{"
+ Integer.toHexString(System.identityHashCode(this))
- + " held=" + mHeld + ", refCount=" + mCount + "}";
+ + " held=" + mHeld + ", refCount=" + mInternalCount + "}";
}
}
diff --git a/core/java/android/os/ZygoteProcess.java b/core/java/android/os/ZygoteProcess.java
index 0d81bd9..7a13ee8 100644
--- a/core/java/android/os/ZygoteProcess.java
+++ b/core/java/android/os/ZygoteProcess.java
@@ -488,8 +488,8 @@
* Instructs the zygote to pre-load the classes and native libraries at the given paths
* for the specified abi. Not all zygotes support this function.
*/
- public void preloadPackageForAbi(String packagePath, String libsPath, String cacheKey,
- String abi) throws ZygoteStartFailedEx, IOException {
+ public boolean preloadPackageForAbi(String packagePath, String libsPath, String cacheKey,
+ String abi) throws ZygoteStartFailedEx, IOException {
synchronized(mLock) {
ZygoteState state = openZygoteSocketIfNeeded(abi);
state.writer.write("4");
@@ -508,6 +508,8 @@
state.writer.newLine();
state.writer.flush();
+
+ return (state.inputStream.readInt() == 0);
}
}
diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java
index bc0534a..b710cf1 100755
--- a/core/java/android/provider/Settings.java
+++ b/core/java/android/provider/Settings.java
@@ -195,6 +195,24 @@
"android.settings.AIRPLANE_MODE_SETTINGS";
/**
+ * Activity Action: Show mobile data usage list.
+ * <p>
+ * Input: {@link EXTRA_NETWORK_TEMPLATE} and {@link EXTRA_SUB_ID} should be included to specify
+ * how and what mobile data statistics should be collected.
+ * <p>
+ * Output: Nothing
+ * @hide
+ */
+ @SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION)
+ public static final String ACTION_MOBILE_DATA_USAGE =
+ "android.settings.MOBILE_DATA_USAGE";
+
+ /** @hide */
+ public static final String EXTRA_NETWORK_TEMPLATE = "network_template";
+ /** @hide */
+ public static final String EXTRA_SUB_ID = "sub_id";
+
+ /**
* Activity Action: Modify Airplane mode settings using a voice command.
* <p>
* In some cases, a matching Activity may not exist, so ensure you safeguard against this.
@@ -7060,6 +7078,12 @@
public static final String NOTIFICATION_BADGING = "notification_badging";
/**
+ * Comma separated list of QS tiles that have been auto-added already.
+ * @hide
+ */
+ public static final String QS_AUTO_ADDED_TILES = "qs_auto_tiles";
+
+ /**
* This are the settings to be backed up.
*
* NOTE: Settings are backed up and restored in the order they appear
@@ -7155,7 +7179,8 @@
ASSIST_GESTURE_SILENCE_ALERTS_ENABLED,
ASSIST_GESTURE_WAKE_ENABLED,
VR_DISPLAY_MODE,
- NOTIFICATION_BADGING
+ NOTIFICATION_BADGING,
+ QS_AUTO_ADDED_TILES,
};
/** @hide */
diff --git a/core/java/android/service/persistentdata/PersistentDataBlockManager.java b/core/java/android/service/persistentdata/PersistentDataBlockManager.java
index fa75ad3..9332a5b 100644
--- a/core/java/android/service/persistentdata/PersistentDataBlockManager.java
+++ b/core/java/android/service/persistentdata/PersistentDataBlockManager.java
@@ -130,6 +130,7 @@
*
* Returns -1 on error.
*/
+ @SuppressLint("Doclava125")
public long getMaximumDataBlockSize() {
try {
return sService.getMaximumDataBlockSize();
diff --git a/core/java/android/util/MergedConfiguration.java b/core/java/android/util/MergedConfiguration.java
index 68d0309..ae66050 100644
--- a/core/java/android/util/MergedConfiguration.java
+++ b/core/java/android/util/MergedConfiguration.java
@@ -161,6 +161,21 @@
return "{mGlobalConfig=" + mGlobalConfig + " mOverrideConfig=" + mOverrideConfig + "}";
}
+ @Override
+ public int hashCode() {
+ return mMergedConfig.hashCode();
+ }
+
+ @Override
+ public boolean equals(Object that) {
+ if (!(that instanceof MergedConfiguration)) {
+ return false;
+ }
+
+ if (that == this) return true;
+ return mMergedConfig.equals(((MergedConfiguration) that).mMergedConfig);
+ }
+
public void dump(PrintWriter pw, String prefix) {
pw.println(prefix + "mGlobalConfig=" + mGlobalConfig);
pw.println(prefix + "mOverrideConfig=" + mOverrideConfig);
diff --git a/core/java/android/util/SparseLongArray.java b/core/java/android/util/SparseLongArray.java
index 0166c4a..81db2b7 100644
--- a/core/java/android/util/SparseLongArray.java
+++ b/core/java/android/util/SparseLongArray.java
@@ -119,6 +119,23 @@
}
/**
+ * @hide
+ * Remove a range of mappings as a batch.
+ *
+ * @param index Index to begin at
+ * @param size Number of mappings to remove
+ *
+ * <p>For indices outside of the range <code>0...size()-1</code>,
+ * the behavior is undefined.</p>
+ */
+ public void removeAtRange(int index, int size) {
+ size = Math.min(size, mSize - index);
+ System.arraycopy(mKeys, index + size, mKeys, index, mSize - (index + size));
+ System.arraycopy(mValues, index + size, mValues, index, mSize - (index + size));
+ mSize -= size;
+ }
+
+ /**
* Removes the mapping at the given index.
*/
public void removeAt(int index) {
diff --git a/core/java/android/view/Display.java b/core/java/android/view/Display.java
index cdb9b82..7346a21 100644
--- a/core/java/android/view/Display.java
+++ b/core/java/android/view/Display.java
@@ -726,6 +726,17 @@
}
/**
+ * Returns the rotation associated with this display as used during layout. This is currently
+ * derived from the {@link Configuration}.
+ *
+ * @hide
+ */
+ @Surface.Rotation
+ public int getLayoutRotation() {
+ return mResources.getConfiguration().getRotation();
+ }
+
+ /**
* @deprecated use {@link #getRotation}
* @return orientation of this display.
*/
diff --git a/core/java/android/view/HapticFeedbackConstants.java b/core/java/android/view/HapticFeedbackConstants.java
index 0a73949..71a3f7e 100644
--- a/core/java/android/view/HapticFeedbackConstants.java
+++ b/core/java/android/view/HapticFeedbackConstants.java
@@ -58,6 +58,7 @@
/**
* The user has released a virtual or software keyboard key.
+ * @hide
*/
public static final int VIRTUAL_KEY_RELEASE = 7;
diff --git a/core/java/android/view/Surface.java b/core/java/android/view/Surface.java
index 4f9dbd5..1b70232 100644
--- a/core/java/android/view/Surface.java
+++ b/core/java/android/view/Surface.java
@@ -131,11 +131,17 @@
public static final int SCALING_MODE_NO_SCALE_CROP = 3;
/** @hide */
- @IntDef({ROTATION_0, ROTATION_90, ROTATION_180, ROTATION_270})
+ @IntDef({ROTATION_UNDEFINED, ROTATION_0, ROTATION_90, ROTATION_180, ROTATION_270})
@Retention(RetentionPolicy.SOURCE)
public @interface Rotation {}
/**
+ * Rotation constant: undefined
+ * @hide
+ */
+ public static final int ROTATION_UNDEFINED = -1;
+
+ /**
* Rotation constant: 0 degree rotation (natural orientation)
*/
public static final int ROTATION_0 = 0;
diff --git a/core/java/android/view/ViewRootImpl.java b/core/java/android/view/ViewRootImpl.java
index e27eab9..e38a55f 100644
--- a/core/java/android/view/ViewRootImpl.java
+++ b/core/java/android/view/ViewRootImpl.java
@@ -1904,14 +1904,16 @@
+ " outsets=" + mPendingOutsets.toShortString()
+ " surface=" + mSurface);
- final Configuration pendingMergedConfig =
- mPendingMergedConfiguration.getMergedConfiguration();
- if (pendingMergedConfig.seq != 0) {
+ // If the pending {@link MergedConfiguration} handed back from
+ // {@link #relayoutWindow} does not match the one last reported,
+ // WindowManagerService has reported back a frame from a configuration not yet
+ // handled by the client. In this case, we need to accept the configuration so we
+ // do not lay out and draw with the wrong configuration.
+ if (!mPendingMergedConfiguration.equals(mLastReportedMergedConfiguration)) {
if (DEBUG_CONFIGURATION) Log.v(mTag, "Visible with new config: "
- + pendingMergedConfig);
+ + mPendingMergedConfiguration.getMergedConfiguration());
performConfigurationChange(mPendingMergedConfiguration, !mFirst,
INVALID_DISPLAY /* same display */);
- pendingMergedConfig.seq = 0;
updatedConfiguration = true;
}
@@ -3596,6 +3598,13 @@
mView.setLayoutDirection(currentLayoutDirection);
}
mView.dispatchConfigurationChanged(config);
+
+ // We could have gotten this {@link Configuration} update after we called
+ // {@link #performTraversals} with an older {@link Configuration}. As a result, our
+ // window frame may be stale. We must ensure the next pass of {@link #performTraversals}
+ // catches this.
+ mForceNextWindowRelayout = true;
+ requestLayout();
}
}
@@ -3757,10 +3766,10 @@
SomeArgs args = (SomeArgs) msg.obj;
final int displayId = args.argi3;
- final MergedConfiguration mergedConfiguration = (MergedConfiguration) args.arg4;
+ MergedConfiguration mergedConfiguration = (MergedConfiguration) args.arg4;
final boolean displayChanged = mDisplay.getDisplayId() != displayId;
- if (mergedConfiguration != null) {
+ if (!mLastReportedMergedConfiguration.equals(mergedConfiguration)) {
// If configuration changed - notify about that and, maybe, about move to
// display.
performConfigurationChange(mergedConfiguration, false /* force */,
@@ -6094,7 +6103,7 @@
if (params != null) {
if (DBG) Log.d(mTag, "WindowLayout in layoutWindow:" + params);
}
- mPendingMergedConfiguration.getMergedConfiguration().seq = 0;
+
//Log.d(mTag, ">>>>>> CALLING relayout");
if (params != null && mOrigWindowType != params.type) {
// For compatibility with old apps, don't crash here.
diff --git a/core/java/android/view/WindowManager.java b/core/java/android/view/WindowManager.java
index 3fd4599..050aa4d 100644
--- a/core/java/android/view/WindowManager.java
+++ b/core/java/android/view/WindowManager.java
@@ -1403,15 +1403,14 @@
public static final int PRIVATE_FLAG_SUSTAINED_PERFORMANCE_MODE = 0x00040000;
/**
- * Flag to indicate that this window is used as a task snapshot window. A task snapshot
- * window is a starting window that gets shown with a screenshot from the previous state
- * that is active until the app has drawn its first frame.
- *
- * <p>If this flag is set, SystemUI flags are ignored such that the real window behind can
- * set the SystemUI flags.
+ * Flag to indicate that any window added by an application process that is of type
+ * {@link #TYPE_TOAST} or that requires
+ * {@link android.app.AppOpsManager#OP_SYSTEM_ALERT_WINDOW} permission should be hidden when
+ * this window is visible.
* @hide
*/
- public static final int PRIVATE_FLAG_TASK_SNAPSHOT = 0x00080000;
+ @RequiresPermission(android.Manifest.permission.HIDE_NON_SYSTEM_OVERLAY_WINDOWS)
+ public static final int PRIVATE_FLAG_HIDE_NON_SYSTEM_OVERLAY_WINDOWS = 0x00080000;
/**
* Flag to indicate that this window should be ignored when determining what parts of the
diff --git a/core/java/android/view/textservice/TextServicesManager.java b/core/java/android/view/textservice/TextServicesManager.java
index d9bfade..f368c74 100644
--- a/core/java/android/view/textservice/TextServicesManager.java
+++ b/core/java/android/view/textservice/TextServicesManager.java
@@ -213,20 +213,6 @@
/**
* @hide
*/
- public void setCurrentSpellChecker(SpellCheckerInfo sci) {
- try {
- if (sci == null) {
- throw new NullPointerException("SpellCheckerInfo is null.");
- }
- mService.setCurrentSpellChecker(null, sci.getId());
- } catch (RemoteException e) {
- throw e.rethrowFromSystemServer();
- }
- }
-
- /**
- * @hide
- */
public SpellCheckerSubtype getCurrentSpellCheckerSubtype(
boolean allowImplicitlySelectedSubtype) {
try {
@@ -240,34 +226,6 @@
/**
* @hide
*/
- public void setSpellCheckerSubtype(SpellCheckerSubtype subtype) {
- try {
- final int hashCode;
- if (subtype == null) {
- hashCode = 0;
- } else {
- hashCode = subtype.hashCode();
- }
- mService.setCurrentSpellCheckerSubtype(null, hashCode);
- } catch (RemoteException e) {
- throw e.rethrowFromSystemServer();
- }
- }
-
- /**
- * @hide
- */
- public void setSpellCheckerEnabled(boolean enabled) {
- try {
- mService.setSpellCheckerEnabled(enabled);
- } catch (RemoteException e) {
- throw e.rethrowFromSystemServer();
- }
- }
-
- /**
- * @hide
- */
public boolean isSpellCheckerEnabled() {
try {
return mService.isSpellCheckerEnabled();
diff --git a/core/java/android/widget/Editor.java b/core/java/android/widget/Editor.java
index 1f2e3d0..f21545f 100644
--- a/core/java/android/widget/Editor.java
+++ b/core/java/android/widget/Editor.java
@@ -3914,25 +3914,30 @@
menu.removeItem(TextView.ID_ASSIST);
final TextClassification textClassification =
getSelectionActionModeHelper().getTextClassification();
- if (textClassification != null) {
- final Drawable icon = textClassification.getIcon();
- final CharSequence label = textClassification.getLabel();
- final OnClickListener onClickListener =
- textClassification.getOnClickListener();
- final Intent intent = textClassification.getIntent();
- if ((icon != null || !TextUtils.isEmpty(label))
- && (onClickListener != null || intent != null)) {
- menu.add(TextView.ID_ASSIST, TextView.ID_ASSIST, MENU_ITEM_ORDER_ASSIST, label)
- .setIcon(icon)
- .setShowAsAction(MenuItem.SHOW_AS_ACTION_ALWAYS);
- mMetricsLogger.write(
- new LogMaker(MetricsEvent.TEXT_SELECTION_MENU_ITEM_ASSIST)
- .setType(MetricsEvent.TYPE_OPEN)
- .setSubtype(textClassification.getLogType()));
- }
+ if (canAssist()) {
+ menu.add(TextView.ID_ASSIST, TextView.ID_ASSIST, MENU_ITEM_ORDER_ASSIST,
+ textClassification.getLabel())
+ .setIcon(textClassification.getIcon())
+ .setShowAsAction(MenuItem.SHOW_AS_ACTION_ALWAYS);
+ mMetricsLogger.write(
+ new LogMaker(MetricsEvent.TEXT_SELECTION_MENU_ITEM_ASSIST)
+ .setType(MetricsEvent.TYPE_OPEN)
+ .setSubtype(textClassification.getLogType()));
}
}
+ private boolean canAssist() {
+ final TextClassification textClassification =
+ getSelectionActionModeHelper().getTextClassification();
+ return mTextView.isDeviceProvisioned()
+ && textClassification != null
+ && (textClassification.getIcon() != null
+ || !TextUtils.isEmpty(textClassification.getLabel()))
+ && (textClassification.getOnClickListener() != null
+ || (textClassification.getIntent() != null
+ && mTextView.getContext().canStartActivityForResult()));
+ }
+
@Override
public boolean onActionItemClicked(ActionMode mode, MenuItem item) {
getSelectionActionModeHelper().onSelectionAction();
diff --git a/core/java/android/widget/RelativeLayout.java b/core/java/android/widget/RelativeLayout.java
index 181ad31..33e6521 100644
--- a/core/java/android/widget/RelativeLayout.java
+++ b/core/java/android/widget/RelativeLayout.java
@@ -833,25 +833,28 @@
if (!wrapContent) {
centerHorizontal(child, params, myWidth);
} else {
- params.mLeft = mPaddingLeft + params.leftMargin;
- params.mRight = params.mLeft + child.getMeasuredWidth();
+ positionAtEdge(child, params, myWidth);
}
return true;
} else {
// This is the default case. For RTL we start from the right and for LTR we start
// from the left. This will give LEFT/TOP for LTR and RIGHT/TOP for RTL.
- if (isLayoutRtl()) {
- params.mRight = myWidth - mPaddingRight- params.rightMargin;
- params.mLeft = params.mRight - child.getMeasuredWidth();
- } else {
- params.mLeft = mPaddingLeft + params.leftMargin;
- params.mRight = params.mLeft + child.getMeasuredWidth();
- }
+ positionAtEdge(child, params, myWidth);
}
}
return rules[ALIGN_PARENT_END] != 0;
}
+ private void positionAtEdge(View child, LayoutParams params, int myWidth) {
+ if (isLayoutRtl()) {
+ params.mRight = myWidth - mPaddingRight - params.rightMargin;
+ params.mLeft = params.mRight - child.getMeasuredWidth();
+ } else {
+ params.mLeft = mPaddingLeft + params.leftMargin;
+ params.mRight = params.mLeft + child.getMeasuredWidth();
+ }
+ }
+
private boolean positionChildVertical(View child, LayoutParams params, int myHeight,
boolean wrapContent) {
diff --git a/core/java/com/android/internal/app/ChooserActivity.java b/core/java/com/android/internal/app/ChooserActivity.java
index ece4981..54afc95 100644
--- a/core/java/com/android/internal/app/ChooserActivity.java
+++ b/core/java/com/android/internal/app/ChooserActivity.java
@@ -69,7 +69,10 @@
import android.view.animation.Interpolator;
import android.widget.AbsListView;
import android.widget.BaseAdapter;
+import android.widget.LinearLayout;
import android.widget.ListView;
+import android.widget.Space;
+
import com.android.internal.R;
import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.app.ResolverActivity.TargetInfo;
@@ -1412,6 +1415,10 @@
} else {
lp.height = v.getMeasuredHeight();
}
+ if (i != (mColumnCount - 1)) {
+ row.addView(new Space(ChooserActivity.this),
+ new LinearLayout.LayoutParams(0, 0, 1));
+ }
}
// Pre-measure so we can scale later.
@@ -1439,13 +1446,34 @@
if (startType == ChooserListAdapter.TARGET_SERVICE) {
holder.row.setBackgroundColor(
getColor(R.color.chooser_service_row_background_color));
+ int nextStartType = mChooserListAdapter.getPositionTargetType(
+ getFirstRowPosition(rowPosition + 1));
+ int serviceSpacing = holder.row.getContext().getResources()
+ .getDimensionPixelSize(R.dimen.chooser_service_spacing);
+ int top = rowPosition == 0 ? serviceSpacing : 0;
+ if (nextStartType != ChooserListAdapter.TARGET_SERVICE) {
+ setVertPadding(holder, top, serviceSpacing);
+ } else {
+ setVertPadding(holder, top, 0);
+ }
} else {
holder.row.setBackgroundColor(Color.TRANSPARENT);
+ int lastStartType = mChooserListAdapter.getPositionTargetType(
+ getFirstRowPosition(rowPosition - 1));
+ if (lastStartType == ChooserListAdapter.TARGET_SERVICE || rowPosition == 0) {
+ int serviceSpacing = holder.row.getContext().getResources()
+ .getDimensionPixelSize(R.dimen.chooser_service_spacing);
+ setVertPadding(holder, serviceSpacing, 0);
+ } else {
+ setVertPadding(holder, 0, 0);
+ }
}
final int oldHeight = holder.row.getLayoutParams().height;
+ int measuredRowHeight = holder.measuredRowHeight + holder.row.getPaddingTop()
+ + holder.row.getPaddingBottom();
holder.row.getLayoutParams().height = Math.max(1,
- (int) (holder.measuredRowHeight * getRowScale(rowPosition)));
+ (int) (measuredRowHeight * getRowScale(rowPosition)));
if (holder.row.getLayoutParams().height != oldHeight) {
holder.row.requestLayout();
}
@@ -1457,11 +1485,16 @@
holder.itemIndices[i] = start + i;
mChooserListAdapter.bindView(holder.itemIndices[i], v);
} else {
- v.setVisibility(View.GONE);
+ v.setVisibility(View.INVISIBLE);
}
}
}
+ private void setVertPadding(RowViewHolder holder, int top, int bottom) {
+ holder.row.setPadding(holder.row.getPaddingLeft(), top,
+ holder.row.getPaddingRight(), bottom);
+ }
+
int getFirstRowPosition(int row) {
final int callerCount = mChooserListAdapter.getCallerTargetCount();
final int callerRows = (int) Math.ceil((float) callerCount / mColumnCount);
diff --git a/core/java/com/android/internal/app/IBatteryStats.aidl b/core/java/com/android/internal/app/IBatteryStats.aidl
index 04f7c76..09ad266 100644
--- a/core/java/com/android/internal/app/IBatteryStats.aidl
+++ b/core/java/com/android/internal/app/IBatteryStats.aidl
@@ -66,7 +66,7 @@
void noteSyncStart(String name, int uid);
void noteSyncFinish(String name, int uid);
void noteJobStart(String name, int uid);
- void noteJobFinish(String name, int uid);
+ void noteJobFinish(String name, int uid, int stopReason);
void noteStartWakelock(int uid, int pid, String name, String historyName,
int type, boolean unimportantForLogging);
diff --git a/core/java/com/android/internal/app/ResolverActivity.java b/core/java/com/android/internal/app/ResolverActivity.java
index 9c6f1d0..5c1bafd 100644
--- a/core/java/com/android/internal/app/ResolverActivity.java
+++ b/core/java/com/android/internal/app/ResolverActivity.java
@@ -1681,7 +1681,14 @@
// We assume that at this point we've already filtered out the only intent for a different
// targetUserId which we're going to use.
private void addResolveInfo(DisplayResolveInfo dri) {
- if (dri.mResolveInfo.targetUserId == UserHandle.USER_CURRENT) {
+ if (dri != null && dri.mResolveInfo != null
+ && dri.mResolveInfo.targetUserId == UserHandle.USER_CURRENT) {
+ // Checks if this info is already listed in display.
+ for (DisplayResolveInfo existingInfo : mDisplayList) {
+ if (resolveInfoMatch(dri.mResolveInfo, existingInfo.mResolveInfo)) {
+ return;
+ }
+ }
mDisplayList.add(dri);
}
}
diff --git a/core/java/com/android/internal/app/ResolverComparator.java b/core/java/com/android/internal/app/ResolverComparator.java
index 54b9cd8..a0f58a9 100644
--- a/core/java/com/android/internal/app/ResolverComparator.java
+++ b/core/java/com/android/internal/app/ResolverComparator.java
@@ -553,7 +553,9 @@
Log.e(TAG, "Error in Predict: " + e);
}
}
- mAfterCompute.afterCompute();
+ if (mAfterCompute != null) {
+ mAfterCompute.afterCompute();
+ }
}
// adds select prob as the default values, according to a pre-trained Logistic Regression model.
diff --git a/core/java/com/android/internal/app/ResolverListController.java b/core/java/com/android/internal/app/ResolverListController.java
index 5ab17e44..2ab2d20 100644
--- a/core/java/com/android/internal/app/ResolverListController.java
+++ b/core/java/com/android/internal/app/ResolverListController.java
@@ -30,6 +30,7 @@
import android.content.pm.ResolveInfo;
import android.os.RemoteException;
import android.util.Log;
+import com.android.internal.annotations.GuardedBy;
import com.android.internal.annotations.VisibleForTesting;
import java.lang.InterruptedException;
@@ -55,7 +56,11 @@
private static final String TAG = "ResolverListController";
private static final boolean DEBUG = false;
+ Object mLock = new Object();
+
+ @GuardedBy("mLock")
private ResolverComparator mResolverComparator;
+ private boolean isComputed = false;
public ResolverListController(
Context context,
@@ -68,6 +73,10 @@
mLaunchedFromUid = launchedFromUid;
mTargetIntent = targetIntent;
mReferrerPackage = referrerPackage;
+ synchronized (mLock) {
+ mResolverComparator =
+ new ResolverComparator(mContext, mTargetIntent, mReferrerPackage, null);
+ }
}
@VisibleForTesting
@@ -232,25 +241,29 @@
@VisibleForTesting
@WorkerThread
public void sort(List<ResolverActivity.ResolvedComponentInfo> inputList) {
- final CountDownLatch finishComputeSignal = new CountDownLatch(1);
- ComputeCallback callback = new ComputeCallback(finishComputeSignal);
- if (mResolverComparator == null) {
- mResolverComparator =
- new ResolverComparator(mContext, mTargetIntent, mReferrerPackage, callback);
- } else {
- mResolverComparator.setCallBack(callback);
- }
- try {
- long beforeRank = System.currentTimeMillis();
- mResolverComparator.compute(inputList);
- finishComputeSignal.await();
- Collections.sort(inputList, mResolverComparator);
- long afterRank = System.currentTimeMillis();
- if (DEBUG) {
- Log.d(TAG, "Time Cost: " + Long.toString(afterRank - beforeRank));
+ synchronized (mLock) {
+ if (mResolverComparator == null) {
+ Log.d(TAG, "Comparator has already been destroyed; skipped.");
+ return;
}
- } catch (InterruptedException e) {
- Log.e(TAG, "Compute & Sort was interrupted: " + e);
+ final CountDownLatch finishComputeSignal = new CountDownLatch(1);
+ ComputeCallback callback = new ComputeCallback(finishComputeSignal);
+ mResolverComparator.setCallBack(callback);
+ try {
+ long beforeRank = System.currentTimeMillis();
+ if (!isComputed) {
+ mResolverComparator.compute(inputList);
+ finishComputeSignal.await();
+ isComputed = true;
+ }
+ Collections.sort(inputList, mResolverComparator);
+ long afterRank = System.currentTimeMillis();
+ if (DEBUG) {
+ Log.d(TAG, "Time Cost: " + Long.toString(afterRank - beforeRank));
+ }
+ } catch (InterruptedException e) {
+ Log.e(TAG, "Compute & Sort was interrupted: " + e);
+ }
}
}
@@ -271,27 +284,36 @@
@VisibleForTesting
public float getScore(ResolverActivity.DisplayResolveInfo target) {
- if (mResolverComparator == null) {
- return 0.0f;
+ synchronized (mLock) {
+ if (mResolverComparator == null) {
+ return 0.0f;
+ }
+ return mResolverComparator.getScore(target.getResolvedComponentName());
}
- return mResolverComparator.getScore(target.getResolvedComponentName());
}
public void updateModel(ComponentName componentName) {
- if (mResolverComparator != null) {
- mResolverComparator.updateModel(componentName);
+ synchronized (mLock) {
+ if (mResolverComparator != null) {
+ mResolverComparator.updateModel(componentName);
+ }
}
}
public void updateChooserCounts(String packageName, int userId, String action) {
- if (mResolverComparator != null) {
- mResolverComparator.updateChooserCounts(packageName, userId, action);
+ synchronized (mLock) {
+ if (mResolverComparator != null) {
+ mResolverComparator.updateChooserCounts(packageName, userId, action);
+ }
}
}
public void destroy() {
- if (mResolverComparator != null) {
- mResolverComparator.destroy();
+ synchronized (mLock) {
+ if (mResolverComparator != null) {
+ mResolverComparator.destroy();
+ }
+ mResolverComparator = null;
}
}
}
diff --git a/core/java/com/android/internal/content/FileSystemProvider.java b/core/java/com/android/internal/content/FileSystemProvider.java
index 79544df..ebea1a4 100644
--- a/core/java/com/android/internal/content/FileSystemProvider.java
+++ b/core/java/com/android/internal/content/FileSystemProvider.java
@@ -27,6 +27,7 @@
import android.database.MatrixCursor.RowBuilder;
import android.graphics.Point;
import android.net.Uri;
+import android.os.Binder;
import android.os.CancellationSignal;
import android.os.FileObserver;
import android.os.FileUtils;
@@ -156,11 +157,17 @@
if (visibleFolder != null) {
assert (visibleFolder.isDirectory());
- final ContentResolver resolver = getContext().getContentResolver();
- final Uri uri = MediaStore.Files.getDirectoryUri("external");
- ContentValues values = new ContentValues();
- values.put(MediaStore.Files.FileColumns.DATA, visibleFolder.getAbsolutePath());
- resolver.insert(uri, values);
+ final long token = Binder.clearCallingIdentity();
+
+ try {
+ final ContentResolver resolver = getContext().getContentResolver();
+ final Uri uri = MediaStore.Files.getDirectoryUri("external");
+ ContentValues values = new ContentValues();
+ values.put(MediaStore.Files.FileColumns.DATA, visibleFolder.getAbsolutePath());
+ resolver.insert(uri, values);
+ } finally {
+ Binder.restoreCallingIdentity(token);
+ }
}
}
@@ -214,22 +221,28 @@
// They should be all null or not null at the same time. File#renameTo() doesn't work across
// volumes so an exception will be thrown before calling this method.
if (oldVisibleFile != null && newVisibleFile != null) {
- final ContentResolver resolver = getContext().getContentResolver();
- final Uri externalUri = newVisibleFile.isDirectory()
- ? MediaStore.Files.getDirectoryUri("external")
- : MediaStore.Files.getContentUri("external");
+ final long token = Binder.clearCallingIdentity();
- ContentValues values = new ContentValues();
- values.put(MediaStore.Files.FileColumns.DATA, newVisibleFile.getAbsolutePath());
+ try {
+ final ContentResolver resolver = getContext().getContentResolver();
+ final Uri externalUri = newVisibleFile.isDirectory()
+ ? MediaStore.Files.getDirectoryUri("external")
+ : MediaStore.Files.getContentUri("external");
- // Logic borrowed from MtpDatabase.
- // note - we are relying on a special case in MediaProvider.update() to update
- // the paths for all children in the case where this is a directory.
- final String path = oldVisibleFile.getAbsolutePath();
- resolver.update(externalUri,
- values,
- "_data LIKE ? AND lower(_data)=lower(?)",
- new String[] { path, path });
+ ContentValues values = new ContentValues();
+ values.put(MediaStore.Files.FileColumns.DATA, newVisibleFile.getAbsolutePath());
+
+ // Logic borrowed from MtpDatabase.
+ // note - we are relying on a special case in MediaProvider.update() to update
+ // the paths for all children in the case where this is a directory.
+ final String path = oldVisibleFile.getAbsolutePath();
+ resolver.update(externalUri,
+ values,
+ "_data LIKE ? AND lower(_data)=lower(?)",
+ new String[]{path, path});
+ } finally {
+ Binder.restoreCallingIdentity(token);
+ }
}
}
@@ -253,23 +266,29 @@
throws FileNotFoundException {
// visibleFolder is null if we're removing a document from external thumb drive or SD card.
if (visibleFile != null) {
- final ContentResolver resolver = getContext().getContentResolver();
- final Uri externalUri = MediaStore.Files.getContentUri("external");
+ final long token = Binder.clearCallingIdentity();
- // Remove media store entries for any files inside this directory, using
- // path prefix match. Logic borrowed from MtpDatabase.
- if (isFolder) {
- final String path = visibleFile.getAbsolutePath() + "/";
+ try {
+ final ContentResolver resolver = getContext().getContentResolver();
+ final Uri externalUri = MediaStore.Files.getContentUri("external");
+
+ // Remove media store entries for any files inside this directory, using
+ // path prefix match. Logic borrowed from MtpDatabase.
+ if (isFolder) {
+ final String path = visibleFile.getAbsolutePath() + "/";
+ resolver.delete(externalUri,
+ "_data LIKE ?1 AND lower(substr(_data,1,?2))=lower(?3)",
+ new String[]{path + "%", Integer.toString(path.length()), path});
+ }
+
+ // Remove media store entry for this exact file.
+ final String path = visibleFile.getAbsolutePath();
resolver.delete(externalUri,
- "_data LIKE ?1 AND lower(substr(_data,1,?2))=lower(?3)",
- new String[] { path + "%", Integer.toString(path.length()), path });
+ "_data LIKE ?1 AND lower(_data)=lower(?2)",
+ new String[]{path, path});
+ } finally {
+ Binder.restoreCallingIdentity(token);
}
-
- // Remove media store entry for this exact file.
- final String path = visibleFile.getAbsolutePath();
- resolver.delete(externalUri,
- "_data LIKE ?1 AND lower(_data)=lower(?2)",
- new String[] { path, path });
}
}
diff --git a/core/java/com/android/internal/os/BatteryStatsHelper.java b/core/java/com/android/internal/os/BatteryStatsHelper.java
index f3632f0..f085e29 100644
--- a/core/java/com/android/internal/os/BatteryStatsHelper.java
+++ b/core/java/com/android/internal/os/BatteryStatsHelper.java
@@ -840,7 +840,10 @@
if (sipper.shouldHide) {
if (sipper.drainType != BatterySipper.DrainType.OVERCOUNTED
&& sipper.drainType != BatterySipper.DrainType.SCREEN
- && sipper.drainType != BatterySipper.DrainType.UNACCOUNTED) {
+ && sipper.drainType != BatterySipper.DrainType.UNACCOUNTED
+ && sipper.drainType != BatterySipper.DrainType.BLUETOOTH
+ && sipper.drainType != BatterySipper.DrainType.WIFI
+ && sipper.drainType != BatterySipper.DrainType.IDLE) {
// Don't add it if it is overcounted, unaccounted or screen
proportionalSmearPowerMah += sipper.totalPowerMah;
}
@@ -861,19 +864,19 @@
* time.
*/
public void smearScreenBatterySipper(List<BatterySipper> sippers, BatterySipper screenSipper) {
- final long rawRealtimeMs = SystemClock.elapsedRealtime();
long totalActivityTimeMs = 0;
final SparseLongArray activityTimeArray = new SparseLongArray();
for (int i = 0, size = sippers.size(); i < size; i++) {
final BatteryStats.Uid uid = sippers.get(i).uidObj;
if (uid != null) {
- final long timeMs = getForegroundActivityTotalTimeMs(uid, rawRealtimeMs);
+ final long timeMs = getProcessForegroundTimeMs(uid,
+ BatteryStats.STATS_SINCE_CHARGED);
activityTimeArray.put(uid.getUid(), timeMs);
totalActivityTimeMs += timeMs;
}
}
- if (totalActivityTimeMs >= 10 * DateUtils.MINUTE_IN_MILLIS) {
+ if (screenSipper != null && totalActivityTimeMs >= 10 * DateUtils.MINUTE_IN_MILLIS) {
final double screenPowerMah = screenSipper.totalPowerMah;
for (int i = 0, size = sippers.size(); i < size; i++) {
final BatterySipper sipper = sippers.get(i);
@@ -936,17 +939,42 @@
return false;
}
+ public long convertUsToMs(long timeUs) {
+ return timeUs / 1000;
+ }
+
+ public long convertMsToUs(long timeMs) {
+ return timeMs * 1000;
+ }
+
@VisibleForTesting
- public long getForegroundActivityTotalTimeMs(BatteryStats.Uid uid, long rawRealtimeMs) {
+ public long getForegroundActivityTotalTimeUs(BatteryStats.Uid uid, long rawRealtimeUs) {
final BatteryStats.Timer timer = uid.getForegroundActivityTimer();
if (timer != null) {
- return timer.getTotalTimeLocked(rawRealtimeMs, BatteryStats.STATS_SINCE_CHARGED);
+ return timer.getTotalTimeLocked(rawRealtimeUs, BatteryStats.STATS_SINCE_CHARGED);
}
return 0;
}
@VisibleForTesting
+ public long getProcessForegroundTimeMs(BatteryStats.Uid uid, int which) {
+ final long rawRealTimeUs = convertMsToUs(SystemClock.elapsedRealtime());
+ final int foregroundTypes[] = {BatteryStats.Uid.PROCESS_STATE_TOP};
+
+ long timeUs = 0;
+ for (int type : foregroundTypes) {
+ final long localTime = uid.getProcessStateTime(type, rawRealTimeUs, which);
+ timeUs += localTime;
+ }
+
+ // Return the min value of STATE_TOP time and foreground activity time, since both of these
+ // time have some errors.
+ return convertUsToMs(
+ Math.min(timeUs, getForegroundActivityTotalTimeUs(uid, rawRealTimeUs)));
+ }
+
+ @VisibleForTesting
public void setPackageManager(PackageManager packageManager) {
mPackageManager = packageManager;
}
diff --git a/core/java/com/android/internal/os/BatteryStatsImpl.java b/core/java/com/android/internal/os/BatteryStatsImpl.java
index cb00c5e..fa23e40 100644
--- a/core/java/com/android/internal/os/BatteryStatsImpl.java
+++ b/core/java/com/android/internal/os/BatteryStatsImpl.java
@@ -42,7 +42,7 @@
import android.os.RemoteException;
import android.os.ServiceManager;
import android.os.SystemClock;
-import android.os.SystemProperties;
+import android.os.UserHandle;
import android.os.WorkSource;
import android.telephony.DataConnectionRealTimeInfo;
import android.telephony.ModemActivityInfo;
@@ -75,7 +75,7 @@
import com.android.internal.util.FastXmlSerializer;
import com.android.internal.util.JournaledFile;
import com.android.internal.util.XmlUtils;
-import com.android.server.NetworkManagementSocketTagger;
+
import libcore.util.EmptyArray;
import org.xmlpull.v1.XmlPullParser;
import org.xmlpull.v1.XmlPullParserException;
@@ -119,7 +119,7 @@
private static final int MAGIC = 0xBA757475; // 'BATSTATS'
// Current on-disk Parcel version
- private static final int VERSION = 159 + (USE_OLD_HISTORY ? 1000 : 0);
+ private static final int VERSION = 160 + (USE_OLD_HISTORY ? 1000 : 0);
// Maximum number of items we will record in the history.
private static final int MAX_HISTORY_ITEMS;
@@ -194,6 +194,17 @@
public String getSubsystemLowPowerStats();
}
+ public static abstract class UserInfoProvider {
+ private int[] userIds;
+ protected abstract @Nullable int[] getUserIds();
+ private final void refreshUserIds() {
+ userIds = getUserIds();
+ }
+ private final boolean exists(int userId) {
+ return userIds != null ? ArrayUtils.contains(userIds, userId) : true;
+ }
+ }
+
private final PlatformIdleStateCallback mPlatformIdleStateCallback;
final class MyHandler extends Handler {
@@ -262,6 +273,7 @@
public final MyHandler mHandler;
private ExternalStatsSync mExternalSync = null;
+ private UserInfoProvider mUserInfoProvider = null;
private BatteryCallback mCallback;
@@ -649,6 +661,7 @@
mDailyFile = null;
mHandler = null;
mPlatformIdleStateCallback = null;
+ mUserInfoProvider = null;
clearHistoryLocked();
}
@@ -3664,11 +3677,11 @@
addHistoryEventLocked(elapsedRealtime, uptime, HistoryItem.EVENT_JOB_START, name, uid);
}
- public void noteJobFinishLocked(String name, int uid) {
+ public void noteJobFinishLocked(String name, int uid, int stopReason) {
uid = mapUid(uid);
final long elapsedRealtime = mClocks.elapsedRealtime();
final long uptime = mClocks.uptimeMillis();
- getUidStatsLocked(uid).noteStopJobLocked(name, elapsedRealtime);
+ getUidStatsLocked(uid).noteStopJobLocked(name, elapsedRealtime, stopReason);
if (!mActiveEvents.updateState(HistoryItem.EVENT_JOB_FINISH, name, uid, 0)) {
return;
}
@@ -5702,6 +5715,11 @@
final OverflowArrayMap<DualTimer> mJobStats;
/**
+ * Count of the jobs that have completed and the reasons why they completed.
+ */
+ final ArrayMap<String, SparseIntArray> mJobCompletions = new ArrayMap<>();
+
+ /**
* The statistics we have collected for this uid's sensor activations.
*/
final SparseArray<Sensor> mSensorStats = new SparseArray<>();
@@ -5823,6 +5841,11 @@
}
@Override
+ public ArrayMap<String, SparseIntArray> getJobCompletionStats() {
+ return mJobCompletions;
+ }
+
+ @Override
public SparseArray<? extends BatteryStats.Uid.Sensor> getSensorStats() {
return mSensorStats;
}
@@ -6706,6 +6729,7 @@
}
}
mJobStats.cleanup();
+ mJobCompletions.clear();
for (int ise=mSensorStats.size()-1; ise>=0; ise--) {
Sensor s = mSensorStats.valueAt(ise);
if (s.reset()) {
@@ -6868,6 +6892,21 @@
return !active;
}
+ void writeJobCompletionsToParcelLocked(Parcel out) {
+ int NJC = mJobCompletions.size();
+ out.writeInt(NJC);
+ for (int ijc=0; ijc<NJC; ijc++) {
+ out.writeString(mJobCompletions.keyAt(ijc));
+ SparseIntArray types = mJobCompletions.valueAt(ijc);
+ int NT = types.size();
+ out.writeInt(NT);
+ for (int it=0; it<NT; it++) {
+ out.writeInt(types.keyAt(it));
+ out.writeInt(types.valueAt(it));
+ }
+ }
+ }
+
void writeToParcelLocked(Parcel out, long uptimeUs, long elapsedRealtimeUs) {
mOnBatteryBackgroundTimeBase.writeToParcel(out, uptimeUs, elapsedRealtimeUs);
mOnBatteryScreenOffBackgroundTimeBase.writeToParcel(out, uptimeUs, elapsedRealtimeUs);
@@ -6899,6 +6938,8 @@
Timer.writeTimerToParcel(out, timer, elapsedRealtimeUs);
}
+ writeJobCompletionsToParcelLocked(out);
+
int NSE = mSensorStats.size();
out.writeInt(NSE);
for (int ise=0; ise<NSE; ise++) {
@@ -7114,6 +7155,24 @@
}
}
+ void readJobCompletionsFromParcelLocked(Parcel in) {
+ int numJobCompletions = in.readInt();
+ mJobCompletions.clear();
+ for (int j = 0; j < numJobCompletions; j++) {
+ String jobName = in.readString();
+ int numTypes = in.readInt();
+ if (numTypes > 0) {
+ SparseIntArray types = new SparseIntArray();
+ for (int k = 0; k < numTypes; k++) {
+ int type = in.readInt();
+ int count = in.readInt();
+ types.put(type, count);
+ }
+ mJobCompletions.put(jobName, types);
+ }
+ }
+ }
+
void readFromParcelLocked(TimeBase timeBase, TimeBase screenOffTimeBase, Parcel in) {
mOnBatteryBackgroundTimeBase.readFromParcel(in);
mOnBatteryScreenOffBackgroundTimeBase.readFromParcel(in);
@@ -7148,6 +7207,8 @@
}
}
+ readJobCompletionsFromParcelLocked(in);
+
int numSensors = in.readInt();
mSensorStats.clear();
for (int k = 0; k < numSensors; k++) {
@@ -8460,11 +8521,20 @@
}
}
- public void noteStopJobLocked(String name, long elapsedRealtimeMs) {
+ public void noteStopJobLocked(String name, long elapsedRealtimeMs, int stopReason) {
DualTimer t = mJobStats.stopObject(name);
if (t != null) {
t.stopRunningLocked(elapsedRealtimeMs);
}
+ if (mBsi.mOnBatteryTimeBase.isRunning()) {
+ SparseIntArray types = mJobCompletions.get(name);
+ if (types == null) {
+ types = new SparseIntArray();
+ mJobCompletions.put(name, types);
+ }
+ int last = types.get(stopReason, 0);
+ types.put(stopReason, last + 1);
+ }
}
public StopwatchTimer getWakelockTimerLocked(Wakelock wl, int type) {
@@ -8588,16 +8658,14 @@
return mCpuFreqs;
}
- public BatteryStatsImpl(File systemDir, Handler handler) {
- this(new SystemClocks(), systemDir, handler, null);
+ public BatteryStatsImpl(File systemDir, Handler handler, PlatformIdleStateCallback cb,
+ UserInfoProvider userInfoProvider) {
+ this(new SystemClocks(), systemDir, handler, cb, userInfoProvider);
}
- public BatteryStatsImpl(File systemDir, Handler handler, PlatformIdleStateCallback cb) {
- this(new SystemClocks(), systemDir, handler, cb);
- }
-
- public BatteryStatsImpl(Clocks clocks, File systemDir, Handler handler,
- PlatformIdleStateCallback cb) {
+ private BatteryStatsImpl(Clocks clocks, File systemDir, Handler handler,
+ PlatformIdleStateCallback cb,
+ UserInfoProvider userInfoProvider) {
init(clocks);
if (systemDir != null) {
@@ -8684,6 +8752,7 @@
clearHistoryLocked();
updateDailyDeadlineLocked();
mPlatformIdleStateCallback = cb;
+ mUserInfoProvider = userInfoProvider;
}
public BatteryStatsImpl(Parcel p) {
@@ -10172,6 +10241,7 @@
// we read, we get a delta. If we are to distribute the cpu time, then do so. Otherwise
// we just ignore the data.
final long startTimeMs = mClocks.uptimeMillis();
+ mUserInfoProvider.refreshUserIds();
mKernelUidCpuTimeReader.readDelta(!mOnBatteryInternal ? null :
new KernelUidCpuTimeReader.Callback() {
@Override
@@ -10185,6 +10255,11 @@
+ " no mapping to owning uid: " + uid);
return;
}
+ if (!mUserInfoProvider.exists(UserHandle.getUserId(uid))) {
+ Slog.d(TAG, "Got readings for an invalid user's uid " + uid);
+ mKernelUidCpuTimeReader.removeUid(uid);
+ return;
+ }
final Uid u = getUidStatsLocked(uid);
// Accumulate the total system and user time.
@@ -10357,6 +10432,11 @@
+ " no mapping to owning uid: " + uid);
return;
}
+ if (!mUserInfoProvider.exists(UserHandle.getUserId(uid))) {
+ Slog.d(TAG, "Got readings for an invalid user's uid " + uid);
+ mKernelUidCpuFreqTimeReader.removeUid(uid);
+ return;
+ }
final Uid u = getUidStatsLocked(uid);
if (u.mCpuFreqTimeMs == null) {
u.mCpuFreqTimeMs = new LongSamplingCounterArray(mOnBatteryTimeBase);
@@ -11018,6 +11098,23 @@
return u;
}
+ public void onCleanupUserLocked(int userId) {
+ final int firstUidForUser = UserHandle.getUid(userId, 0);
+ final int lastUidForUser = UserHandle.getUid(userId, UserHandle.PER_USER_RANGE - 1);
+ mKernelUidCpuFreqTimeReader.removeUidsInRange(firstUidForUser, lastUidForUser);
+ mKernelUidCpuTimeReader.removeUidsInRange(firstUidForUser, lastUidForUser);
+ }
+
+ public void onUserRemovedLocked(int userId) {
+ final int firstUidForUser = UserHandle.getUid(userId, 0);
+ final int lastUidForUser = UserHandle.getUid(userId, UserHandle.PER_USER_RANGE - 1);
+ mUidStats.put(firstUidForUser, null);
+ mUidStats.put(lastUidForUser, null);
+ final int firstIndex = mUidStats.indexOfKey(firstUidForUser);
+ final int lastIndex = mUidStats.indexOfKey(lastUidForUser);
+ mUidStats.removeAtRange(firstIndex, lastIndex - firstIndex + 1);
+ }
+
/**
* Remove the statistics object for a particular uid.
*/
@@ -11640,6 +11737,8 @@
u.readJobSummaryFromParcelLocked(name, in);
}
+ u.readJobCompletionsFromParcelLocked(in);
+
int NP = in.readInt();
if (NP > 1000) {
throw new ParcelFormatException("File corrupt: too many sensors " + NP);
@@ -12079,6 +12178,8 @@
jobStats.valueAt(ij).writeSummaryFromParcelLocked(out, NOWREAL_SYS);
}
+ u.writeJobCompletionsToParcelLocked(out);
+
int NSE = u.mSensorStats.size();
out.writeInt(NSE);
for (int ise=0; ise<NSE; ise++) {
diff --git a/core/java/com/android/internal/os/KernelUidCpuFreqTimeReader.java b/core/java/com/android/internal/os/KernelUidCpuFreqTimeReader.java
index ce5e73a..f282fac 100644
--- a/core/java/com/android/internal/os/KernelUidCpuFreqTimeReader.java
+++ b/core/java/com/android/internal/os/KernelUidCpuFreqTimeReader.java
@@ -76,6 +76,17 @@
mLastUidCpuFreqTimeMs.delete(uid);
}
+ public void removeUidsInRange(int startUid, int endUid) {
+ if (endUid < startUid) {
+ return;
+ }
+ mLastUidCpuFreqTimeMs.put(startUid, null);
+ mLastUidCpuFreqTimeMs.put(endUid, null);
+ final int firstIndex = mLastUidCpuFreqTimeMs.indexOfKey(startUid);
+ final int lastIndex = mLastUidCpuFreqTimeMs.indexOfKey(endUid);
+ mLastUidCpuFreqTimeMs.removeAtRange(firstIndex, lastIndex - firstIndex + 1);
+ }
+
@VisibleForTesting
public void readDelta(BufferedReader reader, @Nullable Callback callback) throws IOException {
String line = reader.readLine();
diff --git a/core/java/com/android/internal/os/KernelUidCpuTimeReader.java b/core/java/com/android/internal/os/KernelUidCpuTimeReader.java
index 181e1ac..37d9d1d 100644
--- a/core/java/com/android/internal/os/KernelUidCpuTimeReader.java
+++ b/core/java/com/android/internal/os/KernelUidCpuTimeReader.java
@@ -130,17 +130,42 @@
* @param uid The UID to remove.
*/
public void removeUid(int uid) {
- int index = mLastUserTimeUs.indexOfKey(uid);
+ final int index = mLastSystemTimeUs.indexOfKey(uid);
if (index >= 0) {
- mLastUserTimeUs.removeAt(index);
mLastSystemTimeUs.removeAt(index);
+ mLastUserTimeUs.removeAt(index);
}
+ removeUidsFromKernelModule(uid, uid);
+ }
+ /**
+ * Removes UIDs in a given range from the kernel module and internal accounting data.
+ * @param startUid the first uid to remove
+ * @param endUid the last uid to remove
+ */
+ public void removeUidsInRange(int startUid, int endUid) {
+ if (endUid < startUid) {
+ return;
+ }
+ mLastSystemTimeUs.put(startUid, 0);
+ mLastUserTimeUs.put(startUid, 0);
+ mLastSystemTimeUs.put(endUid, 0);
+ mLastUserTimeUs.put(endUid, 0);
+ final int startIndex = mLastSystemTimeUs.indexOfKey(startUid);
+ final int endIndex = mLastSystemTimeUs.indexOfKey(endUid);
+ mLastSystemTimeUs.removeAtRange(startIndex, endIndex - startIndex + 1);
+ mLastUserTimeUs.removeAtRange(startIndex, endIndex - startIndex + 1);
+ removeUidsFromKernelModule(startUid, endUid);
+ }
+
+ private void removeUidsFromKernelModule(int startUid, int endUid) {
+ Slog.d(TAG, "Removing uids " + startUid + "-" + endUid);
try (FileWriter writer = new FileWriter(sRemoveUidProcFile)) {
- writer.write(Integer.toString(uid) + "-" + Integer.toString(uid));
+ writer.write(startUid + "-" + endUid);
writer.flush();
} catch (IOException e) {
- Slog.e(TAG, "failed to remove uid from uid_cputime module", e);
+ Slog.e(TAG, "failed to remove uids " + startUid + " - " + endUid
+ + " from uid_cputime module", e);
}
}
}
diff --git a/core/java/com/android/internal/os/RuntimeInit.java b/core/java/com/android/internal/os/RuntimeInit.java
index f4be128..66475e4 100644
--- a/core/java/com/android/internal/os/RuntimeInit.java
+++ b/core/java/com/android/internal/os/RuntimeInit.java
@@ -31,6 +31,7 @@
import com.android.internal.logging.AndroidConfig;
import com.android.server.NetworkManagementSocketTagger;
import dalvik.system.VMRuntime;
+import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.util.TimeZone;
@@ -228,8 +229,8 @@
* @param argv Argument vector for main()
* @param classLoader the classLoader to load {@className} with
*/
- private static void invokeStaticMain(String className, String[] argv, ClassLoader classLoader)
- throws Zygote.MethodAndArgsCaller {
+ private static Runnable findStaticMain(String className, String[] argv,
+ ClassLoader classLoader) {
Class<?> cl;
try {
@@ -263,7 +264,7 @@
* clears up all the stack frames that were required in setting
* up the process.
*/
- throw new Zygote.MethodAndArgsCaller(m, argv);
+ return new MethodAndArgsCaller(m, argv);
}
public static final void main(String[] argv) {
@@ -286,8 +287,8 @@
if (DEBUG) Slog.d(TAG, "Leaving RuntimeInit!");
}
- protected static void applicationInit(int targetSdkVersion, String[] argv, ClassLoader classLoader)
- throws Zygote.MethodAndArgsCaller {
+ protected static Runnable applicationInit(int targetSdkVersion, String[] argv,
+ ClassLoader classLoader) {
// If the application calls System.exit(), terminate the process
// immediately without running any shutdown hooks. It is not possible to
// shutdown an Android application gracefully. Among other things, the
@@ -300,20 +301,13 @@
VMRuntime.getRuntime().setTargetHeapUtilization(0.75f);
VMRuntime.getRuntime().setTargetSdkVersion(targetSdkVersion);
- final Arguments args;
- try {
- args = new Arguments(argv);
- } catch (IllegalArgumentException ex) {
- Slog.e(TAG, ex.getMessage());
- // let the process exit
- return;
- }
+ final Arguments args = new Arguments(argv);
// The end of of the RuntimeInit event (see #zygoteInit).
Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
// Remaining arguments are passed to the start class's static main
- invokeStaticMain(args.startClass, args.startArgs, classLoader);
+ return findStaticMain(args.startClass, args.startArgs, classLoader);
}
/**
@@ -422,4 +416,37 @@
System.arraycopy(args, curArg, startArgs, 0, startArgs.length);
}
}
+
+ /**
+ * Helper class which holds a method and arguments and can call them. This is used as part of
+ * a trampoline to get rid of the initial process setup stack frames.
+ */
+ static class MethodAndArgsCaller implements Runnable {
+ /** method to call */
+ private final Method mMethod;
+
+ /** argument array */
+ private final String[] mArgs;
+
+ public MethodAndArgsCaller(Method method, String[] args) {
+ mMethod = method;
+ mArgs = args;
+ }
+
+ public void run() {
+ try {
+ mMethod.invoke(null, new Object[] { mArgs });
+ } catch (IllegalAccessException ex) {
+ throw new RuntimeException(ex);
+ } catch (InvocationTargetException ex) {
+ Throwable cause = ex.getCause();
+ if (cause instanceof RuntimeException) {
+ throw (RuntimeException) cause;
+ } else if (cause instanceof Error) {
+ throw (Error) cause;
+ }
+ throw new RuntimeException(ex);
+ }
+ }
+ }
}
diff --git a/core/java/com/android/internal/os/WebViewZygoteInit.java b/core/java/com/android/internal/os/WebViewZygoteInit.java
index e28079f..7f46a0c 100644
--- a/core/java/com/android/internal/os/WebViewZygoteInit.java
+++ b/core/java/com/android/internal/os/WebViewZygoteInit.java
@@ -26,6 +26,7 @@
import android.webkit.WebViewFactory;
import android.webkit.WebViewFactoryProvider;
+import java.io.DataOutputStream;
import java.io.File;
import java.io.IOException;
import java.lang.reflect.InvocationTargetException;
@@ -68,8 +69,7 @@
}
@Override
- protected boolean handlePreloadPackage(String packagePath, String libsPath,
- String cacheKey) {
+ protected void handlePreloadPackage(String packagePath, String libsPath, String cacheKey) {
Log.i(TAG, "Beginning package preload");
// 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.
@@ -87,19 +87,28 @@
// Once we have the classloader, look up the WebViewFactoryProvider implementation and
// call preloadInZygote() on it to give it the opportunity to preload the native library
// and perform any other initialisation work that should be shared among the children.
+ boolean preloadSucceeded = false;
try {
Class<WebViewFactoryProvider> providerClass =
WebViewFactory.getWebViewProviderClass(loader);
Object result = providerClass.getMethod("preloadInZygote").invoke(null);
- if (!((Boolean)result).booleanValue()) {
+ preloadSucceeded = ((Boolean) result).booleanValue();
+ if (!preloadSucceeded) {
Log.e(TAG, "preloadInZygote returned false");
}
} catch (ClassNotFoundException | NoSuchMethodException | SecurityException |
IllegalAccessException | InvocationTargetException e) {
Log.e(TAG, "Exception while preloading package", e);
}
+
+ try {
+ DataOutputStream socketOut = getSocketOutputStream();
+ socketOut.writeInt(preloadSucceeded ? 1 : 0);
+ } catch (IOException ioe) {
+ throw new IllegalStateException("Error writing to command socket", ioe);
+ }
+
Log.i(TAG, "Package preload done");
- return false;
}
}
@@ -113,16 +122,23 @@
throw new RuntimeException("Failed to setpgid(0,0)", ex);
}
+ final Runnable caller;
try {
sServer.registerServerSocket("webview_zygote");
- sServer.runSelectLoop(TextUtils.join(",", Build.SUPPORTED_ABIS));
- sServer.closeServerSocket();
- } catch (Zygote.MethodAndArgsCaller caller) {
- caller.run();
+ // The select loop returns early in the child process after a fork and
+ // loops forever in the zygote.
+ caller = sServer.runSelectLoop(TextUtils.join(",", Build.SUPPORTED_ABIS));
} catch (RuntimeException e) {
Log.e(TAG, "Fatal exception:", e);
+ throw e;
+ } finally {
+ sServer.closeServerSocket();
}
- System.exit(0);
+ // We're in the child process and have exited the select loop. Proceed to execute the
+ // command.
+ if (caller != null) {
+ caller.run();
+ }
}
}
diff --git a/core/java/com/android/internal/os/WrapperInit.java b/core/java/com/android/internal/os/WrapperInit.java
index 608bc9f..89328b2 100644
--- a/core/java/com/android/internal/os/WrapperInit.java
+++ b/core/java/com/android/internal/os/WrapperInit.java
@@ -25,7 +25,6 @@
import android.system.StructCapUserHeader;
import android.util.BootTimingsTraceLog;
import android.util.Slog;
-import com.android.internal.os.Zygote.MethodAndArgsCaller;
import dalvik.system.VMRuntime;
import java.io.DataOutputStream;
import java.io.FileDescriptor;
@@ -61,37 +60,35 @@
* @param args The command-line arguments.
*/
public static void main(String[] args) {
- try {
- // Parse our mandatory arguments.
- int fdNum = Integer.parseInt(args[0], 10);
- int targetSdkVersion = Integer.parseInt(args[1], 10);
+ // Parse our mandatory arguments.
+ int fdNum = Integer.parseInt(args[0], 10);
+ int targetSdkVersion = Integer.parseInt(args[1], 10);
- // Tell the Zygote what our actual PID is (since it only knows about the
- // wrapper that it directly forked).
- if (fdNum != 0) {
- try {
- FileDescriptor fd = new FileDescriptor();
- fd.setInt$(fdNum);
- DataOutputStream os = new DataOutputStream(new FileOutputStream(fd));
- os.writeInt(Process.myPid());
- os.close();
- IoUtils.closeQuietly(fd);
- } catch (IOException ex) {
- Slog.d(TAG, "Could not write pid of wrapped process to Zygote pipe.", ex);
- }
+ // Tell the Zygote what our actual PID is (since it only knows about the
+ // wrapper that it directly forked).
+ if (fdNum != 0) {
+ try {
+ FileDescriptor fd = new FileDescriptor();
+ fd.setInt$(fdNum);
+ DataOutputStream os = new DataOutputStream(new FileOutputStream(fd));
+ os.writeInt(Process.myPid());
+ os.close();
+ IoUtils.closeQuietly(fd);
+ } catch (IOException ex) {
+ Slog.d(TAG, "Could not write pid of wrapped process to Zygote pipe.", ex);
}
-
- // Mimic system Zygote preloading.
- ZygoteInit.preload(new BootTimingsTraceLog("WrapperInitTiming",
- Trace.TRACE_TAG_DALVIK));
-
- // Launch the application.
- String[] runtimeArgs = new String[args.length - 2];
- System.arraycopy(args, 2, runtimeArgs, 0, runtimeArgs.length);
- WrapperInit.wrapperInit(targetSdkVersion, runtimeArgs);
- } catch (Zygote.MethodAndArgsCaller caller) {
- caller.run();
}
+
+ // Mimic system Zygote preloading.
+ ZygoteInit.preload(new BootTimingsTraceLog("WrapperInitTiming",
+ Trace.TRACE_TAG_DALVIK));
+
+ // Launch the application.
+ String[] runtimeArgs = new String[args.length - 2];
+ System.arraycopy(args, 2, runtimeArgs, 0, runtimeArgs.length);
+ Runnable r = wrapperInit(targetSdkVersion, runtimeArgs);
+
+ r.run();
}
/**
@@ -142,8 +139,7 @@
* @param targetSdkVersion target SDK version
* @param argv arg strings
*/
- private static void wrapperInit(int targetSdkVersion, String[] argv)
- throws Zygote.MethodAndArgsCaller {
+ private static Runnable wrapperInit(int targetSdkVersion, String[] argv) {
if (RuntimeInit.DEBUG) {
Slog.d(RuntimeInit.TAG, "RuntimeInit: Starting application from wrapper");
}
@@ -165,7 +161,7 @@
// Perform the same initialization that would happen after the Zygote forks.
Zygote.nativePreApplicationInit();
- RuntimeInit.applicationInit(targetSdkVersion, argv, classLoader);
+ return RuntimeInit.applicationInit(targetSdkVersion, argv, classLoader);
}
/**
diff --git a/core/java/com/android/internal/os/Zygote.java b/core/java/com/android/internal/os/Zygote.java
index 0106b81..a9350db 100644
--- a/core/java/com/android/internal/os/Zygote.java
+++ b/core/java/com/android/internal/os/Zygote.java
@@ -221,39 +221,4 @@
command.append(" '").append(arg.replace("'", "'\\''")).append("'");
}
}
-
- /**
- * Helper exception class which holds a method and arguments and
- * can call them. This is used as part of a trampoline to get rid of
- * the initial process setup stack frames.
- */
- public static class MethodAndArgsCaller extends Exception
- implements Runnable {
- /** method to call */
- private final Method mMethod;
-
- /** argument array */
- private final String[] mArgs;
-
- public MethodAndArgsCaller(Method method, String[] args) {
- mMethod = method;
- mArgs = args;
- }
-
- public void run() {
- try {
- mMethod.invoke(null, new Object[] { mArgs });
- } catch (IllegalAccessException ex) {
- throw new RuntimeException(ex);
- } catch (InvocationTargetException ex) {
- Throwable cause = ex.getCause();
- if (cause instanceof RuntimeException) {
- throw (RuntimeException) cause;
- } else if (cause instanceof Error) {
- throw (Error) cause;
- }
- throw new RuntimeException(ex);
- }
- }
- }
}
diff --git a/core/java/com/android/internal/os/ZygoteConnection.java b/core/java/com/android/internal/os/ZygoteConnection.java
index 2013ac0..33382ed 100644
--- a/core/java/com/android/internal/os/ZygoteConnection.java
+++ b/core/java/com/android/internal/os/ZygoteConnection.java
@@ -26,7 +26,6 @@
import android.net.LocalSocket;
import android.os.FactoryTest;
import android.os.Process;
-import android.os.SELinux;
import android.os.SystemProperties;
import android.os.Trace;
import android.system.ErrnoException;
@@ -36,15 +35,13 @@
import java.io.BufferedReader;
import java.io.DataInputStream;
import java.io.DataOutputStream;
+import java.io.EOFException;
import java.io.FileDescriptor;
import java.io.FileInputStream;
-import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStreamReader;
-import java.io.PrintStream;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
-import java.util.Arrays;
import libcore.io.IoUtils;
/**
@@ -80,6 +77,7 @@
private final BufferedReader mSocketReader;
private final Credentials peer;
private final String abiList;
+ private boolean isEof;
/**
* Constructs instance from connected socket.
@@ -106,6 +104,8 @@
Log.e(TAG, "Cannot read peer credentials", ex);
throw ex;
}
+
+ isEof = false;
}
/**
@@ -118,21 +118,14 @@
}
/**
- * Reads one start command from the command socket. If successful,
- * a child is forked and a {@link Zygote.MethodAndArgsCaller}
- * exception is thrown in that child while in the parent process,
- * the method returns normally. On failure, the child is not
- * spawned and messages are printed to the log and stderr. Returns
- * a boolean status value indicating whether an end-of-file on the command
- * socket has been encountered.
+ * Reads one start command from the command socket. If successful, a child is forked and a
+ * {@code Runnable} that calls the childs main method (or equivalent) is returned in the child
+ * process. {@code null} is always returned in the parent process (the zygote).
*
- * @return false if command socket should continue to be read from, or
- * true if an end-of-file has been encountered.
- * @throws Zygote.MethodAndArgsCaller trampoline to invoke main()
- * method in child process
+ * If the client closes the socket, an {@code EOF} condition is set, which callers can test
+ * for by calling {@code ZygoteConnection.isClosedByPeer}.
*/
- boolean runOnce(ZygoteServer zygoteServer) throws Zygote.MethodAndArgsCaller {
-
+ Runnable processOneCommand(ZygoteServer zygoteServer) {
String args[];
Arguments parsedArgs = null;
FileDescriptor[] descriptors;
@@ -141,130 +134,120 @@
args = readArgumentList();
descriptors = mSocket.getAncillaryFileDescriptors();
} catch (IOException ex) {
- Log.w(TAG, "IOException on command socket " + ex.getMessage());
- closeSocket();
- return true;
+ throw new IllegalStateException("IOException on command socket", ex);
}
+ // readArgumentList returns null only when it has reached EOF with no available
+ // data to read. This will only happen when the remote socket has disconnected.
if (args == null) {
- // EOF reached.
- closeSocket();
- return true;
- }
-
- /** the stderr of the most recent request, if avail */
- PrintStream newStderr = null;
-
- if (descriptors != null && descriptors.length >= 3) {
- newStderr = new PrintStream(
- new FileOutputStream(descriptors[2]));
+ isEof = true;
+ return null;
}
int pid = -1;
FileDescriptor childPipeFd = null;
FileDescriptor serverPipeFd = null;
- try {
- parsedArgs = new Arguments(args);
+ parsedArgs = new Arguments(args);
- if (parsedArgs.abiListQuery) {
- return handleAbiListQuery();
- }
+ if (parsedArgs.abiListQuery) {
+ handleAbiListQuery();
+ return null;
+ }
- if (parsedArgs.preloadDefault) {
- return handlePreload();
- }
+ if (parsedArgs.preloadDefault) {
+ handlePreload();
+ return null;
+ }
- if (parsedArgs.preloadPackage != null) {
- return handlePreloadPackage(parsedArgs.preloadPackage,
- parsedArgs.preloadPackageLibs, parsedArgs.preloadPackageCacheKey);
- }
+ if (parsedArgs.preloadPackage != null) {
+ handlePreloadPackage(parsedArgs.preloadPackage, parsedArgs.preloadPackageLibs,
+ parsedArgs.preloadPackageCacheKey);
+ return null;
+ }
- if (parsedArgs.permittedCapabilities != 0 || parsedArgs.effectiveCapabilities != 0) {
- throw new ZygoteSecurityException("Client may not specify capabilities: " +
- "permitted=0x" + Long.toHexString(parsedArgs.permittedCapabilities) +
- ", effective=0x" + Long.toHexString(parsedArgs.effectiveCapabilities));
- }
+ if (parsedArgs.permittedCapabilities != 0 || parsedArgs.effectiveCapabilities != 0) {
+ throw new ZygoteSecurityException("Client may not specify capabilities: " +
+ "permitted=0x" + Long.toHexString(parsedArgs.permittedCapabilities) +
+ ", effective=0x" + Long.toHexString(parsedArgs.effectiveCapabilities));
+ }
- applyUidSecurityPolicy(parsedArgs, peer);
- applyInvokeWithSecurityPolicy(parsedArgs, peer);
+ applyUidSecurityPolicy(parsedArgs, peer);
+ applyInvokeWithSecurityPolicy(parsedArgs, peer);
- applyDebuggerSystemProperty(parsedArgs);
- applyInvokeWithSystemProperty(parsedArgs);
+ applyDebuggerSystemProperty(parsedArgs);
+ applyInvokeWithSystemProperty(parsedArgs);
- int[][] rlimits = null;
+ int[][] rlimits = null;
- if (parsedArgs.rlimits != null) {
- rlimits = parsedArgs.rlimits.toArray(intArray2d);
- }
+ if (parsedArgs.rlimits != null) {
+ rlimits = parsedArgs.rlimits.toArray(intArray2d);
+ }
- int[] fdsToIgnore = null;
+ int[] fdsToIgnore = null;
- if (parsedArgs.invokeWith != null) {
+ if (parsedArgs.invokeWith != null) {
+ try {
FileDescriptor[] pipeFds = Os.pipe2(O_CLOEXEC);
childPipeFd = pipeFds[1];
serverPipeFd = pipeFds[0];
Os.fcntlInt(childPipeFd, F_SETFD, 0);
- fdsToIgnore = new int[] { childPipeFd.getInt$(), serverPipeFd.getInt$() };
+ fdsToIgnore = new int[]{childPipeFd.getInt$(), serverPipeFd.getInt$()};
+ } catch (ErrnoException errnoEx) {
+ throw new IllegalStateException("Unable to set up pipe for invoke-with", errnoEx);
}
-
- /**
- * In order to avoid leaking descriptors to the Zygote child,
- * the native code must close the two Zygote socket descriptors
- * in the child process before it switches from Zygote-root to
- * the UID and privileges of the application being launched.
- *
- * In order to avoid "bad file descriptor" errors when the
- * two LocalSocket objects are closed, the Posix file
- * descriptors are released via a dup2() call which closes
- * the socket and substitutes an open descriptor to /dev/null.
- */
-
- int [] fdsToClose = { -1, -1 };
-
- FileDescriptor fd = mSocket.getFileDescriptor();
-
- if (fd != null) {
- fdsToClose[0] = fd.getInt$();
- }
-
- fd = zygoteServer.getServerSocketFileDescriptor();
-
- if (fd != null) {
- fdsToClose[1] = fd.getInt$();
- }
-
- fd = null;
-
- pid = Zygote.forkAndSpecialize(parsedArgs.uid, parsedArgs.gid, parsedArgs.gids,
- parsedArgs.debugFlags, rlimits, parsedArgs.mountExternal, parsedArgs.seInfo,
- parsedArgs.niceName, fdsToClose, fdsToIgnore, parsedArgs.instructionSet,
- parsedArgs.appDataDir);
- } catch (ErrnoException ex) {
- logAndPrintError(newStderr, "Exception creating pipe", ex);
- } catch (IllegalArgumentException ex) {
- logAndPrintError(newStderr, "Invalid zygote arguments", ex);
- } catch (ZygoteSecurityException ex) {
- logAndPrintError(newStderr,
- "Zygote security policy prevents request: ", ex);
}
+ /**
+ * In order to avoid leaking descriptors to the Zygote child,
+ * the native code must close the two Zygote socket descriptors
+ * in the child process before it switches from Zygote-root to
+ * the UID and privileges of the application being launched.
+ *
+ * In order to avoid "bad file descriptor" errors when the
+ * two LocalSocket objects are closed, the Posix file
+ * descriptors are released via a dup2() call which closes
+ * the socket and substitutes an open descriptor to /dev/null.
+ */
+
+ int [] fdsToClose = { -1, -1 };
+
+ FileDescriptor fd = mSocket.getFileDescriptor();
+
+ if (fd != null) {
+ fdsToClose[0] = fd.getInt$();
+ }
+
+ fd = zygoteServer.getServerSocketFileDescriptor();
+
+ if (fd != null) {
+ fdsToClose[1] = fd.getInt$();
+ }
+
+ fd = null;
+
+ pid = Zygote.forkAndSpecialize(parsedArgs.uid, parsedArgs.gid, parsedArgs.gids,
+ parsedArgs.debugFlags, rlimits, parsedArgs.mountExternal, parsedArgs.seInfo,
+ parsedArgs.niceName, fdsToClose, fdsToIgnore, parsedArgs.instructionSet,
+ parsedArgs.appDataDir);
+
try {
if (pid == 0) {
// in child
+ zygoteServer.setForkChild();
+
zygoteServer.closeServerSocket();
IoUtils.closeQuietly(serverPipeFd);
serverPipeFd = null;
- handleChildProc(parsedArgs, descriptors, childPipeFd, newStderr);
- // should never get here, the child is expected to either
- // throw Zygote.MethodAndArgsCaller or exec().
- return true;
+ return handleChildProc(parsedArgs, descriptors, childPipeFd);
} else {
- // in parent...pid of < 0 means failure
+ // In the parent. A pid < 0 indicates a failure and will be handled in
+ // handleParentProc.
IoUtils.closeQuietly(childPipeFd);
childPipeFd = null;
- return handleParentProc(pid, descriptors, serverPipeFd, parsedArgs);
+ handleParentProc(pid, descriptors, serverPipeFd);
+ return null;
}
} finally {
IoUtils.closeQuietly(childPipeFd);
@@ -272,15 +255,13 @@
}
}
- private boolean handleAbiListQuery() {
+ private void handleAbiListQuery() {
try {
final byte[] abiListBytes = abiList.getBytes(StandardCharsets.US_ASCII);
mSocketOutStream.writeInt(abiListBytes.length);
mSocketOutStream.write(abiListBytes);
- return false;
} catch (IOException ioe) {
- Log.e(TAG, "Error writing to command socket", ioe);
- return true;
+ throw new IllegalStateException("Error writing to command socket", ioe);
}
}
@@ -290,7 +271,7 @@
* if no preload was initiated. The latter implies that the zygote is not configured to load
* resources lazy or that the zygote has already handled a previous request to handlePreload.
*/
- private boolean handlePreload() {
+ private void handlePreload() {
try {
if (isPreloadComplete()) {
mSocketOutStream.writeInt(1);
@@ -298,11 +279,8 @@
preload();
mSocketOutStream.writeInt(0);
}
-
- return false;
} catch (IOException ioe) {
- Log.e(TAG, "Error writing to command socket", ioe);
- return true;
+ throw new IllegalStateException("Error writing to command socket", ioe);
}
}
@@ -314,7 +292,11 @@
return ZygoteInit.isPreloadComplete();
}
- protected boolean handlePreloadPackage(String packagePath, String libsPath, String cacheKey) {
+ protected DataOutputStream getSocketOutputStream() {
+ return mSocketOutStream;
+ }
+
+ protected void handlePreloadPackage(String packagePath, String libsPath, String cacheKey) {
throw new RuntimeException("Zyogte does not support package preloading");
}
@@ -330,6 +312,10 @@
}
}
+ boolean isClosedByPeer() {
+ return isEof;
+ }
+
/**
* Handles argument parsing for args related to the zygote spawner.
*
@@ -777,15 +763,9 @@
* @param parsedArgs non-null; zygote args
* @param descriptors null-ok; new file descriptors for stdio if available.
* @param pipeFd null-ok; pipe for communication back to Zygote.
- * @param newStderr null-ok; stream to use for stderr until stdio
- * is reopened.
- *
- * @throws Zygote.MethodAndArgsCaller on success to
- * trampoline to code that invokes static main.
*/
- private void handleChildProc(Arguments parsedArgs,
- FileDescriptor[] descriptors, FileDescriptor pipeFd, PrintStream newStderr)
- throws Zygote.MethodAndArgsCaller {
+ private Runnable handleChildProc(Arguments parsedArgs, FileDescriptor[] descriptors,
+ FileDescriptor pipeFd) {
/**
* By the time we get here, the native code has closed the two actual Zygote
* socket connections, and substituted /dev/null in their place. The LocalSocket
@@ -802,7 +782,6 @@
for (FileDescriptor fd: descriptors) {
IoUtils.closeQuietly(fd);
}
- newStderr = System.err;
} catch (ErrnoException ex) {
Log.e(TAG, "Error reopening stdio", ex);
}
@@ -819,9 +798,12 @@
parsedArgs.niceName, parsedArgs.targetSdkVersion,
VMRuntime.getCurrentInstructionSet(),
pipeFd, parsedArgs.remainingArgs);
+
+ // Should not get here.
+ throw new IllegalStateException("WrapperInit.execApplication unexpectedly returned");
} else {
- ZygoteInit.zygoteInit(parsedArgs.targetSdkVersion,
- parsedArgs.remainingArgs, null /* classLoader */);
+ return ZygoteInit.zygoteInit(parsedArgs.targetSdkVersion, parsedArgs.remainingArgs,
+ null /* classLoader */);
}
}
@@ -833,13 +815,8 @@
* @param descriptors null-ok; file descriptors for child's new stdio if
* specified.
* @param pipeFd null-ok; pipe for communication with child.
- * @param parsedArgs non-null; zygote args
- * @return true for "exit command loop" and false for "continue command
- * loop"
*/
- private boolean handleParentProc(int pid,
- FileDescriptor[] descriptors, FileDescriptor pipeFd, Arguments parsedArgs) {
-
+ private void handleParentProc(int pid, FileDescriptor[] descriptors, FileDescriptor pipeFd) {
if (pid > 0) {
setChildPgid(pid);
}
@@ -888,11 +865,8 @@
mSocketOutStream.writeInt(pid);
mSocketOutStream.writeBoolean(usingWrapper);
} catch (IOException ex) {
- Log.e(TAG, "Error writing to command socket", ex);
- return true;
+ throw new IllegalStateException("Error writing to command socket", ex);
}
-
- return false;
}
private void setChildPgid(int pid) {
@@ -908,20 +882,4 @@
+ "normal if peer is not in our session");
}
}
-
- /**
- * Logs an error message and prints it to the specified stream, if
- * provided
- *
- * @param newStderr null-ok; a standard error stream
- * @param message non-null; error message
- * @param ex null-ok an exception
- */
- private static void logAndPrintError (PrintStream newStderr,
- String message, Throwable ex) {
- Log.e(TAG, message, ex);
- if (newStderr != null) {
- newStderr.println(message + (ex == null ? "" : ex));
- }
- }
}
diff --git a/core/java/com/android/internal/os/ZygoteInit.java b/core/java/com/android/internal/os/ZygoteInit.java
index 385976c..b9022bc 100644
--- a/core/java/com/android/internal/os/ZygoteInit.java
+++ b/core/java/com/android/internal/os/ZygoteInit.java
@@ -24,7 +24,6 @@
import android.icu.impl.CacheValue;
import android.icu.text.DecimalFormatSymbols;
import android.icu.util.ULocale;
-import android.net.LocalServerSocket;
import android.opengl.EGL14;
import android.os.Build;
import android.os.IInstalld;
@@ -446,10 +445,7 @@
/**
* Finish remaining work for the newly forked system server process.
*/
- private static void handleSystemServerProcess(
- ZygoteConnection.Arguments parsedArgs)
- throws Zygote.MethodAndArgsCaller {
-
+ private static Runnable handleSystemServerProcess(ZygoteConnection.Arguments parsedArgs) {
// set umask to 0077 so new files and directories will default to owner-only permissions.
Os.umask(S_IRWXG | S_IRWXO);
@@ -495,6 +491,8 @@
WrapperInit.execApplication(parsedArgs.invokeWith,
parsedArgs.niceName, parsedArgs.targetSdkVersion,
VMRuntime.getCurrentInstructionSet(), null, args);
+
+ throw new IllegalStateException("Unexpected return from WrapperInit.execApplication");
} else {
ClassLoader cl = null;
if (systemServerClasspath != null) {
@@ -506,7 +504,7 @@
/*
* Pass the remaining arguments to SystemServer.
*/
- ZygoteInit.zygoteInit(parsedArgs.targetSdkVersion, parsedArgs.remainingArgs, cl);
+ return ZygoteInit.zygoteInit(parsedArgs.targetSdkVersion, parsedArgs.remainingArgs, cl);
}
/* should never reach here */
@@ -588,10 +586,13 @@
}
/**
- * Prepare the arguments and fork for the system server process.
+ * Prepare the arguments and forks for the system server process.
+ *
+ * Returns an {@code Runnable} that provides an entrypoint into system_server code in the
+ * child process, and {@code null} in the parent.
*/
- private static boolean startSystemServer(String abiList, String socketName, ZygoteServer zygoteServer)
- throws Zygote.MethodAndArgsCaller, RuntimeException {
+ private static Runnable forkSystemServer(String abiList, String socketName,
+ ZygoteServer zygoteServer) {
long capabilities = posixCapabilitiesAsBits(
OsConstants.CAP_IPC_LOCK,
OsConstants.CAP_KILL,
@@ -648,10 +649,10 @@
}
zygoteServer.closeServerSocket();
- handleSystemServerProcess(parsedArgs);
+ return handleSystemServerProcess(parsedArgs);
}
- return true;
+ return null;
}
/**
@@ -682,6 +683,7 @@
throw new RuntimeException("Failed to setpgid(0,0)", ex);
}
+ final Runnable caller;
try {
// Report Zygote start time to tron unless it is a runtime restart
if (!"1".equals(SystemProperties.get("sys.boot_completed"))) {
@@ -751,19 +753,32 @@
ZygoteHooks.stopZygoteNoThreadCreation();
if (startSystemServer) {
- startSystemServer(abiList, socketName, zygoteServer);
+ Runnable r = forkSystemServer(abiList, socketName, zygoteServer);
+
+ // {@code r == null} in the parent (zygote) process, and {@code r != null} in the
+ // child (system_server) process.
+ if (r != null) {
+ r.run();
+ return;
+ }
}
Log.i(TAG, "Accepting command socket connections");
- zygoteServer.runSelectLoop(abiList);
- zygoteServer.closeServerSocket();
- } catch (Zygote.MethodAndArgsCaller caller) {
- caller.run();
+ // The select loop returns early in the child process after a fork and
+ // loops forever in the zygote.
+ caller = zygoteServer.runSelectLoop(abiList);
} catch (Throwable ex) {
Log.e(TAG, "System zygote died with exception", ex);
- zygoteServer.closeServerSocket();
throw ex;
+ } finally {
+ zygoteServer.closeServerSocket();
+ }
+
+ // We're in the child process and have exited the select loop. Proceed to execute the
+ // command.
+ if (caller != null) {
+ caller.run();
}
}
@@ -807,8 +822,7 @@
* @param targetSdkVersion target SDK version
* @param argv arg strings
*/
- public static final void zygoteInit(int targetSdkVersion, String[] argv,
- ClassLoader classLoader) throws Zygote.MethodAndArgsCaller {
+ public static final Runnable zygoteInit(int targetSdkVersion, String[] argv, ClassLoader classLoader) {
if (RuntimeInit.DEBUG) {
Slog.d(RuntimeInit.TAG, "RuntimeInit: Starting application from zygote");
}
@@ -818,7 +832,7 @@
RuntimeInit.commonInit();
ZygoteInit.nativeZygoteInit();
- RuntimeInit.applicationInit(targetSdkVersion, argv, classLoader);
+ return RuntimeInit.applicationInit(targetSdkVersion, argv, classLoader);
}
private static final native void nativeZygoteInit();
diff --git a/core/java/com/android/internal/os/ZygoteServer.java b/core/java/com/android/internal/os/ZygoteServer.java
index 126d9e7..8baa15a 100644
--- a/core/java/com/android/internal/os/ZygoteServer.java
+++ b/core/java/com/android/internal/os/ZygoteServer.java
@@ -25,6 +25,7 @@
import android.system.StructPollfd;
import android.util.Log;
+import android.util.Slog;
import java.io.IOException;
import java.io.FileDescriptor;
import java.util.ArrayList;
@@ -45,9 +46,18 @@
private LocalServerSocket mServerSocket;
+ /**
+ * Set by the child process, immediately after a call to {@code Zygote.forkAndSpecialize}.
+ */
+ private boolean mIsForkChild;
+
ZygoteServer() {
}
+ void setForkChild() {
+ mIsForkChild = true;
+ }
+
/**
* Registers a server socket for zygote command connections
*
@@ -129,11 +139,8 @@
* Runs the zygote process's select loop. Accepts new connections as
* they happen, and reads commands from connections one spawn-request's
* worth at a time.
- *
- * @throws Zygote.MethodAndArgsCaller in a child process when a main()
- * should be executed.
*/
- void runSelectLoop(String abiList) throws Zygote.MethodAndArgsCaller {
+ Runnable runSelectLoop(String abiList) {
ArrayList<FileDescriptor> fds = new ArrayList<FileDescriptor>();
ArrayList<ZygoteConnection> peers = new ArrayList<ZygoteConnection>();
@@ -156,15 +163,62 @@
if ((pollFds[i].revents & POLLIN) == 0) {
continue;
}
+
if (i == 0) {
ZygoteConnection newPeer = acceptCommandPeer(abiList);
peers.add(newPeer);
fds.add(newPeer.getFileDesciptor());
} else {
- boolean done = peers.get(i).runOnce(this);
- if (done) {
- peers.remove(i);
- fds.remove(i);
+ try {
+ ZygoteConnection connection = peers.get(i);
+ final Runnable command = connection.processOneCommand(this);
+
+ if (mIsForkChild) {
+ // We're in the child. We should always have a command to run at this
+ // stage if processOneCommand hasn't called "exec".
+ if (command == null) {
+ throw new IllegalStateException("command == null");
+ }
+
+ return command;
+ } else {
+ // We're in the server - we should never have any commands to run.
+ if (command != null) {
+ throw new IllegalStateException("command != null");
+ }
+
+ // We don't know whether the remote side of the socket was closed or
+ // not until we attempt to read from it from processOneCommand. This shows up as
+ // a regular POLLIN event in our regular processing loop.
+ if (connection.isClosedByPeer()) {
+ connection.closeSocket();
+ peers.remove(i);
+ fds.remove(i);
+ }
+ }
+ } catch (Exception e) {
+ if (!mIsForkChild) {
+ // We're in the server so any exception here is one that has taken place
+ // pre-fork while processing commands or reading / writing from the
+ // control socket. Make a loud noise about any such exceptions so that
+ // we know exactly what failed and why.
+
+ Slog.e(TAG, "Exception executing zygote command: ", e);
+
+ // Make sure the socket is closed so that the other end knows immediately
+ // that something has gone wrong and doesn't time out waiting for a
+ // response.
+ ZygoteConnection conn = peers.remove(i);
+ conn.closeSocket();
+
+ fds.remove(i);
+ } else {
+ // We're in the child so any exception caught here has happened post
+ // fork and before we execute ActivityThread.main (or any other main()
+ // method). Log the details of the exception and bring down the process.
+ Log.e(TAG, "Caught post-fork exception in child process.", e);
+ throw e;
+ }
}
}
}
diff --git a/core/java/com/android/internal/textservice/ITextServicesManager.aidl b/core/java/com/android/internal/textservice/ITextServicesManager.aidl
index 4882a12..c5940ba 100644
--- a/core/java/com/android/internal/textservice/ITextServicesManager.aidl
+++ b/core/java/com/android/internal/textservice/ITextServicesManager.aidl
@@ -36,9 +36,6 @@
in ITextServicesSessionListener tsListener,
in ISpellCheckerSessionListener scListener, in Bundle bundle);
oneway void finishSpellCheckerService(in ISpellCheckerSessionListener listener);
- oneway void setCurrentSpellChecker(String locale, String sciId);
- oneway void setCurrentSpellCheckerSubtype(String locale, int hashCode);
- oneway void setSpellCheckerEnabled(boolean enabled);
boolean isSpellCheckerEnabled();
SpellCheckerInfo[] getEnabledSpellCheckers();
}
diff --git a/core/jni/AndroidRuntime.cpp b/core/jni/AndroidRuntime.cpp
index 9d9828e..89e137b 100644
--- a/core/jni/AndroidRuntime.cpp
+++ b/core/jni/AndroidRuntime.cpp
@@ -792,19 +792,27 @@
"--compiler-filter=", "-Ximage-compiler-option");
}
- // Make sure there is a preloaded-classes file.
- if (!hasFile("/system/etc/preloaded-classes")) {
- ALOGE("Missing preloaded-classes file, /system/etc/preloaded-classes not found: %s\n",
- strerror(errno));
- return -1;
- }
- addOption("-Ximage-compiler-option");
- addOption("--image-classes=/system/etc/preloaded-classes");
-
- // If there is a compiled-classes file, push it.
- if (hasFile("/system/etc/compiled-classes")) {
+ // If there is a boot profile, it takes precedence over the image and preloaded classes.
+ if (hasFile("/system/etc/boot-image.prof")) {
addOption("-Ximage-compiler-option");
- addOption("--compiled-classes=/system/etc/compiled-classes");
+ addOption("--profile-file=/system/etc/boot-image.prof");
+ addOption("-Ximage-compiler-option");
+ addOption("--compiler-filter=speed-profile");
+ } else {
+ // Make sure there is a preloaded-classes file.
+ if (!hasFile("/system/etc/preloaded-classes")) {
+ ALOGE("Missing preloaded-classes file, /system/etc/preloaded-classes not found: %s\n",
+ strerror(errno));
+ return -1;
+ }
+ addOption("-Ximage-compiler-option");
+ addOption("--image-classes=/system/etc/preloaded-classes");
+
+ // If there is a compiled-classes file, push it.
+ if (hasFile("/system/etc/compiled-classes")) {
+ addOption("-Ximage-compiler-option");
+ addOption("--compiled-classes=/system/etc/compiled-classes");
+ }
}
property_get("dalvik.vm.image-dex2oat-flags", dex2oatImageFlagsBuf, "");
diff --git a/core/jni/android_database_SQLiteConnection.cpp b/core/jni/android_database_SQLiteConnection.cpp
index bcc3bb0..62240ea 100644
--- a/core/jni/android_database_SQLiteConnection.cpp
+++ b/core/jni/android_database_SQLiteConnection.cpp
@@ -112,7 +112,8 @@
static jlong nativeOpen(JNIEnv* env, jclass clazz, jstring pathStr, jint openFlags,
- jstring labelStr, jboolean enableTrace, jboolean enableProfile) {
+ jstring labelStr, jboolean enableTrace, jboolean enableProfile, jint lookasideSz,
+ jint lookasideCnt) {
int sqliteFlags;
if (openFlags & SQLiteConnection::CREATE_IF_NECESSARY) {
sqliteFlags = SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE;
@@ -137,6 +138,16 @@
return 0;
}
+ if (lookasideSz >= 0 && lookasideCnt >= 0) {
+ int err = sqlite3_db_config(db, SQLITE_DBCONFIG_LOOKASIDE, NULL, lookasideSz, lookasideCnt);
+ if (err != SQLITE_OK) {
+ ALOGE("sqlite3_db_config(..., %d, %d) failed: %d", lookasideSz, lookasideCnt, err);
+ throw_sqlite3_exception(env, db, "Cannot set lookaside");
+ sqlite3_close(db);
+ return 0;
+ }
+ }
+
// Check that the database is really read/write when that is what we asked for.
if ((sqliteFlags & SQLITE_OPEN_READWRITE) && sqlite3_db_readonly(db, NULL)) {
throw_sqlite3_exception(env, db, "Could not open the database in read/write mode.");
@@ -789,7 +800,7 @@
static const JNINativeMethod sMethods[] =
{
/* name, signature, funcPtr */
- { "nativeOpen", "(Ljava/lang/String;ILjava/lang/String;ZZ)J",
+ { "nativeOpen", "(Ljava/lang/String;ILjava/lang/String;ZZII)J",
(void*)nativeOpen },
{ "nativeClose", "(J)V",
(void*)nativeClose },
diff --git a/core/res/AndroidManifest.xml b/core/res/AndroidManifest.xml
index be7934b..a3cb350 100644
--- a/core/res/AndroidManifest.xml
+++ b/core/res/AndroidManifest.xml
@@ -279,6 +279,7 @@
<protected-broadcast android:name="com.android.nfc.cardemulation.action.CLOSE_TAP_DIALOG" />
<protected-broadcast android:name="com.android.nfc.handover.action.ALLOW_CONNECT" />
<protected-broadcast android:name="com.android.nfc.handover.action.DENY_CONNECT" />
+ <protected-broadcast android:name="com.android.nfc.handover.action.TIMEOUT_CONNECT" />
<protected-broadcast android:name="com.android.nfc_extras.action.RF_FIELD_ON_DETECTED" />
<protected-broadcast android:name="com.android.nfc_extras.action.RF_FIELD_OFF_DETECTED" />
<protected-broadcast android:name="com.android.nfc_extras.action.AID_SELECTED" />
@@ -2394,6 +2395,15 @@
<permission android:name="android.permission.INTERNAL_SYSTEM_WINDOW"
android:protectionLevel="signature" />
+ <!-- @SystemApi Allows an application to use
+ {@link android.view.WindowManager.LayoutsParams#PRIVATE_FLAG_HIDE_NON_SYSTEM_OVERLAY_WINDOWS}
+ to hide non-system-overlay windows.
+ <p>Not for use by third-party applications.
+ @hide
+ -->
+ <permission android:name="android.permission.HIDE_NON_SYSTEM_OVERLAY_WINDOWS"
+ android:protectionLevel="signature|installer" />
+
<!-- @SystemApi Allows an application to manage (create, destroy,
Z-order) application tokens in the window manager.
<p>Not for use by third-party applications.
@@ -2632,6 +2642,12 @@
<permission android:name="android.permission.MODIFY_PARENTAL_CONTROLS"
android:protectionLevel="signature|privileged" />
+ <!-- @SystemApi Allows an application to read TvContentRatingSystemInfo
+ <p>Not for use by third-party applications.
+ @hide -->
+ <permission android:name="android.permission.READ_CONTENT_RATING_SYSTEMS"
+ android:protectionLevel="signature|privileged" />
+
<!-- @SystemApi Allows an application to notify TV inputs by sending broadcasts.
<p>Protection level: signature|privileged
<p>Not for use by third-party applications.
diff --git a/core/res/res/layout-land/time_picker_material.xml b/core/res/res/layout-land/time_picker_material.xml
index d83ccb2..dc47dcf 100644
--- a/core/res/res/layout-land/time_picker_material.xml
+++ b/core/res/res/layout-land/time_picker_material.xml
@@ -17,7 +17,6 @@
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
- android:layoutDirection="ltr"
android:layout_width="match_parent"
android:layout_height="wrap_content">
@@ -34,6 +33,7 @@
android:layoutDirection="ltr"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
+ android:layout_centerHorizontal="true"
android:paddingTop="@dimen/timepicker_radial_picker_top_margin"
android:orientation="horizontal">
diff --git a/core/res/res/layout/chooser_row.xml b/core/res/res/layout/chooser_row.xml
index 9baa32c..6c1271d 100644
--- a/core/res/res/layout/chooser_row.xml
+++ b/core/res/res/layout/chooser_row.xml
@@ -18,11 +18,9 @@
-->
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="horizontal"
- android:layout_width="match_parent" android:layout_height="wrap_content"
- android:minHeight="80dp"
+ android:layout_width="match_parent"
+ android:layout_height="100dp"
android:gravity="start|top"
- android:paddingTop="8dp"
- android:paddingBottom="8dp"
android:paddingStart="@dimen/chooser_grid_padding"
android:paddingEnd="@dimen/chooser_grid_padding"
android:weightSum="4">
diff --git a/core/res/res/layout/resolve_grid_item.xml b/core/res/res/layout/resolve_grid_item.xml
index 305c8b0..71c153f 100644
--- a/core/res/res/layout/resolve_grid_item.xml
+++ b/core/res/res/layout/resolve_grid_item.xml
@@ -18,10 +18,9 @@
-->
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
- android:layout_width="0dp"
+ android:layout_width="76dp"
android:layout_height="wrap_content"
- android:layout_weight="1"
- android:minWidth="80dp"
+ android:minHeight="100dp"
android:gravity="center"
android:paddingTop="8dp"
android:paddingBottom="8dp"
@@ -49,7 +48,7 @@
<TextView android:id="@android:id/text1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
- android:layout_marginTop="8dp"
+ android:layout_marginTop="4dp"
android:layout_marginLeft="4dp"
android:layout_marginRight="4dp"
android:textAppearance="?attr/textAppearanceSmall"
diff --git a/core/res/res/layout/shutdown_dialog.xml b/core/res/res/layout/shutdown_dialog.xml
new file mode 100644
index 0000000..398bfb1
--- /dev/null
+++ b/core/res/res/layout/shutdown_dialog.xml
@@ -0,0 +1,52 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ 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.
+-->
+<LinearLayout
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:orientation="vertical"
+ android:gravity="center_horizontal" >
+
+ <Space
+ android:layout_width="match_parent"
+ android:layout_height="0dp"
+ android:layout_weight="6" />
+
+ <TextView
+ android:id="@id/text1"
+ android:layout_width="wrap_content"
+ android:layout_height="32dp"
+ android:text="@string/shutdown_progress"
+ android:textDirection="locale"
+ android:textSize="24sp"
+ android:textAppearance="?attr/textAppearanceLarge"
+ android:gravity="center"
+ android:layout_marginBottom="24dp"
+ android:fontFamily="@string/config_headlineFontFamily"/>
+
+ <ProgressBar
+ android:id="@id/progress"
+ android:layout_width="30dp"
+ android:layout_height="30dp"
+ style="?attr/progressBarStyleLarge" />
+
+ <Space
+ android:layout_width="match_parent"
+ android:layout_height="0dp"
+ android:layout_weight="10" />
+
+</LinearLayout>
diff --git a/core/res/res/values-af/strings.xml b/core/res/res/values-af/strings.xml
index 907f895..0e7b5c0 100644
--- a/core/res/res/values-af/strings.xml
+++ b/core/res/res/values-af/strings.xml
@@ -1769,6 +1769,8 @@
<string name="etws_primary_default_message_tsunami" msgid="1887685943498368548">"Ontruim kusgebiede en riviergebiede dadelik en gaan na \'n veiliger plek, soos \'n hoogliggende omgewing."</string>
<string name="etws_primary_default_message_earthquake_and_tsunami" msgid="998797956848445862">"Bly kalm en soek skuiling naby."</string>
<string name="etws_primary_default_message_test" msgid="2709597093560037455">"Noodboodskappetoets"</string>
+ <!-- no translation found for notification_reply_button_accessibility (3621714652387814344) -->
+ <skip />
<string name="etws_primary_default_message_others" msgid="6293148756130398971"></string>
<string name="mmcc_authentication_reject" msgid="7729819349669603406">"SIM word nie toegelaat nie"</string>
<string name="mmcc_imsi_unknown_in_hlr" msgid="6321202257374418726">"SIM is nie opgestel nie"</string>
diff --git a/core/res/res/values-am/strings.xml b/core/res/res/values-am/strings.xml
index 27ce84d..8356efa 100644
--- a/core/res/res/values-am/strings.xml
+++ b/core/res/res/values-am/strings.xml
@@ -1769,6 +1769,8 @@
<string name="etws_primary_default_message_tsunami" msgid="1887685943498368548">"ወዲያውኑ ከባህር ዳርቻ አካባቢዎች እና የወንዝ ዳርቻ አካባቢዎች ይውጡና እንደ ከፍ ያለ መሬት ያሉ ከአደጋ የተሻለ ደህንነት ወዳቸው ቦታዎች ይሂዱ።"</string>
<string name="etws_primary_default_message_earthquake_and_tsunami" msgid="998797956848445862">"ረጋ ይበሉና በአቅራቢያ ያለ መጠለያ ይፈልጉ።"</string>
<string name="etws_primary_default_message_test" msgid="2709597093560037455">"የአስቸኳይ አደጋ መልእክቶች ሙከራ"</string>
+ <!-- no translation found for notification_reply_button_accessibility (3621714652387814344) -->
+ <skip />
<string name="etws_primary_default_message_others" msgid="6293148756130398971"></string>
<string name="mmcc_authentication_reject" msgid="7729819349669603406">"ሲም አይፈቀድም"</string>
<string name="mmcc_imsi_unknown_in_hlr" msgid="6321202257374418726">"ሲም አልቀረበም"</string>
diff --git a/core/res/res/values-ar/strings.xml b/core/res/res/values-ar/strings.xml
index d038a42..26e43ca 100644
--- a/core/res/res/values-ar/strings.xml
+++ b/core/res/res/values-ar/strings.xml
@@ -248,7 +248,7 @@
<string name="status_bar_notification_info_overflow" msgid="5301981741705354993">"999+"</string>
<string name="notification_hidden_text" msgid="1135169301897151909">"المحتويات مخفية"</string>
<string name="notification_hidden_by_policy_text" msgid="9004631276932584600">"تم إخفاء المحتويات بواسطة السياسة"</string>
- <string name="notification_channel_virtual_keyboard" msgid="6969925135507955575">"لوحة المفاتيح الظاهرية"</string>
+ <string name="notification_channel_virtual_keyboard" msgid="6969925135507955575">"لوحة المفاتيح الافتراضية"</string>
<string name="notification_channel_physical_keyboard" msgid="7297661826966861459">"لوحة المفاتيح الفعلية"</string>
<string name="notification_channel_security" msgid="7345516133431326347">"الأمان"</string>
<string name="notification_channel_car_mode" msgid="3553380307619874564">"وضع السيارة"</string>
@@ -258,7 +258,7 @@
<string name="notification_channel_network_status" msgid="5025648583129035447">"حالة الشبكة"</string>
<string name="notification_channel_network_alerts" msgid="2895141221414156525">"تنبيهات الشبكة"</string>
<string name="notification_channel_network_available" msgid="4531717914138179517">"الشبكة متوفرة"</string>
- <string name="notification_channel_vpn" msgid="8330103431055860618">"حالة الشبكة الظاهرية الخاصة"</string>
+ <string name="notification_channel_vpn" msgid="8330103431055860618">"حالة الشبكة الافتراضية الخاصة"</string>
<string name="notification_channel_device_admin" msgid="1568154104368069249">"إدارة الجهاز"</string>
<string name="notification_channel_alerts" msgid="4496839309318519037">"التنبيهات"</string>
<string name="notification_channel_retail_mode" msgid="6088920674914038779">"عرض توضيحي لبائع التجزئة"</string>
@@ -1203,7 +1203,7 @@
<item msgid="75483255295529161">"Wi-Fi"</item>
<item msgid="6862614801537202646">"بلوتوث"</item>
<item msgid="5447331121797802871">"إيثرنت"</item>
- <item msgid="8257233890381651999">"شبكة ظاهرية خاصة (VPN)"</item>
+ <item msgid="8257233890381651999">"شبكة افتراضية خاصة (VPN)"</item>
</string-array>
<string name="network_switch_type_name_unknown" msgid="4552612897806660656">"نوع شبكة غير معروف"</string>
<string name="wifi_watchdog_network_disabled" msgid="7904214231651546347">"تعذر الاتصال بـ Wi-Fi"</string>
@@ -1281,7 +1281,7 @@
<string name="decline_remote_bugreport_action" msgid="6230987241608770062">"رفض"</string>
<string name="select_input_method" msgid="8547250819326693584">"تغيير لوحة المفاتيح"</string>
<string name="show_ime" msgid="2506087537466597099">"استمرار عرضها على الشاشة أثناء نشاط لوحة المفاتيح الفعلية"</string>
- <string name="hardware" msgid="194658061510127999">"إظهار لوحة المفاتيح الظاهرية"</string>
+ <string name="hardware" msgid="194658061510127999">"إظهار لوحة المفاتيح الافتراضية"</string>
<string name="select_keyboard_layout_notification_title" msgid="597189518763083494">"تهيئة لوحة المفاتيح الفعلية"</string>
<string name="select_keyboard_layout_notification_message" msgid="8084622969903004900">"انقر لاختيار لغة وتنسيق"</string>
<string name="fast_scroll_alphabet" msgid="5433275485499039199">" أ ب ت ث ج ح خ د ذ ر ز س ش ص ض ط ظ ع غ ف ق ك ل م ن ه و ي"</string>
@@ -1369,14 +1369,14 @@
<string name="vr_listener_binding_label" msgid="4316591939343607306">"مستمع واقع افتراضي"</string>
<string name="condition_provider_service_binding_label" msgid="1321343352906524564">"موفر الحالة"</string>
<string name="notification_ranker_binding_label" msgid="774540592299064747">"خدمة ترتيب أهمية الإشعارات"</string>
- <string name="vpn_title" msgid="19615213552042827">"تم تنشيط الشبكة الظاهرية الخاصة (VPN)"</string>
+ <string name="vpn_title" msgid="19615213552042827">"تم تنشيط الشبكة الافتراضية الخاصة (VPN)"</string>
<string name="vpn_title_long" msgid="6400714798049252294">"تم تنشيط VPN بواسطة <xliff:g id="APP">%s</xliff:g>"</string>
<string name="vpn_text" msgid="1610714069627824309">"انقر لإدارة الشبكة."</string>
<string name="vpn_text_long" msgid="4907843483284977618">"تم الاتصال بـ <xliff:g id="SESSION">%s</xliff:g>. انقر لإدارة الشبكة."</string>
- <string name="vpn_lockdown_connecting" msgid="6443438964440960745">"جارٍ الاتصال بشبكة ظاهرية خاصة (VPN) دائمة التشغيل..."</string>
- <string name="vpn_lockdown_connected" msgid="8202679674819213931">"تم الاتصال بشبكة ظاهرية خاصة (VPN) دائمة التشغيل"</string>
- <string name="vpn_lockdown_disconnected" msgid="4532298952570796327">"تم فصل الشبكة الظاهرية الخاصة (VPN) دائمة التشغيل"</string>
- <string name="vpn_lockdown_error" msgid="6009249814034708175">"خطأ بشبكة ظاهرية خاصة (VPN) دائمة التشغيل"</string>
+ <string name="vpn_lockdown_connecting" msgid="6443438964440960745">"جارٍ الاتصال بشبكة افتراضية خاصة (VPN) دائمة التشغيل..."</string>
+ <string name="vpn_lockdown_connected" msgid="8202679674819213931">"تم الاتصال بشبكة افتراضية خاصة (VPN) دائمة التشغيل"</string>
+ <string name="vpn_lockdown_disconnected" msgid="4532298952570796327">"تم فصل الشبكة الافتراضية الخاصة (VPN) دائمة التشغيل"</string>
+ <string name="vpn_lockdown_error" msgid="6009249814034708175">"خطأ بشبكة افتراضية خاصة (VPN) دائمة التشغيل"</string>
<string name="vpn_lockdown_config" msgid="5099330695245008680">"انقر للإعداد."</string>
<string name="upload_file" msgid="2897957172366730416">"اختيار ملف"</string>
<string name="no_file_chosen" msgid="6363648562170759465">"لم يتم اختيار أي ملف"</string>
@@ -1905,6 +1905,8 @@
<string name="etws_primary_default_message_tsunami" msgid="1887685943498368548">"يُرجى النزوح في الحال من المناطق الساحلية وضفاف النهر إلى مكان أكثر أمانًا مثل الأراضي المرتفعة."</string>
<string name="etws_primary_default_message_earthquake_and_tsunami" msgid="998797956848445862">"يُرجى الثبات والبحث عن ملاذ بالجوار."</string>
<string name="etws_primary_default_message_test" msgid="2709597093560037455">"اختبار رسائل الطوارئ"</string>
+ <!-- no translation found for notification_reply_button_accessibility (3621714652387814344) -->
+ <skip />
<string name="etws_primary_default_message_others" msgid="6293148756130398971"></string>
<string name="mmcc_authentication_reject" msgid="7729819349669603406">"غير مسموح باستخدام SIM"</string>
<string name="mmcc_imsi_unknown_in_hlr" msgid="6321202257374418726">"لم يتم تقديم SIM"</string>
diff --git a/core/res/res/values-az/strings.xml b/core/res/res/values-az/strings.xml
index 76f7e2c..10198de 100644
--- a/core/res/res/values-az/strings.xml
+++ b/core/res/res/values-az/strings.xml
@@ -1769,6 +1769,8 @@
<string name="etws_primary_default_message_tsunami" msgid="1887685943498368548">"Dərhal sahil bölgələrindən və çay kənarı ərazilərdən daha təhlükəsiz yüksək yerlərə evakuasiya edin."</string>
<string name="etws_primary_default_message_earthquake_and_tsunami" msgid="998797956848445862">"Sakit qalın və yaxınlıqda sığınacaq axtarın."</string>
<string name="etws_primary_default_message_test" msgid="2709597093560037455">"Təcili mesaj testi"</string>
+ <!-- no translation found for notification_reply_button_accessibility (3621714652387814344) -->
+ <skip />
<string name="etws_primary_default_message_others" msgid="6293148756130398971"></string>
<string name="mmcc_authentication_reject" msgid="7729819349669603406">"SIM-ə icazə verilmir"</string>
<string name="mmcc_imsi_unknown_in_hlr" msgid="6321202257374418726">"SIM təmin edilməyib"</string>
diff --git a/core/res/res/values-b+sr+Latn/strings.xml b/core/res/res/values-b+sr+Latn/strings.xml
index 1b67cf7..5849536 100644
--- a/core/res/res/values-b+sr+Latn/strings.xml
+++ b/core/res/res/values-b+sr+Latn/strings.xml
@@ -1204,7 +1204,7 @@
<string name="usb_notification_message" msgid="3370903770828407960">"Dodirnite za još opcija."</string>
<string name="usb_unsupported_audio_accessory_title" msgid="2256529893240208458">"Dodatna oprema za audio sadržaj nije podržana"</string>
<string name="usb_unsupported_audio_accessory_message" msgid="7811865061127547035">"Dodirnite za više informacija"</string>
- <string name="adb_active_notification_title" msgid="6729044778949189918">"Otklanjanje grešaka sa USB-a je uspostavljeno"</string>
+ <string name="adb_active_notification_title" msgid="6729044778949189918">"Otklanjanje grešaka sa USB-a je omogućeno"</string>
<string name="adb_active_notification_message" msgid="4948470599328424059">"Dodirnite da biste onemogućili otklanjanje grešaka sa USB-a."</string>
<string name="adb_active_notification_message" product="tv" msgid="8470296818270110396">"Izaberite da biste onemogućili otklanjanja grešaka sa USB-a."</string>
<string name="taking_remote_bugreport_notification_title" msgid="6742483073875060934">"Izveštaj o grešci se generiše…"</string>
@@ -1803,6 +1803,8 @@
<string name="etws_primary_default_message_tsunami" msgid="1887685943498368548">"Odmah se sklonite iz priobalnih regiona i oblasti pored reka na neko bezbednije mesto, na primer, na neko uzvišenje."</string>
<string name="etws_primary_default_message_earthquake_and_tsunami" msgid="998797956848445862">"Ostanite mirni i potražite sklonište u okolini."</string>
<string name="etws_primary_default_message_test" msgid="2709597093560037455">"Testiranje poruka u hitnim slučajevima"</string>
+ <!-- no translation found for notification_reply_button_accessibility (3621714652387814344) -->
+ <skip />
<string name="etws_primary_default_message_others" msgid="6293148756130398971"></string>
<string name="mmcc_authentication_reject" msgid="7729819349669603406">"SIM kartica nije dozvoljena"</string>
<string name="mmcc_imsi_unknown_in_hlr" msgid="6321202257374418726">"SIM kartica nije podešena"</string>
diff --git a/core/res/res/values-be/strings.xml b/core/res/res/values-be/strings.xml
index 6ad22f6..316ee49 100644
--- a/core/res/res/values-be/strings.xml
+++ b/core/res/res/values-be/strings.xml
@@ -1837,6 +1837,8 @@
<string name="etws_primary_default_message_tsunami" msgid="1887685943498368548">"Неадкладна эвакуіруйцеся з прыбярэжных раёнаў у больш бяспечнае месца, напрыклад на ўзвышша."</string>
<string name="etws_primary_default_message_earthquake_and_tsunami" msgid="998797956848445862">"Заставайцеся спакойнымі і пашукайце прытулак паблізу."</string>
<string name="etws_primary_default_message_test" msgid="2709597093560037455">"Праверка экстранных паведамленняў"</string>
+ <!-- no translation found for notification_reply_button_accessibility (3621714652387814344) -->
+ <skip />
<string name="etws_primary_default_message_others" msgid="6293148756130398971"></string>
<string name="mmcc_authentication_reject" msgid="7729819349669603406">"SIM-карта не дапускаецца"</string>
<string name="mmcc_imsi_unknown_in_hlr" msgid="6321202257374418726">"SIM-карты няма"</string>
diff --git a/core/res/res/values-bg/strings.xml b/core/res/res/values-bg/strings.xml
index c9ed0ca..83ae338 100644
--- a/core/res/res/values-bg/strings.xml
+++ b/core/res/res/values-bg/strings.xml
@@ -268,7 +268,7 @@
<string name="permgroupdesc_calendar" msgid="3889615280211184106">"има достъп до календара ви"</string>
<string name="permgrouplab_sms" msgid="228308803364967808">"SMS"</string>
<string name="permgroupdesc_sms" msgid="4656988620100940350">"да изпраща и преглежда SMS съобщения"</string>
- <string name="permgrouplab_storage" msgid="1971118770546336966">"Съхранение"</string>
+ <string name="permgrouplab_storage" msgid="1971118770546336966">"Хранилище"</string>
<string name="permgroupdesc_storage" msgid="637758554581589203">"да има достъп до снимките, мултимедията и файловете на устройството ви"</string>
<string name="permgrouplab_microphone" msgid="171539900250043464">"Микрофон"</string>
<string name="permgroupdesc_microphone" msgid="4988812113943554584">"записва звук"</string>
@@ -1769,6 +1769,8 @@
<string name="etws_primary_default_message_tsunami" msgid="1887685943498368548">"Евакуирайте се незабавно от крайбрежните и крайречните региони на по-безопасно място – например такова с по-високо надморско равнище."</string>
<string name="etws_primary_default_message_earthquake_and_tsunami" msgid="998797956848445862">"Запазете спокойствие и потърсете убежище в района."</string>
<string name="etws_primary_default_message_test" msgid="2709597093560037455">"Тест за спешни съобщения"</string>
+ <!-- no translation found for notification_reply_button_accessibility (3621714652387814344) -->
+ <skip />
<string name="etws_primary_default_message_others" msgid="6293148756130398971"></string>
<string name="mmcc_authentication_reject" msgid="7729819349669603406">"SIM картата не е разрешена"</string>
<string name="mmcc_imsi_unknown_in_hlr" msgid="6321202257374418726">"SIM картата не е обезпечена"</string>
diff --git a/core/res/res/values-bn/strings.xml b/core/res/res/values-bn/strings.xml
index 86ff997..3e487b9 100644
--- a/core/res/res/values-bn/strings.xml
+++ b/core/res/res/values-bn/strings.xml
@@ -118,7 +118,9 @@
<string name="roamingText12" msgid="1189071119992726320">"রোমিং ব্যানার বন্ধ আছে"</string>
<string name="roamingTextSearching" msgid="8360141885972279963">"পরিষেবা অনুসন্ধান করা হচ্ছে"</string>
<string name="wfcRegErrorTitle" msgid="2301376280632110664">"ওয়াই-ফাই কলিং"</string>
- <!-- no translation found for wfcOperatorErrorAlertMessages:0 (3910386316304772394) -->
+ <string-array name="wfcOperatorErrorAlertMessages">
+ <item msgid="3910386316304772394">"ওয়াই-ফাই এর মাধ্যমে কল করতে ও মেসেজ পাঠাতে, প্রথমে আপনার পরিষেবা প্রদানকারীকে এই পরিষেবার সেট-আপ করতে বলুন। তারপর আবার সেটিংস থেকে ওয়াই-ফাই কলিং চালু করুন। (ত্রুটি কোড: <xliff:g id="CODE">%1$s</xliff:g>)"</item>
+ </string-array>
<string-array name="wfcOperatorErrorNotificationMessages">
<item msgid="6177300162212449033">"আপনার পরিষেবা প্রদানকারীকে নথিভুক্ত করুন"</item>
</string-array>
@@ -1768,6 +1770,8 @@
<string name="etws_primary_default_message_tsunami" msgid="1887685943498368548">"উপকূলবর্তী এবং নদীর পাশের অঞ্চল থেকে অবিলম্বে উঁচু কোনো জায়গার দিকে যান।"</string>
<string name="etws_primary_default_message_earthquake_and_tsunami" msgid="998797956848445862">"শান্ত থাকুন, আশেপাশে আশ্রয় খুঁজুন।"</string>
<string name="etws_primary_default_message_test" msgid="2709597093560037455">"বিপদকালীন বার্তাগুলির পরীক্ষা"</string>
+ <!-- no translation found for notification_reply_button_accessibility (3621714652387814344) -->
+ <skip />
<string name="etws_primary_default_message_others" msgid="6293148756130398971"></string>
<string name="mmcc_authentication_reject" msgid="7729819349669603406">"সিম অনুমোদিত নয়"</string>
<string name="mmcc_imsi_unknown_in_hlr" msgid="6321202257374418726">"সিম প্রস্তুত নয়"</string>
diff --git a/core/res/res/values-bs/strings.xml b/core/res/res/values-bs/strings.xml
index f1ec56f..4539121 100644
--- a/core/res/res/values-bs/strings.xml
+++ b/core/res/res/values-bs/strings.xml
@@ -1809,6 +1809,8 @@
<string name="etws_primary_default_message_tsunami" msgid="1887685943498368548">"Odmah se evakuirajte iz priobalnih područja i područja oko rijeka na sigurnije mjesto kao što su viši predjeli."</string>
<string name="etws_primary_default_message_earthquake_and_tsunami" msgid="998797956848445862">"Ostanite smireni i potražite sklonište u blizini."</string>
<string name="etws_primary_default_message_test" msgid="2709597093560037455">"Test poruka za hitne slučajeve"</string>
+ <!-- no translation found for notification_reply_button_accessibility (3621714652387814344) -->
+ <skip />
<string name="etws_primary_default_message_others" msgid="6293148756130398971"></string>
<string name="mmcc_authentication_reject" msgid="7729819349669603406">"SIM kartica nije dozvoljena"</string>
<string name="mmcc_imsi_unknown_in_hlr" msgid="6321202257374418726">"SIM kartica nije dodijeljena"</string>
diff --git a/core/res/res/values-ca/strings.xml b/core/res/res/values-ca/strings.xml
index dc769e6..7036603 100644
--- a/core/res/res/values-ca/strings.xml
+++ b/core/res/res/values-ca/strings.xml
@@ -81,9 +81,9 @@
<string name="RestrictedOnEmergencyTitle" msgid="3646729271176394091">"No es poden fer trucades d\'emergència"</string>
<string name="RestrictedOnNormalTitle" msgid="3179574012752700984">"Sense servei de veu"</string>
<string name="RestrictedOnAllVoiceTitle" msgid="158800171499150681">"Sense servei de veu/emergència"</string>
- <string name="RestrictedStateContent" msgid="4278821484643362350">"La xarxa de telefonia mòbil de la teva ubicació temporalment no ofereix aquest servei"</string>
+ <string name="RestrictedStateContent" msgid="4278821484643362350">"La xarxa mòbil de la teva ubicació temporalment no ofereix aquest servei"</string>
<string name="NetworkPreferenceSwitchTitle" msgid="4008877505368566980">"No es pot accedir a la xarxa"</string>
- <string name="NetworkPreferenceSwitchSummary" msgid="1203771446683319957">"Per millorar la recepció, prova de canviar el tipus de xarxa a Configuració > Xarxa i Internet > Xarxes de telefonia mòbil > Tipus de xarxa preferit."</string>
+ <string name="NetworkPreferenceSwitchSummary" msgid="1203771446683319957">"Per millorar la recepció, prova de canviar el tipus de xarxa a Configuració > Xarxa i Internet > Xarxes mòbils > Tipus de xarxa preferit."</string>
<string name="notification_channel_network_alert" msgid="4427736684338074967">"Alertes"</string>
<string name="notification_channel_call_forward" msgid="2419697808481833249">"Desviació de trucades"</string>
<string name="notification_channel_emergency_callback" msgid="6686166232265733921">"Mode de devolució de trucada d\'emergència"</string>
@@ -1154,10 +1154,10 @@
<string name="sms_short_code_confirm_always_allow" msgid="3241181154869493368">"Permet sempre"</string>
<string name="sms_short_code_confirm_never_allow" msgid="446992765774269673">"No permetis mai"</string>
<string name="sim_removed_title" msgid="6227712319223226185">"Extracció de la targeta SIM"</string>
- <string name="sim_removed_message" msgid="2333164559970958645">"La xarxa de telefonia mòbil no estarà disponible fins que no reiniciïs amb una targeta SIM vàlida inserida."</string>
+ <string name="sim_removed_message" msgid="2333164559970958645">"La xarxa mòbil no estarà disponible fins que no reiniciïs amb una targeta SIM vàlida inserida."</string>
<string name="sim_done_button" msgid="827949989369963775">"Fet"</string>
<string name="sim_added_title" msgid="3719670512889674693">"Addició de la targeta SIM"</string>
- <string name="sim_added_message" msgid="6599945301141050216">"Reinicia el dispositiu per accedir a la xarxa de telefonia mòbil."</string>
+ <string name="sim_added_message" msgid="6599945301141050216">"Reinicia el dispositiu per accedir a la xarxa mòbil."</string>
<string name="sim_restart_button" msgid="4722407842815232347">"Reinicia"</string>
<string name="carrier_app_dialog_message" msgid="7066156088266319533">"Perquè la nova SIM funcioni, has d\'instal·lar i obrir una aplicació del teu operador de telefonia mòbil."</string>
<string name="carrier_app_dialog_button" msgid="7900235513678617329">"BAIXA L\'APLICACIÓ"</string>
@@ -1769,6 +1769,8 @@
<string name="etws_primary_default_message_tsunami" msgid="1887685943498368548">"Abandona immediatament les regions costaneres i riberenques, i cerca un lloc més segur, com ara un terreny elevat."</string>
<string name="etws_primary_default_message_earthquake_and_tsunami" msgid="998797956848445862">"Mantén la calma i busca refugi a prop."</string>
<string name="etws_primary_default_message_test" msgid="2709597093560037455">"Prova de missatges d\'emergència"</string>
+ <!-- no translation found for notification_reply_button_accessibility (3621714652387814344) -->
+ <skip />
<string name="etws_primary_default_message_others" msgid="6293148756130398971"></string>
<string name="mmcc_authentication_reject" msgid="7729819349669603406">"SIM no compatible"</string>
<string name="mmcc_imsi_unknown_in_hlr" msgid="6321202257374418726">"SIM no proporcionada"</string>
diff --git a/core/res/res/values-cs/strings.xml b/core/res/res/values-cs/strings.xml
index f117982..04190d5 100644
--- a/core/res/res/values-cs/strings.xml
+++ b/core/res/res/values-cs/strings.xml
@@ -1837,6 +1837,8 @@
<string name="etws_primary_default_message_tsunami" msgid="1887685943498368548">"Z pobřežních oblastí a okolí řek se co nejrychleji přesuňte do většího bezpečí (například na výše položené místo)."</string>
<string name="etws_primary_default_message_earthquake_and_tsunami" msgid="998797956848445862">"Zachovejte klid a přesuňte se na bezpečné místo v okolí."</string>
<string name="etws_primary_default_message_test" msgid="2709597093560037455">"Test nouzových zpráv"</string>
+ <!-- no translation found for notification_reply_button_accessibility (3621714652387814344) -->
+ <skip />
<string name="etws_primary_default_message_others" msgid="6293148756130398971"></string>
<string name="mmcc_authentication_reject" msgid="7729819349669603406">"SIM karta není povolena"</string>
<string name="mmcc_imsi_unknown_in_hlr" msgid="6321202257374418726">"SIM karta není poskytována"</string>
diff --git a/core/res/res/values-da/strings.xml b/core/res/res/values-da/strings.xml
index e7db8d5..3834d7c 100644
--- a/core/res/res/values-da/strings.xml
+++ b/core/res/res/values-da/strings.xml
@@ -1769,6 +1769,8 @@
<string name="etws_primary_default_message_tsunami" msgid="1887685943498368548">"Forlad omgående kyst- og flodområder, og søg mod et mere sikkert sted, f.eks. et højere terræn."</string>
<string name="etws_primary_default_message_earthquake_and_tsunami" msgid="998797956848445862">"Bevar roen, og søg ly i nærheden."</string>
<string name="etws_primary_default_message_test" msgid="2709597093560037455">"Test af nødbeskeder"</string>
+ <!-- no translation found for notification_reply_button_accessibility (3621714652387814344) -->
+ <skip />
<string name="etws_primary_default_message_others" msgid="6293148756130398971"></string>
<string name="mmcc_authentication_reject" msgid="7729819349669603406">"SIM-kortet har ikke adgangstilladelse"</string>
<string name="mmcc_imsi_unknown_in_hlr" msgid="6321202257374418726">"SIM-kortet er ikke aktiveret"</string>
diff --git a/core/res/res/values-de/strings.xml b/core/res/res/values-de/strings.xml
index 7ff623b..27bd4a9 100644
--- a/core/res/res/values-de/strings.xml
+++ b/core/res/res/values-de/strings.xml
@@ -437,7 +437,7 @@
<string name="permlab_accessWifiState" msgid="5202012949247040011">"WLAN-Verbindungen abrufen"</string>
<string name="permdesc_accessWifiState" msgid="5002798077387803726">"Ermöglicht der App, Informationen zu WLAN-Netzwerken abzurufen, etwa ob ein WLAN aktiviert ist, und den Namen verbundener WLAN-Geräte."</string>
<string name="permlab_changeWifiState" msgid="6550641188749128035">"WLAN-Verbindungen herstellen und trennen"</string>
- <string name="permdesc_changeWifiState" msgid="7137950297386127533">"Ermöglicht der App, eine Verbindung zu WLAN-Zugangspunkten herzustellen und solche zu trennen und Änderungen an der Gerätekonfiguration für WLAN-Netzwerke vorzunehmen."</string>
+ <string name="permdesc_changeWifiState" msgid="7137950297386127533">"Ermöglicht der App, eine Verbindung zu WLAN-Zugangspunkten herzustellen und solche zu trennen und Änderungen an der Gerätekonfiguration für WLANs vorzunehmen."</string>
<string name="permlab_changeWifiMulticastState" msgid="1368253871483254784">"WLAN-Multicast-Empfang zulassen"</string>
<string name="permdesc_changeWifiMulticastState" product="tablet" msgid="7969774021256336548">"Ermöglicht der App, Pakete zu empfangen, die mithilfe von Multicast-Adressen an sämtliche Geräte in einem WLAN versendet wurden, nicht nur an dein Tablet. Dies nicht mehr Leistung in Anspruch als der Nicht-Multicast-Modus."</string>
<string name="permdesc_changeWifiMulticastState" product="tv" msgid="9031975661145014160">"Ermöglicht der App, Pakete zu empfangen, die mithilfe von Multicast-Adressen an sämtliche Geräte in einem WLAN gesendet wurden, nicht nur an deinen Fernseher. Dies nimmt mehr Leistung in Anspruch als der Nicht-Multicast-Modus."</string>
@@ -1087,12 +1087,12 @@
<string name="ringtone_picker_title_notification" msgid="4837740874822788802">"Benachrichtigungstöne"</string>
<string name="ringtone_unknown" msgid="3914515995813061520">"Unbekannt"</string>
<plurals name="wifi_available" formatted="false" msgid="7900333017752027322">
- <item quantity="other">WLAN-Netzwerke verfügbar</item>
- <item quantity="one">WLAN-Netzwerk verfügbar</item>
+ <item quantity="other">WLANe verfügbar</item>
+ <item quantity="one">WLAN verfügbar</item>
</plurals>
<plurals name="wifi_available_detailed" formatted="false" msgid="1140699367193975606">
- <item quantity="other">Verfügbare WLAN-Netzwerke öffnen</item>
- <item quantity="one">Verfügbares WLAN-Netzwerk öffnen</item>
+ <item quantity="other">Verfügbare WLANe öffnen</item>
+ <item quantity="one">Verfügbares WLAN öffnen</item>
</plurals>
<string name="wifi_available_title" msgid="3817100557900599505">"Mit offenem WLAN verbinden"</string>
<string name="wifi_available_title_connecting" msgid="1557292688310330032">"Verbindung mit offenem WLAN wird hergestellt"</string>
@@ -1101,7 +1101,7 @@
<string name="wifi_available_content_failed_to_connect" msgid="3377406637062802645">"Tippen, um alle Netzwerke zu sehen"</string>
<string name="wifi_available_action_connect" msgid="2635699628459488788">"Verbinden"</string>
<string name="wifi_available_action_all_networks" msgid="1100098935861622985">"Alle Netzwerke"</string>
- <string name="wifi_available_sign_in" msgid="9157196203958866662">"In WLAN-Netzwerk anmelden"</string>
+ <string name="wifi_available_sign_in" msgid="9157196203958866662">"In WLAN anmelden"</string>
<string name="network_available_sign_in" msgid="1848877297365446605">"Im Netzwerk anmelden"</string>
<!-- no translation found for network_available_sign_in_detailed (8000081941447976118) -->
<skip />
@@ -1121,7 +1121,7 @@
<string name="wifi_watchdog_network_disabled" msgid="7904214231651546347">"Es konnte keine WLAN-Verbindung hergestellt werden."</string>
<string name="wifi_watchdog_network_disabled_detailed" msgid="5548780776418332675">" hat eine schlechte Internetverbindung."</string>
<string name="wifi_connect_alert_title" msgid="8455846016001810172">"Verbindung zulassen?"</string>
- <string name="wifi_connect_alert_message" msgid="6451273376815958922">"Die App \"%1$s\" möchte eine Verbindung zum WLAN-Netzwerk %2$s herstellen."</string>
+ <string name="wifi_connect_alert_message" msgid="6451273376815958922">"Die App \"%1$s\" möchte eine Verbindung zum WLAN %2$s herstellen."</string>
<string name="wifi_connect_default_application" msgid="7143109390475484319">"Eine App"</string>
<string name="wifi_p2p_dialog_title" msgid="97611782659324517">"Wi-Fi Direct"</string>
<string name="wifi_p2p_turnon_message" msgid="2909250942299627244">"Wi-Fi Direct-Betrieb starten. Hierdurch wird der WLAN-Client-/-Hotspot-Betrieb deaktiviert."</string>
@@ -1183,7 +1183,7 @@
<string name="usb_unsupported_audio_accessory_title" msgid="2256529893240208458">"Audiozubehör wird nicht unterstützt"</string>
<string name="usb_unsupported_audio_accessory_message" msgid="7811865061127547035">"Tippen, um weitere Informationen zu erhalten"</string>
<string name="adb_active_notification_title" msgid="6729044778949189918">"USB-Debugging aktiviert"</string>
- <string name="adb_active_notification_message" msgid="4948470599328424059">"Zum Deaktivieren von USB-Debugging tippen."</string>
+ <string name="adb_active_notification_message" msgid="4948470599328424059">"Zum Deaktivieren von USB-Debugging tippen"</string>
<string name="adb_active_notification_message" product="tv" msgid="8470296818270110396">"USB-Debugging deaktivieren: auswählen"</string>
<string name="taking_remote_bugreport_notification_title" msgid="6742483073875060934">"Fehlerbericht wird abgerufen…"</string>
<string name="share_remote_bugreport_notification_title" msgid="4987095013583691873">"Fehlerbericht teilen?"</string>
@@ -1769,6 +1769,8 @@
<string name="etws_primary_default_message_tsunami" msgid="1887685943498368548">"Verlasse so schnell wie möglich Flussufer und Küstengebiete und suche in einer höher gelegenen Umgebung Schutz."</string>
<string name="etws_primary_default_message_earthquake_and_tsunami" msgid="998797956848445862">"Bleibe ruhig und suche in der Nähe Schutz."</string>
<string name="etws_primary_default_message_test" msgid="2709597093560037455">"Test der Notfallwarnungen"</string>
+ <!-- no translation found for notification_reply_button_accessibility (3621714652387814344) -->
+ <skip />
<string name="etws_primary_default_message_others" msgid="6293148756130398971"></string>
<string name="mmcc_authentication_reject" msgid="7729819349669603406">"SIM-Karte nicht zulässig"</string>
<string name="mmcc_imsi_unknown_in_hlr" msgid="6321202257374418726">"SIM nicht eingerichtet"</string>
diff --git a/core/res/res/values-el/strings.xml b/core/res/res/values-el/strings.xml
index def96a8..2421797 100644
--- a/core/res/res/values-el/strings.xml
+++ b/core/res/res/values-el/strings.xml
@@ -1364,7 +1364,7 @@
<string name="action_menu_overflow_description" msgid="2295659037509008453">"Περισσότερες επιλογές"</string>
<string name="action_bar_home_description_format" msgid="7965984360903693903">"%1$s, %2$s"</string>
<string name="action_bar_home_subtitle_description_format" msgid="6985546530471780727">"%1$s, %2$s, %3$s"</string>
- <string name="storage_internal" msgid="3570990907910199483">"Εσωτερικός κοινόχρηστος αποθηκευτικός χώρος"</string>
+ <string name="storage_internal" msgid="3570990907910199483">"Εσωτ. κοινόχρ. αποθ. χώρος"</string>
<string name="storage_sd_card" msgid="3282948861378286745">"Κάρτα SD"</string>
<string name="storage_sd_card_label" msgid="6347111320774379257">"Κάρτα SD <xliff:g id="MANUFACTURER">%s</xliff:g>"</string>
<string name="storage_usb_drive" msgid="6261899683292244209">"Μονάδα USB"</string>
@@ -1769,6 +1769,8 @@
<string name="etws_primary_default_message_tsunami" msgid="1887685943498368548">"Εκκενώστε αμέσως τις παράκτιες περιοχές και τις περιοχές δίπλα σε ποτάμια και μετακινηθείτε σε ένα ασφαλέστερο μέρος, όπως περιοχές με υψόμετρο."</string>
<string name="etws_primary_default_message_earthquake_and_tsunami" msgid="998797956848445862">"Μείνετε ψύχραιμοι και αναζητήστε κάποιο κοντινό καταφύγιο."</string>
<string name="etws_primary_default_message_test" msgid="2709597093560037455">"Δοκιμαστικό μήνυμα έκτακτης ανάγκης"</string>
+ <!-- no translation found for notification_reply_button_accessibility (3621714652387814344) -->
+ <skip />
<string name="etws_primary_default_message_others" msgid="6293148756130398971"></string>
<string name="mmcc_authentication_reject" msgid="7729819349669603406">"Η κάρτα SIM δεν επιτρέπεται"</string>
<string name="mmcc_imsi_unknown_in_hlr" msgid="6321202257374418726">"Δεν παρέχεται κάρτα SIM"</string>
diff --git a/core/res/res/values-en-rAU/strings.xml b/core/res/res/values-en-rAU/strings.xml
index 5db79b8..f546256 100644
--- a/core/res/res/values-en-rAU/strings.xml
+++ b/core/res/res/values-en-rAU/strings.xml
@@ -1769,6 +1769,8 @@
<string name="etws_primary_default_message_tsunami" msgid="1887685943498368548">"Evacuate immediately from coastal regions and riverside areas to a safer place such as high ground."</string>
<string name="etws_primary_default_message_earthquake_and_tsunami" msgid="998797956848445862">"Stay calm and seek shelter nearby."</string>
<string name="etws_primary_default_message_test" msgid="2709597093560037455">"Emergency messages test"</string>
+ <!-- no translation found for notification_reply_button_accessibility (3621714652387814344) -->
+ <skip />
<string name="etws_primary_default_message_others" msgid="6293148756130398971"></string>
<string name="mmcc_authentication_reject" msgid="7729819349669603406">"SIM not allowed"</string>
<string name="mmcc_imsi_unknown_in_hlr" msgid="6321202257374418726">"SIM not provisioned"</string>
diff --git a/core/res/res/values-en-rGB/strings.xml b/core/res/res/values-en-rGB/strings.xml
index 5db79b8..f546256 100644
--- a/core/res/res/values-en-rGB/strings.xml
+++ b/core/res/res/values-en-rGB/strings.xml
@@ -1769,6 +1769,8 @@
<string name="etws_primary_default_message_tsunami" msgid="1887685943498368548">"Evacuate immediately from coastal regions and riverside areas to a safer place such as high ground."</string>
<string name="etws_primary_default_message_earthquake_and_tsunami" msgid="998797956848445862">"Stay calm and seek shelter nearby."</string>
<string name="etws_primary_default_message_test" msgid="2709597093560037455">"Emergency messages test"</string>
+ <!-- no translation found for notification_reply_button_accessibility (3621714652387814344) -->
+ <skip />
<string name="etws_primary_default_message_others" msgid="6293148756130398971"></string>
<string name="mmcc_authentication_reject" msgid="7729819349669603406">"SIM not allowed"</string>
<string name="mmcc_imsi_unknown_in_hlr" msgid="6321202257374418726">"SIM not provisioned"</string>
diff --git a/core/res/res/values-en-rIN/strings.xml b/core/res/res/values-en-rIN/strings.xml
index 5db79b8..f546256 100644
--- a/core/res/res/values-en-rIN/strings.xml
+++ b/core/res/res/values-en-rIN/strings.xml
@@ -1769,6 +1769,8 @@
<string name="etws_primary_default_message_tsunami" msgid="1887685943498368548">"Evacuate immediately from coastal regions and riverside areas to a safer place such as high ground."</string>
<string name="etws_primary_default_message_earthquake_and_tsunami" msgid="998797956848445862">"Stay calm and seek shelter nearby."</string>
<string name="etws_primary_default_message_test" msgid="2709597093560037455">"Emergency messages test"</string>
+ <!-- no translation found for notification_reply_button_accessibility (3621714652387814344) -->
+ <skip />
<string name="etws_primary_default_message_others" msgid="6293148756130398971"></string>
<string name="mmcc_authentication_reject" msgid="7729819349669603406">"SIM not allowed"</string>
<string name="mmcc_imsi_unknown_in_hlr" msgid="6321202257374418726">"SIM not provisioned"</string>
diff --git a/core/res/res/values-es-rUS/strings.xml b/core/res/res/values-es-rUS/strings.xml
index 2a828f7..68fb34b 100644
--- a/core/res/res/values-es-rUS/strings.xml
+++ b/core/res/res/values-es-rUS/strings.xml
@@ -1173,7 +1173,7 @@
<string name="no_permissions" msgid="7283357728219338112">"No se requieren permisos"</string>
<string name="perm_costs_money" msgid="4902470324142151116">"esto puede costarte dinero"</string>
<string name="dlg_ok" msgid="7376953167039865701">"Aceptar"</string>
- <string name="usb_charging_notification_title" msgid="6895185153353640787">"Este dispositivo se está cargando mediante USB"</string>
+ <string name="usb_charging_notification_title" msgid="6895185153353640787">"Cargando este dispositivo por USB"</string>
<string name="usb_supplying_notification_title" msgid="5310642257296510271">"El dispositivo conectado se está cargando mediante USB"</string>
<string name="usb_mtp_notification_title" msgid="8396264943589760855">"USB para transferir archivos"</string>
<string name="usb_ptp_notification_title" msgid="1347328437083192112">"USB para transferir fotos"</string>
@@ -1769,6 +1769,8 @@
<string name="etws_primary_default_message_tsunami" msgid="1887685943498368548">"Evacúa inmediatamente las regiones costeras y ribereñas en busca de un lugar seguro, como un terreno elevado."</string>
<string name="etws_primary_default_message_earthquake_and_tsunami" msgid="998797956848445862">"Mantén la calma y busca un refugio cercano."</string>
<string name="etws_primary_default_message_test" msgid="2709597093560037455">"Prueba de mensajes de emergencia"</string>
+ <!-- no translation found for notification_reply_button_accessibility (3621714652387814344) -->
+ <skip />
<string name="etws_primary_default_message_others" msgid="6293148756130398971"></string>
<string name="mmcc_authentication_reject" msgid="7729819349669603406">"SIM no permitida"</string>
<string name="mmcc_imsi_unknown_in_hlr" msgid="6321202257374418726">"SIM no provista"</string>
diff --git a/core/res/res/values-es/strings.xml b/core/res/res/values-es/strings.xml
index 9323e1f..95f0dff 100644
--- a/core/res/res/values-es/strings.xml
+++ b/core/res/res/values-es/strings.xml
@@ -1183,7 +1183,7 @@
<string name="usb_unsupported_audio_accessory_title" msgid="2256529893240208458">"Accesorio de audio no compatible"</string>
<string name="usb_unsupported_audio_accessory_message" msgid="7811865061127547035">"Toca para obtener más información"</string>
<string name="adb_active_notification_title" msgid="6729044778949189918">"Depuración USB habilitada"</string>
- <string name="adb_active_notification_message" msgid="4948470599328424059">"Toca para inhabilitar la depuración USB."</string>
+ <string name="adb_active_notification_message" msgid="4948470599328424059">"Toca para inhabilitar la depuración USB"</string>
<string name="adb_active_notification_message" product="tv" msgid="8470296818270110396">"Seleccionar para inhabilitar la depuración USB"</string>
<string name="taking_remote_bugreport_notification_title" msgid="6742483073875060934">"Creando informe de errores…"</string>
<string name="share_remote_bugreport_notification_title" msgid="4987095013583691873">"¿Compartir informe de errores?"</string>
@@ -1769,6 +1769,8 @@
<string name="etws_primary_default_message_tsunami" msgid="1887685943498368548">"Aléjate inmediatamente de las zonas costeras y situadas junto a un río para dirigirte hacia un lugar más seguro, por ejemplo, un terreno elevado."</string>
<string name="etws_primary_default_message_earthquake_and_tsunami" msgid="998797956848445862">"Mantén la calma y busca refugio en algún lugar cercano."</string>
<string name="etws_primary_default_message_test" msgid="2709597093560037455">"Prueba de mensajes de emergencia"</string>
+ <!-- no translation found for notification_reply_button_accessibility (3621714652387814344) -->
+ <skip />
<string name="etws_primary_default_message_others" msgid="6293148756130398971"></string>
<string name="mmcc_authentication_reject" msgid="7729819349669603406">"SIM no compatible"</string>
<string name="mmcc_imsi_unknown_in_hlr" msgid="6321202257374418726">"SIM no proporcionada"</string>
diff --git a/core/res/res/values-et/strings.xml b/core/res/res/values-et/strings.xml
index 4ff5a6b..bd05d64 100644
--- a/core/res/res/values-et/strings.xml
+++ b/core/res/res/values-et/strings.xml
@@ -1769,6 +1769,8 @@
<string name="etws_primary_default_message_tsunami" msgid="1887685943498368548">"Evakueeruge ranniku ja jõekallaste piirkondadest viivitamatult ohutusse kohta, näiteks kõrgematesse kohtadesse."</string>
<string name="etws_primary_default_message_earthquake_and_tsunami" msgid="998797956848445862">"Jääge rahulikuks ja otsige lähedusest peavarju."</string>
<string name="etws_primary_default_message_test" msgid="2709597093560037455">"Hädaabisõnumite test"</string>
+ <!-- no translation found for notification_reply_button_accessibility (3621714652387814344) -->
+ <skip />
<string name="etws_primary_default_message_others" msgid="6293148756130398971"></string>
<string name="mmcc_authentication_reject" msgid="7729819349669603406">"SIM-kaart pole lubatud"</string>
<string name="mmcc_imsi_unknown_in_hlr" msgid="6321202257374418726">"SIM-kaart on ettevalmistamata"</string>
diff --git a/core/res/res/values-eu/strings.xml b/core/res/res/values-eu/strings.xml
index ca369c4..36922d9 100644
--- a/core/res/res/values-eu/strings.xml
+++ b/core/res/res/values-eu/strings.xml
@@ -1770,6 +1770,8 @@
<string name="etws_primary_default_message_tsunami" msgid="1887685943498368548">"Ebakuatu kostaldeak eta ibaialdeak berehala eta joan toki seguru batera, adibidez, toki garai batera."</string>
<string name="etws_primary_default_message_earthquake_and_tsunami" msgid="998797956848445862">"Ez larritu eta bilatu babesleku bat inguruan."</string>
<string name="etws_primary_default_message_test" msgid="2709597093560037455">"Larrialdi-mezuen proba"</string>
+ <!-- no translation found for notification_reply_button_accessibility (3621714652387814344) -->
+ <skip />
<string name="etws_primary_default_message_others" msgid="6293148756130398971"></string>
<string name="mmcc_authentication_reject" msgid="7729819349669603406">"Ez da onartzen SIM txartela"</string>
<string name="mmcc_imsi_unknown_in_hlr" msgid="6321202257374418726">"Ez dago SIM txartelik"</string>
diff --git a/core/res/res/values-fa/strings.xml b/core/res/res/values-fa/strings.xml
index 9d4cb6d..46788fb 100644
--- a/core/res/res/values-fa/strings.xml
+++ b/core/res/res/values-fa/strings.xml
@@ -1769,6 +1769,8 @@
<string name="etws_primary_default_message_tsunami" msgid="1887685943498368548">"فوراً مناطق ساحلی و محدوده رودخانه را ترک کنید و به جایی امن، مثل ارتفاعات بروید."</string>
<string name="etws_primary_default_message_earthquake_and_tsunami" msgid="998797956848445862">"آرام باشید و پناهگاهی در این اطراف پیدا کنید."</string>
<string name="etws_primary_default_message_test" msgid="2709597093560037455">"آزمایش پیامهای اضطراری"</string>
+ <!-- no translation found for notification_reply_button_accessibility (3621714652387814344) -->
+ <skip />
<string name="etws_primary_default_message_others" msgid="6293148756130398971"></string>
<string name="mmcc_authentication_reject" msgid="7729819349669603406">"سیمکارت مجاز نیست"</string>
<string name="mmcc_imsi_unknown_in_hlr" msgid="6321202257374418726">"سیمکارت مجوز لازم را ندارد"</string>
diff --git a/core/res/res/values-fi/strings.xml b/core/res/res/values-fi/strings.xml
index ffa6d67..3459e39 100644
--- a/core/res/res/values-fi/strings.xml
+++ b/core/res/res/values-fi/strings.xml
@@ -1769,6 +1769,8 @@
<string name="etws_primary_default_message_tsunami" msgid="1887685943498368548">"Siirry heti rannikkoalueilta ja jokien varsilta korkeampiin tai muuten turvallisempiin paikkoihin."</string>
<string name="etws_primary_default_message_earthquake_and_tsunami" msgid="998797956848445862">"Pysy rauhallisena ja hakeudu lähimpään suojapaikkaan."</string>
<string name="etws_primary_default_message_test" msgid="2709597093560037455">"Hätäilmoitustesti"</string>
+ <!-- no translation found for notification_reply_button_accessibility (3621714652387814344) -->
+ <skip />
<string name="etws_primary_default_message_others" msgid="6293148756130398971"></string>
<string name="mmcc_authentication_reject" msgid="7729819349669603406">"SIM-kortti estetty"</string>
<string name="mmcc_imsi_unknown_in_hlr" msgid="6321202257374418726">"SIM-kortti ei käyttäjien hallinnassa"</string>
diff --git a/core/res/res/values-fr-rCA/strings.xml b/core/res/res/values-fr-rCA/strings.xml
index d4bac7c..a39bc3f 100644
--- a/core/res/res/values-fr-rCA/strings.xml
+++ b/core/res/res/values-fr-rCA/strings.xml
@@ -1182,7 +1182,7 @@
<string name="usb_notification_message" msgid="3370903770828407960">"Touchez pour afficher plus d\'options."</string>
<string name="usb_unsupported_audio_accessory_title" msgid="2256529893240208458">"Accessoire audio non pris en charge"</string>
<string name="usb_unsupported_audio_accessory_message" msgid="7811865061127547035">"Touchez l\'écran pour obtenir plus d\'information"</string>
- <string name="adb_active_notification_title" msgid="6729044778949189918">"Débogage USB connecté"</string>
+ <string name="adb_active_notification_title" msgid="6729044778949189918">"Débogage USB activé"</string>
<string name="adb_active_notification_message" msgid="4948470599328424059">"Touchez pour désactiver le débogage USB."</string>
<string name="adb_active_notification_message" product="tv" msgid="8470296818270110396">"Sélectionnez cette option pour désactiver le débogage USB."</string>
<string name="taking_remote_bugreport_notification_title" msgid="6742483073875060934">"Création d\'un rapport de bogue en cours..."</string>
@@ -1769,6 +1769,8 @@
<string name="etws_primary_default_message_tsunami" msgid="1887685943498368548">"Évacuez immédiatement les zones côtières et les rives des fleuves, et réfugiez-vous dans un endroit plus sécuritaire, comme un terrain surélevé."</string>
<string name="etws_primary_default_message_earthquake_and_tsunami" msgid="998797956848445862">"Restez calme et cherchez un abri à proximité."</string>
<string name="etws_primary_default_message_test" msgid="2709597093560037455">"Test de messages d\'urgence"</string>
+ <!-- no translation found for notification_reply_button_accessibility (3621714652387814344) -->
+ <skip />
<string name="etws_primary_default_message_others" msgid="6293148756130398971"></string>
<string name="mmcc_authentication_reject" msgid="7729819349669603406">"Carte SIM non autorisée"</string>
<string name="mmcc_imsi_unknown_in_hlr" msgid="6321202257374418726">"Carte SIM non configurée"</string>
diff --git a/core/res/res/values-fr/strings.xml b/core/res/res/values-fr/strings.xml
index f1e693d..7d27a5b 100644
--- a/core/res/res/values-fr/strings.xml
+++ b/core/res/res/values-fr/strings.xml
@@ -1769,6 +1769,8 @@
<string name="etws_primary_default_message_tsunami" msgid="1887685943498368548">"Évacuez immédiatement les zones côtières et les berges des fleuves, et réfugiez-vous dans un endroit plus sûr, comme un terrain surélevé."</string>
<string name="etws_primary_default_message_earthquake_and_tsunami" msgid="998797956848445862">"Restez calme et cherchez un abri à proximité."</string>
<string name="etws_primary_default_message_test" msgid="2709597093560037455">"Test de messages d\'urgence"</string>
+ <!-- no translation found for notification_reply_button_accessibility (3621714652387814344) -->
+ <skip />
<string name="etws_primary_default_message_others" msgid="6293148756130398971"></string>
<string name="mmcc_authentication_reject" msgid="7729819349669603406">"Carte SIM non autorisée"</string>
<string name="mmcc_imsi_unknown_in_hlr" msgid="6321202257374418726">"Carte SIM non configurée"</string>
diff --git a/core/res/res/values-gl/strings.xml b/core/res/res/values-gl/strings.xml
index c45b7a9..09104db 100644
--- a/core/res/res/values-gl/strings.xml
+++ b/core/res/res/values-gl/strings.xml
@@ -1770,6 +1770,8 @@
<string name="etws_primary_default_message_tsunami" msgid="1887685943498368548">"Abandona de inmediato rexións costeiras e situadas na beira de ríos para dirixirte a un lugar máis seguro, como un terreo elevado."</string>
<string name="etws_primary_default_message_earthquake_and_tsunami" msgid="998797956848445862">"Mantén a calma e busca refuxio cerca."</string>
<string name="etws_primary_default_message_test" msgid="2709597093560037455">"Proba de mensaxes de emerxencia"</string>
+ <!-- no translation found for notification_reply_button_accessibility (3621714652387814344) -->
+ <skip />
<string name="etws_primary_default_message_others" msgid="6293148756130398971"></string>
<string name="mmcc_authentication_reject" msgid="7729819349669603406">"Non se admite a tarxeta SIM"</string>
<string name="mmcc_imsi_unknown_in_hlr" msgid="6321202257374418726">"Non se introduciu ningunha tarxeta SIM"</string>
diff --git a/core/res/res/values-gu/strings.xml b/core/res/res/values-gu/strings.xml
index bd4789a..4352845 100644
--- a/core/res/res/values-gu/strings.xml
+++ b/core/res/res/values-gu/strings.xml
@@ -1770,6 +1770,8 @@
<string name="etws_primary_default_message_tsunami" msgid="1887685943498368548">"દરિયાકિનારાના પ્રદેશો તથા નદીકાંઠાના વિસ્તારો ખાલી કરીને તાત્કાલિક સુરક્ષિત ઊંચા સ્થાન પર જાઓ."</string>
<string name="etws_primary_default_message_earthquake_and_tsunami" msgid="998797956848445862">"શાંત રહો અને નજીકમાં આશ્રય લો."</string>
<string name="etws_primary_default_message_test" msgid="2709597093560037455">"કટોકટી સંદેશાઓનું પરીક્ષણ"</string>
+ <!-- no translation found for notification_reply_button_accessibility (3621714652387814344) -->
+ <skip />
<string name="etws_primary_default_message_others" msgid="6293148756130398971"></string>
<string name="mmcc_authentication_reject" msgid="7729819349669603406">"SIM મંજૂર નથી"</string>
<string name="mmcc_imsi_unknown_in_hlr" msgid="6321202257374418726">"SIMની જોગવાઈ કરી નથી"</string>
diff --git a/core/res/res/values-hi/strings.xml b/core/res/res/values-hi/strings.xml
index 7baa83b..391ad9f 100644
--- a/core/res/res/values-hi/strings.xml
+++ b/core/res/res/values-hi/strings.xml
@@ -119,7 +119,7 @@
<string name="roamingTextSearching" msgid="8360141885972279963">"सेवा खोज रहा है"</string>
<string name="wfcRegErrorTitle" msgid="2301376280632110664">"वाई-फ़ाई कॉलिंग"</string>
<string-array name="wfcOperatorErrorAlertMessages">
- <item msgid="3910386316304772394">"वाई-फ़ाई से कॉल करने और संदेश भेजने के लिए, सबसे पहले अपने वाहक से इस सेवा को सेट करने के लिए कहें. उसके बाद सेटिंग से वाई-फ़ाई कॉलिंग को दोबारा चालू करें. (गड़बड़ी कोड: <xliff:g id="CODE">%1$s</xliff:g>)"</item>
+ <item msgid="3910386316304772394">"वाई-फ़ाई से कॉल करने और संदेश भेजने के लिए, सबसे पहले अपने वाहक से इस सेवा को सेट अप करने के लिए कहें. उसके बाद सेटिंग से वाई-फ़ाई कॉलिंग को दोबारा चालू करें. (गड़बड़ी कोड: <xliff:g id="CODE">%1$s</xliff:g>)"</item>
</string-array>
<string-array name="wfcOperatorErrorNotificationMessages">
<item msgid="6177300162212449033">"अपने वाहक के साथ पंजीकृत करें"</item>
@@ -1769,6 +1769,8 @@
<string name="etws_primary_default_message_tsunami" msgid="1887685943498368548">"तटीय क्षेत्रों और नदी के किनारे वाले क्षेत्रों को जल्द से जल्द खाली करके किसी सुरक्षित ऊंची जगह पर चले जाएं."</string>
<string name="etws_primary_default_message_earthquake_and_tsunami" msgid="998797956848445862">"शांत रहें और आस-पास आश्रय खोजें."</string>
<string name="etws_primary_default_message_test" msgid="2709597093560037455">"आपातकालीन संदेश परीक्षण"</string>
+ <!-- no translation found for notification_reply_button_accessibility (3621714652387814344) -->
+ <skip />
<string name="etws_primary_default_message_others" msgid="6293148756130398971"></string>
<string name="mmcc_authentication_reject" msgid="7729819349669603406">"SIM की अनुमति नहीं है"</string>
<string name="mmcc_imsi_unknown_in_hlr" msgid="6321202257374418726">"SIM का प्रावधान नहीं किया गया है"</string>
diff --git a/core/res/res/values-hr/strings.xml b/core/res/res/values-hr/strings.xml
index 92d4651..f43c600 100644
--- a/core/res/res/values-hr/strings.xml
+++ b/core/res/res/values-hr/strings.xml
@@ -1803,6 +1803,8 @@
<string name="etws_primary_default_message_tsunami" msgid="1887685943498368548">"Odmah se evakuirajte s obalnih područja i područja uz rijeku na sigurnije mjesto, primjerice povišeno područje."</string>
<string name="etws_primary_default_message_earthquake_and_tsunami" msgid="998797956848445862">"Ostanite mirni i potražite sklonište u blizini."</string>
<string name="etws_primary_default_message_test" msgid="2709597093560037455">"Test hitnih poruka"</string>
+ <!-- no translation found for notification_reply_button_accessibility (3621714652387814344) -->
+ <skip />
<string name="etws_primary_default_message_others" msgid="6293148756130398971"></string>
<string name="mmcc_authentication_reject" msgid="7729819349669603406">"SIM nije dopušten"</string>
<string name="mmcc_imsi_unknown_in_hlr" msgid="6321202257374418726">"Ne pruža se usluga za SIM"</string>
diff --git a/core/res/res/values-hu/strings.xml b/core/res/res/values-hu/strings.xml
index 107581c..285babe 100644
--- a/core/res/res/values-hu/strings.xml
+++ b/core/res/res/values-hu/strings.xml
@@ -1769,6 +1769,8 @@
<string name="etws_primary_default_message_tsunami" msgid="1887685943498368548">"Azonnal meneküljön biztonságosabb helyre a tengerparti, illetve folyóparti területekről, például valamilyen magaslatra."</string>
<string name="etws_primary_default_message_earthquake_and_tsunami" msgid="998797956848445862">"Őrizze meg nyugalmát, és keressen menedéket a közelben."</string>
<string name="etws_primary_default_message_test" msgid="2709597093560037455">"Vészhelyzetben küldött üzenetek tesztelése"</string>
+ <!-- no translation found for notification_reply_button_accessibility (3621714652387814344) -->
+ <skip />
<string name="etws_primary_default_message_others" msgid="6293148756130398971"></string>
<string name="mmcc_authentication_reject" msgid="7729819349669603406">"A SIM-kártya nem engedélyezett"</string>
<string name="mmcc_imsi_unknown_in_hlr" msgid="6321202257374418726">"Nem engedélyezett SIM-kártya"</string>
diff --git a/core/res/res/values-hy/strings.xml b/core/res/res/values-hy/strings.xml
index 9c5b1e0..02da2cc 100644
--- a/core/res/res/values-hy/strings.xml
+++ b/core/res/res/values-hy/strings.xml
@@ -1769,6 +1769,8 @@
<string name="etws_primary_default_message_tsunami" msgid="1887685943498368548">"Ափամերձ և գետափնյա տարածքներից անմիջապես էվակուացվեք դեպի ավելի ապահով վայրեր (օրինակ՝ բարձրադիր գոտիներ):"</string>
<string name="etws_primary_default_message_earthquake_and_tsunami" msgid="998797956848445862">"Պահպանեք հանգստությունը և մոտակայքում ապաստարան փնտրեք:"</string>
<string name="etws_primary_default_message_test" msgid="2709597093560037455">"Արտակարգ իրավիճակների հաղորդագրությունների թեստ"</string>
+ <!-- no translation found for notification_reply_button_accessibility (3621714652387814344) -->
+ <skip />
<string name="etws_primary_default_message_others" msgid="6293148756130398971"></string>
<string name="mmcc_authentication_reject" msgid="7729819349669603406">"SIM քարտի օգտագործումն արգելված է"</string>
<string name="mmcc_imsi_unknown_in_hlr" msgid="6321202257374418726">"SIM քարտը նախապատրաստված չէ"</string>
diff --git a/core/res/res/values-in/strings.xml b/core/res/res/values-in/strings.xml
index f6fcef7..15ea8d2 100644
--- a/core/res/res/values-in/strings.xml
+++ b/core/res/res/values-in/strings.xml
@@ -1769,6 +1769,8 @@
<string name="etws_primary_default_message_tsunami" msgid="1887685943498368548">"Evakuasi segera dari daerah pesisir dan area tepi sungai ke tempat yang lebih aman seperti dataran tinggi."</string>
<string name="etws_primary_default_message_earthquake_and_tsunami" msgid="998797956848445862">"Tetap tenang dan cari tempat berlindung terdekat."</string>
<string name="etws_primary_default_message_test" msgid="2709597093560037455">"Tes pesan darurat"</string>
+ <!-- no translation found for notification_reply_button_accessibility (3621714652387814344) -->
+ <skip />
<string name="etws_primary_default_message_others" msgid="6293148756130398971"></string>
<string name="mmcc_authentication_reject" msgid="7729819349669603406">"SIM tidak diizinkan"</string>
<string name="mmcc_imsi_unknown_in_hlr" msgid="6321202257374418726">"SIM tidak di-provisioning"</string>
diff --git a/core/res/res/values-is/strings.xml b/core/res/res/values-is/strings.xml
index 2c0fb3b..2e0fa2e 100644
--- a/core/res/res/values-is/strings.xml
+++ b/core/res/res/values-is/strings.xml
@@ -1770,6 +1770,8 @@
<string name="etws_primary_default_message_tsunami" msgid="1887685943498368548">"Fólk sem statt er á strandsvæðum eða við ár á tafarlaust að leita öryggis á svæðum sem eru í meiri hæð yfir sjávarmáli."</string>
<string name="etws_primary_default_message_earthquake_and_tsunami" msgid="998797956848445862">"Sýndu stillingu og leitaðu skjóls."</string>
<string name="etws_primary_default_message_test" msgid="2709597093560037455">"Prófun neyðarskilaboða"</string>
+ <!-- no translation found for notification_reply_button_accessibility (3621714652387814344) -->
+ <skip />
<string name="etws_primary_default_message_others" msgid="6293148756130398971"></string>
<string name="mmcc_authentication_reject" msgid="7729819349669603406">"SIM-kort er ekki leyft"</string>
<string name="mmcc_imsi_unknown_in_hlr" msgid="6321202257374418726">"SIM-korti ekki úthlutað"</string>
diff --git a/core/res/res/values-it/strings.xml b/core/res/res/values-it/strings.xml
index f14b65b..5dcd3aaf 100644
--- a/core/res/res/values-it/strings.xml
+++ b/core/res/res/values-it/strings.xml
@@ -1769,6 +1769,8 @@
<string name="etws_primary_default_message_tsunami" msgid="1887685943498368548">"Evacuare immediatamente le zone costiere e in riva ai fiumi e recarsi in un luogo più sicuro, ad esempio un\'altura."</string>
<string name="etws_primary_default_message_earthquake_and_tsunami" msgid="998797956848445862">"Mantieni la calma e cerca riparo nelle vicinanze."</string>
<string name="etws_primary_default_message_test" msgid="2709597093560037455">"Testo messaggi di emergenza"</string>
+ <!-- no translation found for notification_reply_button_accessibility (3621714652387814344) -->
+ <skip />
<string name="etws_primary_default_message_others" msgid="6293148756130398971"></string>
<string name="mmcc_authentication_reject" msgid="7729819349669603406">"Scheda SIM non consentita"</string>
<string name="mmcc_imsi_unknown_in_hlr" msgid="6321202257374418726">"Scheda SIM non predisposta"</string>
diff --git a/core/res/res/values-iw/strings.xml b/core/res/res/values-iw/strings.xml
index 5a3de37..938b03a 100644
--- a/core/res/res/values-iw/strings.xml
+++ b/core/res/res/values-iw/strings.xml
@@ -1837,6 +1837,8 @@
<string name="etws_primary_default_message_tsunami" msgid="1887685943498368548">"יש להתפנות מיידית מאזורים הסמוכים לחופים ולנהרות למקום בטוח יותר, כגון שטח גבוה יותר."</string>
<string name="etws_primary_default_message_earthquake_and_tsunami" msgid="998797956848445862">"הישאר רגוע וחפש מחסה בקרבת מקום."</string>
<string name="etws_primary_default_message_test" msgid="2709597093560037455">"בדיקה של הודעות חירום"</string>
+ <!-- no translation found for notification_reply_button_accessibility (3621714652387814344) -->
+ <skip />
<string name="etws_primary_default_message_others" msgid="6293148756130398971"></string>
<string name="mmcc_authentication_reject" msgid="7729819349669603406">"כרטיס ה-SIM לא מורשה"</string>
<string name="mmcc_imsi_unknown_in_hlr" msgid="6321202257374418726">"כרטיס ה-SIM לא מזוהה"</string>
diff --git a/core/res/res/values-ja/strings.xml b/core/res/res/values-ja/strings.xml
index b237439..c34e09e 100644
--- a/core/res/res/values-ja/strings.xml
+++ b/core/res/res/values-ja/strings.xml
@@ -119,7 +119,7 @@
<string name="roamingTextSearching" msgid="8360141885972279963">"サービスを検索中"</string>
<string name="wfcRegErrorTitle" msgid="2301376280632110664">"Wi-Fi通話"</string>
<string-array name="wfcOperatorErrorAlertMessages">
- <item msgid="3910386316304772394">"Wi-Fi 経由で音声通話の発信やメッセージの送信を行うには、携帯通信会社に Wi-Fi サービスを申し込んだ上で、設定画面で Wi-Fi 発信を再度 ON にしてください(エラーコード: <xliff:g id="CODE">%1$s</xliff:g>)"</item>
+ <item msgid="3910386316304772394">"Wi-Fi 経由で音声通話の発信やメッセージの送信を行うには、携帯通信会社に Wi-Fi サービスを申し込んだ上で、設定画面で Wi-Fi 通話を再度 ON にしてください(エラーコード: <xliff:g id="CODE">%1$s</xliff:g>)"</item>
</string-array>
<string-array name="wfcOperatorErrorNotificationMessages">
<item msgid="6177300162212449033">"携帯通信会社に登録してください"</item>
@@ -1769,6 +1769,8 @@
<string name="etws_primary_default_message_tsunami" msgid="1887685943498368548">"沿岸部の方はただちに高台へ避難してください"</string>
<string name="etws_primary_default_message_earthquake_and_tsunami" msgid="998797956848445862">"強い揺れと津波に注意してください"</string>
<string name="etws_primary_default_message_test" msgid="2709597093560037455">"テスト用緊急速報メール"</string>
+ <!-- no translation found for notification_reply_button_accessibility (3621714652387814344) -->
+ <skip />
<string name="etws_primary_default_message_others" msgid="6293148756130398971"></string>
<string name="mmcc_authentication_reject" msgid="7729819349669603406">"SIM 使用不可"</string>
<string name="mmcc_imsi_unknown_in_hlr" msgid="6321202257374418726">"SIM には対応していません"</string>
diff --git a/core/res/res/values-ka/strings.xml b/core/res/res/values-ka/strings.xml
index af653bd..6bd2ce1 100644
--- a/core/res/res/values-ka/strings.xml
+++ b/core/res/res/values-ka/strings.xml
@@ -119,7 +119,7 @@
<string name="roamingTextSearching" msgid="8360141885972279963">"სერვისის ძიება"</string>
<string name="wfcRegErrorTitle" msgid="2301376280632110664">"დარეკვა Wi-Fi-ს მეშვეობით"</string>
<string-array name="wfcOperatorErrorAlertMessages">
- <item msgid="3910386316304772394">"Wi-Fi-ს მეშვეობით ზარების განსახორციელებლად ან შეტყობინებების გასაგზავნად, პირველ რიგში, ამ სერვისის გააქტიურება თქვენს ოპერატორს უნდა თხოვოთ. შემდეგ კი ხელახლა ჩართეთ Wi-Fi დარეკვა პარამეტრებიდან.. (შეცდომის კოდი: <xliff:g id="CODE">%1$s</xliff:g>)"</item>
+ <item msgid="3910386316304772394">"Wi-Fi-ს მეშვეობით ზარების განსახორციელებლად ან შეტყობინებების გასაგზავნად, პირველ რიგში, ამ სერვისის გააქტიურება თქვენს ოპერატორს უნდა თხოვოთ. შემდეგ კი ხელახლა ჩართეთ Wi-Fi დარეკვა პარამეტრებიდან. (შეცდომის კოდი: <xliff:g id="CODE">%1$s</xliff:g>)"</item>
</string-array>
<string-array name="wfcOperatorErrorNotificationMessages">
<item msgid="6177300162212449033">"დაარეგისტრირეთ თქვენი ოპერატორი"</item>
@@ -1769,6 +1769,8 @@
<string name="etws_primary_default_message_tsunami" msgid="1887685943498368548">"დაუყოვნებლივ გადაინაცვლეთ სანაპირო რეგიონებიდან და მდინარისპირა ტერიტორიებიდან უსაფრთხო ადგილზე (მაგალითად, შემაღლებულ ადგილზე)."</string>
<string name="etws_primary_default_message_earthquake_and_tsunami" msgid="998797956848445862">"შეინარჩუნეთ სიმშვიდე და იპოვეთ ახლომდებარე თავშესაფარი."</string>
<string name="etws_primary_default_message_test" msgid="2709597093560037455">"სატესტო საგანგებო შეტყობინება"</string>
+ <!-- no translation found for notification_reply_button_accessibility (3621714652387814344) -->
+ <skip />
<string name="etws_primary_default_message_others" msgid="6293148756130398971"></string>
<string name="mmcc_authentication_reject" msgid="7729819349669603406">"SIM ბარათი დაუშვებელია"</string>
<string name="mmcc_imsi_unknown_in_hlr" msgid="6321202257374418726">"SIM ბარათი უზრუნველყოფილი არ არის"</string>
diff --git a/core/res/res/values-kk/strings.xml b/core/res/res/values-kk/strings.xml
index e185552..70801fa 100644
--- a/core/res/res/values-kk/strings.xml
+++ b/core/res/res/values-kk/strings.xml
@@ -1770,6 +1770,8 @@
<string name="etws_primary_default_message_tsunami" msgid="1887685943498368548">"Жағалау аймақтан биіктеу қауіпсіз жерге дереу көшіңіз."</string>
<string name="etws_primary_default_message_earthquake_and_tsunami" msgid="998797956848445862">"Сабыр сақтап, жақын жерден баспана іздеңіз."</string>
<string name="etws_primary_default_message_test" msgid="2709597093560037455">"Төтенше хабарлар сынағы"</string>
+ <!-- no translation found for notification_reply_button_accessibility (3621714652387814344) -->
+ <skip />
<string name="etws_primary_default_message_others" msgid="6293148756130398971"></string>
<string name="mmcc_authentication_reject" msgid="7729819349669603406">"SIM картасына рұқсат етілмеген"</string>
<string name="mmcc_imsi_unknown_in_hlr" msgid="6321202257374418726">"SIM картасы белсендірілмеген"</string>
diff --git a/core/res/res/values-km/strings.xml b/core/res/res/values-km/strings.xml
index 3843daa..76f0602 100644
--- a/core/res/res/values-km/strings.xml
+++ b/core/res/res/values-km/strings.xml
@@ -119,7 +119,7 @@
<string name="roamingTextSearching" msgid="8360141885972279963">"ស្វែងរកសេវាកម្ម"</string>
<string name="wfcRegErrorTitle" msgid="2301376280632110664">"ការហៅតាម Wi-Fi"</string>
<string-array name="wfcOperatorErrorAlertMessages">
- <item msgid="3910386316304772394">"ដើម្បីធ្វើការហៅ និងផ្ញើសារតាម Wi-Fi អ្នកត្រូវស្នើឲ្យក្រុមហ៊ុនបម្រើសេវាទូរសព្ទរបស់អ្នកដំឡើងសេវាកម្មនេះជាមុនសិន។ បន្ទាប់មកបើកការហៅតាម Wi-Fi ម្តងទៀតនៅក្នុងការកំណត់។ (លេខកូដបញ្ហា៖ <xliff:g id="CODE">%1$s</xliff:g>)"</item>
+ <item msgid="3910386316304772394">"ដើម្បីហៅទូរសព្ទ និងផ្ញើសារតាម Wi-Fi អ្នកត្រូវស្នើឲ្យក្រុមហ៊ុនបម្រើសេវាទូរសព្ទរបស់អ្នកដំឡើងសេវាកម្មនេះជាមុនសិន។ បន្ទាប់មកបើកការហៅតាម Wi-Fi ម្តងទៀតនៅក្នុងការកំណត់។ (លេខកូដបញ្ហា៖ <xliff:g id="CODE">%1$s</xliff:g>)"</item>
</string-array>
<string-array name="wfcOperatorErrorNotificationMessages">
<item msgid="6177300162212449033">"ចុះឈ្មោះជាមួយក្រុមហ៊ុនរបស់អ្នក"</item>
@@ -1771,6 +1771,8 @@
<string name="etws_primary_default_message_tsunami" msgid="1887685943498368548">"ភៀសខ្លួនជាបន្ទាន់ពីតំបន់ឆ្នេរ និងតំបន់តាមមាត់ទន្លេទៅកាន់កន្លែងដែលមានសុវត្ថិភាពជាងនេះ ដូចជាទីទួលណាមួយ។"</string>
<string name="etws_primary_default_message_earthquake_and_tsunami" msgid="998797956848445862">"សូមរក្សាភាពស្ងប់ស្ងាត់ ហើយស្វែងរកជម្រកសុវត្ថិភាពដែលនៅជិត។"</string>
<string name="etws_primary_default_message_test" msgid="2709597093560037455">"សារសាកល្បងពេលមានអាសន្ន"</string>
+ <!-- no translation found for notification_reply_button_accessibility (3621714652387814344) -->
+ <skip />
<string name="etws_primary_default_message_others" msgid="6293148756130398971"></string>
<string name="mmcc_authentication_reject" msgid="7729819349669603406">"មិនអនុញ្ញាតសីុមកាតទេ"</string>
<string name="mmcc_imsi_unknown_in_hlr" msgid="6321202257374418726">"សីុមមិនត្រូវបានផ្តល់ជូនទេ"</string>
diff --git a/core/res/res/values-kn/strings.xml b/core/res/res/values-kn/strings.xml
index 8d3db20..fad951e 100644
--- a/core/res/res/values-kn/strings.xml
+++ b/core/res/res/values-kn/strings.xml
@@ -1770,6 +1770,8 @@
<string name="etws_primary_default_message_tsunami" msgid="1887685943498368548">"ಕರಾವಳಿ ಪ್ರದೇಶಗಳು ಮತ್ತು ನದಿ ತೀರಗಳಿಂದ ತಕ್ಷಣವೇ ಎತ್ತರದ ಪ್ರದೇಶಗಳಂತಹ ಸುರಕ್ಷಿತ ಸ್ಥಳಕ್ಕೆ ಹೋಗಿ."</string>
<string name="etws_primary_default_message_earthquake_and_tsunami" msgid="998797956848445862">"ಶಾಂತರಾಗಿರಿ ಮತ್ತು ಸಮೀಪದಲ್ಲೆಲ್ಲಾದರೂ ಆಶ್ರಯ ಪಡೆದುಕೊಳ್ಳಿ."</string>
<string name="etws_primary_default_message_test" msgid="2709597093560037455">"ತುರ್ತು ಸಂದೇಶಗಳ ಪರೀಕ್ಷೆ"</string>
+ <!-- no translation found for notification_reply_button_accessibility (3621714652387814344) -->
+ <skip />
<string name="etws_primary_default_message_others" msgid="6293148756130398971"></string>
<string name="mmcc_authentication_reject" msgid="7729819349669603406">"ಸಿಮ್ಗೆ ಅನುಮತಿಯಿಲ್ಲ"</string>
<string name="mmcc_imsi_unknown_in_hlr" msgid="6321202257374418726">"ಸಿಮ್ ಸಿದ್ಧವಾಗಿಲ್ಲ"</string>
diff --git a/core/res/res/values-ko/strings.xml b/core/res/res/values-ko/strings.xml
index 497cfe9..9685e83 100644
--- a/core/res/res/values-ko/strings.xml
+++ b/core/res/res/values-ko/strings.xml
@@ -1769,6 +1769,8 @@
<string name="etws_primary_default_message_tsunami" msgid="1887685943498368548">"즉시 해안 지대나 강가에서 떨어져 고지대 등 안전한 장소로 대피하세요."</string>
<string name="etws_primary_default_message_earthquake_and_tsunami" msgid="998797956848445862">"침착하게 가까운 대피소를 찾으세요."</string>
<string name="etws_primary_default_message_test" msgid="2709597093560037455">"긴급 메시지 테스트"</string>
+ <!-- no translation found for notification_reply_button_accessibility (3621714652387814344) -->
+ <skip />
<string name="etws_primary_default_message_others" msgid="6293148756130398971"></string>
<string name="mmcc_authentication_reject" msgid="7729819349669603406">"SIM이 허용되지 않음"</string>
<string name="mmcc_imsi_unknown_in_hlr" msgid="6321202257374418726">"SIM이 프로비저닝되지 않음"</string>
diff --git a/core/res/res/values-ky/strings.xml b/core/res/res/values-ky/strings.xml
index ea01218..b9e143c 100644
--- a/core/res/res/values-ky/strings.xml
+++ b/core/res/res/values-ky/strings.xml
@@ -1770,6 +1770,8 @@
<string name="etws_primary_default_message_tsunami" msgid="1887685943498368548">"Деңиз жана дарыя жээгинде жайгашкан аймактардан бийик тоо сыяктуу коопсуз жерге тезинен чыгып кетиңиз."</string>
<string name="etws_primary_default_message_earthquake_and_tsunami" msgid="998797956848445862">"Эс алып, жакын жерден калканч издеңиз."</string>
<string name="etws_primary_default_message_test" msgid="2709597093560037455">"Өзгөчө кырдаалда жөнөтүлүүчү билдирүүлөрдү сыноо"</string>
+ <!-- no translation found for notification_reply_button_accessibility (3621714652387814344) -->
+ <skip />
<string name="etws_primary_default_message_others" msgid="6293148756130398971"></string>
<string name="mmcc_authentication_reject" msgid="7729819349669603406">"SIM картаны колдонууга тыюу салынган"</string>
<string name="mmcc_imsi_unknown_in_hlr" msgid="6321202257374418726">"SIM карта таанылган жок"</string>
diff --git a/core/res/res/values-lo/strings.xml b/core/res/res/values-lo/strings.xml
index 9bdfd39..affd287 100644
--- a/core/res/res/values-lo/strings.xml
+++ b/core/res/res/values-lo/strings.xml
@@ -1769,6 +1769,8 @@
<string name="etws_primary_default_message_tsunami" msgid="1887685943498368548">"ອົບພະຍົບອອກຈາກເຂດຊາຍຝັ່ງທະເລ ແລະ ບໍລິເວນແມ່ນ້ຳໄປບ່ອນທີ່ປອດໄພກວ່າ ເຊັ່ນ: ບ່ອນສູງ ໂດຍທັນທີ."</string>
<string name="etws_primary_default_message_earthquake_and_tsunami" msgid="998797956848445862">"ໃຈເຢັນໆ ແລະ ຊອກຫາບ່ອນພັກຢູ່ໃກ້ໆ."</string>
<string name="etws_primary_default_message_test" msgid="2709597093560037455">"ທົດສອບຂໍ້ຄວາມສຸກເສີນ"</string>
+ <!-- no translation found for notification_reply_button_accessibility (3621714652387814344) -->
+ <skip />
<string name="etws_primary_default_message_others" msgid="6293148756130398971"></string>
<string name="mmcc_authentication_reject" msgid="7729819349669603406">"ບໍ່ອະນຸຍາດໃຫ້ໃຊ້ SIM"</string>
<string name="mmcc_imsi_unknown_in_hlr" msgid="6321202257374418726">"ບໍ່ມີການນຳໃຊ້ SIM"</string>
diff --git a/core/res/res/values-lt/strings.xml b/core/res/res/values-lt/strings.xml
index a6aa9c0..f10d025 100644
--- a/core/res/res/values-lt/strings.xml
+++ b/core/res/res/values-lt/strings.xml
@@ -1837,6 +1837,8 @@
<string name="etws_primary_default_message_tsunami" msgid="1887685943498368548">"Nedelsdami pasitraukite nuo pakrančių ir paupių. Eikite į saugią vietą, pvz., vietą, kuri yra aukštai."</string>
<string name="etws_primary_default_message_earthquake_and_tsunami" msgid="998797956848445862">"Nesijaudinkite ir ieškokite prieglobsčio netoliese."</string>
<string name="etws_primary_default_message_test" msgid="2709597093560037455">"Kritinės padėties pranešimo bandymas"</string>
+ <!-- no translation found for notification_reply_button_accessibility (3621714652387814344) -->
+ <skip />
<string name="etws_primary_default_message_others" msgid="6293148756130398971"></string>
<string name="mmcc_authentication_reject" msgid="7729819349669603406">"SIM kortelė neleidžiama"</string>
<string name="mmcc_imsi_unknown_in_hlr" msgid="6321202257374418726">"SIM kortelė neteikiama"</string>
diff --git a/core/res/res/values-lv/strings.xml b/core/res/res/values-lv/strings.xml
index d96ea068..c9e9e1f7 100644
--- a/core/res/res/values-lv/strings.xml
+++ b/core/res/res/values-lv/strings.xml
@@ -1803,6 +1803,8 @@
<string name="etws_primary_default_message_tsunami" msgid="1887685943498368548">"Nekavējoties pametiet piekrastes un upju zonas un dodieties uz drošākām (piemēram, augstākām) vietām."</string>
<string name="etws_primary_default_message_earthquake_and_tsunami" msgid="998797956848445862">"Saglabājiet mieru un meklējiet tuvumā patvērumu."</string>
<string name="etws_primary_default_message_test" msgid="2709597093560037455">"Ārkārtas ziņojuma pārbaude"</string>
+ <!-- no translation found for notification_reply_button_accessibility (3621714652387814344) -->
+ <skip />
<string name="etws_primary_default_message_others" msgid="6293148756130398971"></string>
<string name="mmcc_authentication_reject" msgid="7729819349669603406">"SIM karti nav atļauts izmantot"</string>
<string name="mmcc_imsi_unknown_in_hlr" msgid="6321202257374418726">"SIM karte netiek nodrošināta"</string>
diff --git a/core/res/res/values-mcc302-mnc370-bn/strings.xml b/core/res/res/values-mcc302-mnc370-bn/strings.xml
new file mode 100644
index 0000000..efd9b4b
--- /dev/null
+++ b/core/res/res/values-mcc302-mnc370-bn/strings.xml
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+/*
+** Copyright 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.
+*/
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string-array name="wfcSpnFormats">
+ <item msgid="5022384999749536798">"%s"</item>
+ <item msgid="8117276330682171665">"%s ওয়াই-ফাই"</item>
+ </string-array>
+</resources>
diff --git a/core/res/res/values-mcc302-mnc370-gu/strings.xml b/core/res/res/values-mcc302-mnc370-gu/strings.xml
new file mode 100644
index 0000000..b93949e
--- /dev/null
+++ b/core/res/res/values-mcc302-mnc370-gu/strings.xml
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+/*
+** Copyright 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.
+*/
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string-array name="wfcSpnFormats">
+ <item msgid="5022384999749536798">"%s"</item>
+ <item msgid="8117276330682171665">"%s Wi-Fi"</item>
+ </string-array>
+</resources>
diff --git a/core/res/res/values-mcc302-mnc370-kn/strings.xml b/core/res/res/values-mcc302-mnc370-kn/strings.xml
new file mode 100644
index 0000000..636eb01
--- /dev/null
+++ b/core/res/res/values-mcc302-mnc370-kn/strings.xml
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+/*
+** Copyright 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.
+*/
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string-array name="wfcSpnFormats">
+ <item msgid="5022384999749536798">"%s"</item>
+ <item msgid="8117276330682171665">"%s ವೈ-ಫೈ"</item>
+ </string-array>
+</resources>
diff --git a/core/res/res/values-mcc302-mnc370-ne/strings.xml b/core/res/res/values-mcc302-mnc370-ne/strings.xml
new file mode 100644
index 0000000..b93949e
--- /dev/null
+++ b/core/res/res/values-mcc302-mnc370-ne/strings.xml
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+/*
+** Copyright 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.
+*/
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string-array name="wfcSpnFormats">
+ <item msgid="5022384999749536798">"%s"</item>
+ <item msgid="8117276330682171665">"%s Wi-Fi"</item>
+ </string-array>
+</resources>
diff --git a/core/res/res/values-mcc302-mnc370-pa/strings.xml b/core/res/res/values-mcc302-mnc370-pa/strings.xml
new file mode 100644
index 0000000..b93949e
--- /dev/null
+++ b/core/res/res/values-mcc302-mnc370-pa/strings.xml
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+/*
+** Copyright 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.
+*/
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string-array name="wfcSpnFormats">
+ <item msgid="5022384999749536798">"%s"</item>
+ <item msgid="8117276330682171665">"%s Wi-Fi"</item>
+ </string-array>
+</resources>
diff --git a/core/res/res/values-mcc302-mnc370-ur/strings.xml b/core/res/res/values-mcc302-mnc370-ur/strings.xml
new file mode 100644
index 0000000..81d2888
--- /dev/null
+++ b/core/res/res/values-mcc302-mnc370-ur/strings.xml
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+/*
+** Copyright 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.
+*/
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string-array name="wfcSpnFormats">
+ <item msgid="5022384999749536798">"%s"</item>
+ <item msgid="8117276330682171665">"%s Wi-Fi"</item>
+ </string-array>
+</resources>
diff --git a/core/res/res/values-mcc302-mnc720-bn/strings.xml b/core/res/res/values-mcc302-mnc720-bn/strings.xml
new file mode 100644
index 0000000..543ec7a
--- /dev/null
+++ b/core/res/res/values-mcc302-mnc720-bn/strings.xml
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+/*
+** Copyright 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.
+*/
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string-array name="wfcSpnFormats">
+ <item msgid="2776657861851140021">"%s"</item>
+ <item msgid="5094669985484060934">"%s ওয়াই-ফাই"</item>
+ </string-array>
+</resources>
diff --git a/core/res/res/values-mcc302-mnc720-gu/strings.xml b/core/res/res/values-mcc302-mnc720-gu/strings.xml
new file mode 100644
index 0000000..9b2336d
--- /dev/null
+++ b/core/res/res/values-mcc302-mnc720-gu/strings.xml
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+/*
+** Copyright 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.
+*/
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string-array name="wfcSpnFormats">
+ <item msgid="2776657861851140021">"%s"</item>
+ <item msgid="5094669985484060934">"%s Wi-Fi"</item>
+ </string-array>
+</resources>
diff --git a/core/res/res/values-mcc302-mnc720-kn/strings.xml b/core/res/res/values-mcc302-mnc720-kn/strings.xml
new file mode 100644
index 0000000..6438ffb
--- /dev/null
+++ b/core/res/res/values-mcc302-mnc720-kn/strings.xml
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+/*
+** Copyright 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.
+*/
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string-array name="wfcSpnFormats">
+ <item msgid="2776657861851140021">"%s"</item>
+ <item msgid="5094669985484060934">"%s ವೈ-ಫೈ"</item>
+ </string-array>
+</resources>
diff --git a/core/res/res/values-mcc302-mnc720-ne/strings.xml b/core/res/res/values-mcc302-mnc720-ne/strings.xml
new file mode 100644
index 0000000..9b2336d
--- /dev/null
+++ b/core/res/res/values-mcc302-mnc720-ne/strings.xml
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+/*
+** Copyright 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.
+*/
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string-array name="wfcSpnFormats">
+ <item msgid="2776657861851140021">"%s"</item>
+ <item msgid="5094669985484060934">"%s Wi-Fi"</item>
+ </string-array>
+</resources>
diff --git a/core/res/res/values-mcc302-mnc720-pa/strings.xml b/core/res/res/values-mcc302-mnc720-pa/strings.xml
new file mode 100644
index 0000000..9b2336d
--- /dev/null
+++ b/core/res/res/values-mcc302-mnc720-pa/strings.xml
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+/*
+** Copyright 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.
+*/
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string-array name="wfcSpnFormats">
+ <item msgid="2776657861851140021">"%s"</item>
+ <item msgid="5094669985484060934">"%s Wi-Fi"</item>
+ </string-array>
+</resources>
diff --git a/core/res/res/values-mcc302-mnc720-ur/strings.xml b/core/res/res/values-mcc302-mnc720-ur/strings.xml
new file mode 100644
index 0000000..566f852
--- /dev/null
+++ b/core/res/res/values-mcc302-mnc720-ur/strings.xml
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+/*
+** Copyright 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.
+*/
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string-array name="wfcSpnFormats">
+ <item msgid="2776657861851140021">"%s"</item>
+ <item msgid="5094669985484060934">"%s Wi-Fi"</item>
+ </string-array>
+</resources>
diff --git a/core/res/res/values-mk/strings.xml b/core/res/res/values-mk/strings.xml
index 9ffc7ad..6b68427 100644
--- a/core/res/res/values-mk/strings.xml
+++ b/core/res/res/values-mk/strings.xml
@@ -1772,6 +1772,8 @@
<string name="etws_primary_default_message_tsunami" msgid="1887685943498368548">"Итна евакуација од крајбрежните региони и областите покрај реки на побезбедно место, како на пр., терени на повисока надморска височина."</string>
<string name="etws_primary_default_message_earthquake_and_tsunami" msgid="998797956848445862">"Бидете смирени и побарајте засолниште во близина."</string>
<string name="etws_primary_default_message_test" msgid="2709597093560037455">"Тестирање пораки за итни случаи"</string>
+ <!-- no translation found for notification_reply_button_accessibility (3621714652387814344) -->
+ <skip />
<string name="etws_primary_default_message_others" msgid="6293148756130398971"></string>
<string name="mmcc_authentication_reject" msgid="7729819349669603406">"Не е дозволена SIM-картичка"</string>
<string name="mmcc_imsi_unknown_in_hlr" msgid="6321202257374418726">"Не е обезбедена SIM-картичка"</string>
diff --git a/core/res/res/values-ml/strings.xml b/core/res/res/values-ml/strings.xml
index cc19ec6..344f9f2 100644
--- a/core/res/res/values-ml/strings.xml
+++ b/core/res/res/values-ml/strings.xml
@@ -1770,6 +1770,8 @@
<string name="etws_primary_default_message_tsunami" msgid="1887685943498368548">"തീരപ്രദേശങ്ങളിൽ നിന്നും നദിക്കരകളിൽ നിന്നും ആളുകളെ ഉടനടി ഒഴിപ്പിച്ച് ഉയർന്ന ഭൂമിയിൽ എത്തിക്കുക."</string>
<string name="etws_primary_default_message_earthquake_and_tsunami" msgid="998797956848445862">"പരിഭ്രമിക്കാതിരിക്കുക, അടുത്തുള്ള അഭയകേന്ദ്രം തേടുക."</string>
<string name="etws_primary_default_message_test" msgid="2709597093560037455">"അടിയന്തര സന്ദേശ ടെസ്റ്റ്"</string>
+ <!-- no translation found for notification_reply_button_accessibility (3621714652387814344) -->
+ <skip />
<string name="etws_primary_default_message_others" msgid="6293148756130398971"></string>
<string name="mmcc_authentication_reject" msgid="7729819349669603406">"SIM അനുവദനീയമല്ല"</string>
<string name="mmcc_imsi_unknown_in_hlr" msgid="6321202257374418726">"SIM പ്രൊവിഷൻ ചെയ്തിട്ടില്ല"</string>
diff --git a/core/res/res/values-mn/strings.xml b/core/res/res/values-mn/strings.xml
index a2b08e0..c9a5853 100644
--- a/core/res/res/values-mn/strings.xml
+++ b/core/res/res/values-mn/strings.xml
@@ -1767,6 +1767,8 @@
<string name="etws_primary_default_message_tsunami" msgid="1887685943498368548">"Эргийн бүс, голын эргийн бүсээс өндөрлөг газар зэрэг аюулгүй газар руу нэн даруй шилжинэ үү."</string>
<string name="etws_primary_default_message_earthquake_and_tsunami" msgid="998797956848445862">"Тайван байж, ойролцоох нуугдах газар хайна уу."</string>
<string name="etws_primary_default_message_test" msgid="2709597093560037455">"Онцгой байдлын зурвасын тест"</string>
+ <!-- no translation found for notification_reply_button_accessibility (3621714652387814344) -->
+ <skip />
<string name="etws_primary_default_message_others" msgid="6293148756130398971"></string>
<string name="mmcc_authentication_reject" msgid="7729819349669603406">"SIM боломжгүй"</string>
<string name="mmcc_imsi_unknown_in_hlr" msgid="6321202257374418726">"SIM-г хийгээгүй"</string>
diff --git a/core/res/res/values-mr/strings.xml b/core/res/res/values-mr/strings.xml
index 12026d8..cd9124a 100644
--- a/core/res/res/values-mr/strings.xml
+++ b/core/res/res/values-mr/strings.xml
@@ -1770,6 +1770,8 @@
<string name="etws_primary_default_message_tsunami" msgid="1887685943498368548">"किनारपट्टीचे प्रदेश आणि नदीकाठची क्षेत्रे त्वरित रिकामी करून उंच मैदानासारख्या अधिक सुरक्षित ठिकाणी जा."</string>
<string name="etws_primary_default_message_earthquake_and_tsunami" msgid="998797956848445862">"शांत रहा आणि जवळपास निवारा शोधा."</string>
<string name="etws_primary_default_message_test" msgid="2709597093560037455">"आणीबाणी संदेश चाचणी"</string>
+ <!-- no translation found for notification_reply_button_accessibility (3621714652387814344) -->
+ <skip />
<string name="etws_primary_default_message_others" msgid="6293148756130398971"></string>
<string name="mmcc_authentication_reject" msgid="7729819349669603406">"सिमला अनुमती नाही"</string>
<string name="mmcc_imsi_unknown_in_hlr" msgid="6321202257374418726">"सिमसाठी तरतूद नाही"</string>
diff --git a/core/res/res/values-ms/strings.xml b/core/res/res/values-ms/strings.xml
index bd7e6ac..19bc7d7 100644
--- a/core/res/res/values-ms/strings.xml
+++ b/core/res/res/values-ms/strings.xml
@@ -1769,6 +1769,8 @@
<string name="etws_primary_default_message_tsunami" msgid="1887685943498368548">"Segera beredar dari kawasan pinggir laut dan tepi sungai dan berpindah ke tempat yang lebih selamat seperti kawasan tinggi."</string>
<string name="etws_primary_default_message_earthquake_and_tsunami" msgid="998797956848445862">"Bertenang dan cari perlindungan di kawasan yang berdekatan."</string>
<string name="etws_primary_default_message_test" msgid="2709597093560037455">"Ujian mesej kecemasan"</string>
+ <!-- no translation found for notification_reply_button_accessibility (3621714652387814344) -->
+ <skip />
<string name="etws_primary_default_message_others" msgid="6293148756130398971"></string>
<string name="mmcc_authentication_reject" msgid="7729819349669603406">"SIM tidak dibenarkan"</string>
<string name="mmcc_imsi_unknown_in_hlr" msgid="6321202257374418726">"SIM tidak diperuntukkan"</string>
diff --git a/core/res/res/values-my/strings.xml b/core/res/res/values-my/strings.xml
index 9832137..f24ab13 100644
--- a/core/res/res/values-my/strings.xml
+++ b/core/res/res/values-my/strings.xml
@@ -1770,6 +1770,8 @@
<string name="etws_primary_default_message_tsunami" msgid="1887685943498368548">"ကမ်းရိုးတန်းနှင့် မြစ်ကမ်းရိုးတစ်လျှောက်ရှိ နေရာဒေသတို့မှ ချက်ချင်းထွက်ခွာပြီး ဘေးကင်းရာကုန်းမြင့်ဒေသသို့ ပြောင်းရွှေ့ပါ။"</string>
<string name="etws_primary_default_message_earthquake_and_tsunami" msgid="998797956848445862">"စိတ်ငြိမ်ငြိမ်ထားပြီး အနီးအနားတဝိုက်တွင် ခိုနားစရာ နေရာရှာပါ။"</string>
<string name="etws_primary_default_message_test" msgid="2709597093560037455">"အရေးပေါ် မက်ဆေ့ဂျ် စမ်းသပ်မှု"</string>
+ <!-- no translation found for notification_reply_button_accessibility (3621714652387814344) -->
+ <skip />
<string name="etws_primary_default_message_others" msgid="6293148756130398971"></string>
<string name="mmcc_authentication_reject" msgid="7729819349669603406">"ဆင်းမ်ကို ခွင့်မပြုပါ"</string>
<string name="mmcc_imsi_unknown_in_hlr" msgid="6321202257374418726">"ဆင်းမ်ကို ထောက်ပံ့မထားပါ"</string>
diff --git a/core/res/res/values-nb/strings.xml b/core/res/res/values-nb/strings.xml
index 7103ea9..72ad6d1 100644
--- a/core/res/res/values-nb/strings.xml
+++ b/core/res/res/values-nb/strings.xml
@@ -119,7 +119,7 @@
<string name="roamingTextSearching" msgid="8360141885972279963">"Leter etter tjeneste"</string>
<string name="wfcRegErrorTitle" msgid="2301376280632110664">"Wi-Fi-anrop"</string>
<string-array name="wfcOperatorErrorAlertMessages">
- <item msgid="3910386316304772394">"For å ringe og sende meldinger over Wi-Fi må du først be operatøren om å konfigurere denne tjenesten. Deretter slår du på Wi-Fi-anrop igjen fra Innstillinger. (Feilkode: <xliff:g id="CODE">%1$s</xliff:g>)"</item>
+ <item msgid="3910386316304772394">"For å ringe og sende meldinger over Wi-Fi, må du først be operatøren om å konfigurere denne tjenesten. Deretter slår du på Wi-Fi-anrop igjen fra Innstillinger. (Feilkode: <xliff:g id="CODE">%1$s</xliff:g>)"</item>
</string-array>
<string-array name="wfcOperatorErrorNotificationMessages">
<item msgid="6177300162212449033">"Registrer deg hos operatøren din"</item>
@@ -1769,6 +1769,8 @@
<string name="etws_primary_default_message_tsunami" msgid="1887685943498368548">"Evakuer umiddelbart fra kyst- og elveområder til et tryggere sted, for eksempel høyt terreng."</string>
<string name="etws_primary_default_message_earthquake_and_tsunami" msgid="998797956848445862">"Hold deg rolig og søk ly i nærheten."</string>
<string name="etws_primary_default_message_test" msgid="2709597093560037455">"Test av nødmeldinger"</string>
+ <!-- no translation found for notification_reply_button_accessibility (3621714652387814344) -->
+ <skip />
<string name="etws_primary_default_message_others" msgid="6293148756130398971"></string>
<string name="mmcc_authentication_reject" msgid="7729819349669603406">"SIM-kortet er ikke tillatt"</string>
<string name="mmcc_imsi_unknown_in_hlr" msgid="6321202257374418726">"SIM-kortet er ikke klargjort"</string>
diff --git a/core/res/res/values-ne/strings.xml b/core/res/res/values-ne/strings.xml
index 717b91f..c576c89 100644
--- a/core/res/res/values-ne/strings.xml
+++ b/core/res/res/values-ne/strings.xml
@@ -349,9 +349,9 @@
<string name="permdesc_receiveBootCompleted" product="tv" msgid="4525890122209673621">"अनुप्रयोगलाई अनुमति दिन्छ प्रणालीले बुटिङ सकेपछि आफै सुरूवात हुन। यसले TV सुरू गर्न लामो समय लिन सक्छ र अनुप्रयोगहरूलाई अनुमति दिन सक्छ सँधै सञ्चालन भई समग्र रूपमा ट्याब्लेटलाई ढिलो गराएर।"</string>
<string name="permdesc_receiveBootCompleted" product="default" msgid="513950589102617504">"अनुप्रयोगलाई प्रणाली बुट गरी सकेपछि जति सक्दो चाँडो आफैंमा सुरु गर्न अनुमति दिन्छ। यसले फोन सुरु गर्नमा ढिला गर्न सक्दछ र अनप्रयोगलाई समग्रमा फोन सधैँ चालु गरेर ढिला बनाउँदछ।"</string>
<string name="permlab_broadcastSticky" msgid="7919126372606881614">"स्टिकि प्रसारण पठाउनुहोस्"</string>
- <string name="permdesc_broadcastSticky" product="tablet" msgid="7749760494399915651">"औपचारिक प्रसारणलाई पठाउनको लागि एउटा अनुप्रयोगलाई अनुमति दिन्छ, जुन प्रसारण समाप्त भएपछि बाँकी रहन्छ। अत्याधिक प्रयोगले धेरै मेमोरी प्रयोग गरेको कारणले ट्याब्लेटलाई ढिलो र अस्थिर बनाउन सक्छ।"</string>
+ <string name="permdesc_broadcastSticky" product="tablet" msgid="7749760494399915651">"औपचारिक प्रसारणलाई पठाउनको लागि एउटा अनुप्रयोगलाई अनुमति दिन्छ, जुन प्रसारण समाप्त भएपछि बाँकी रहन्छ। अत्यधिक प्रयोगले धेरै मेमोरी प्रयोग गरेको कारणले ट्याब्लेटलाई ढिलो र अस्थिर बनाउन सक्छ।"</string>
<string name="permdesc_broadcastSticky" product="tv" msgid="6839285697565389467">"अनुप्रयोगलाई टाँसिने प्रसारणहरू पठाउन अनुमति दिन्छ, जुन प्रसारण पछि पनि रहन्छ। अत्यन्य धेरै मेमोरी प्रयोग गर्ने बनाएर अत्यधिक प्रयोगले TV लाई ढिलो वा अस्थिर बनाउन सक्छ ।"</string>
- <string name="permdesc_broadcastSticky" product="default" msgid="2825803764232445091">"औपचारिक प्रसारणलाई पठाउनको लागि एक अनुप्रयोगलाई अनुमति दिन्छ, जुन प्रसारण समाप्त भएपछि बाँकी रहन्छ। अत्याधिक प्रयोगले धेरै मेमोरी प्रयोग गरेको कारणले फोनलाई ढिलो र अस्थिर बनाउन सक्छ।"</string>
+ <string name="permdesc_broadcastSticky" product="default" msgid="2825803764232445091">"औपचारिक प्रसारणलाई पठाउनको लागि एक अनुप्रयोगलाई अनुमति दिन्छ, जुन प्रसारण समाप्त भएपछि बाँकी रहन्छ। अत्यधिक प्रयोगले धेरै मेमोरी प्रयोग गरेको कारणले फोनलाई ढिलो र अस्थिर बनाउन सक्छ।"</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">"अनुप्रयोगलाई अनुमति दिन्छ तपाईँको TV मा भण्डारण गरिएका तपाईँका सम्पर्कका डेटा, तपाईँको कल, इमेलको बारम्बारता, वा अन्य तरीकाले खास व्यक्तिहरूसँग गरिएको सञ्चार लगायत, पढ्न।यस अनुमतिले अनुप्रयोगलाई अनुमति दिन्छ तपाईँको सम्पर्क डेटा सुरक्षित गर्न र दुस्प्रभावी अनुप्रयोगहरूले तपाईँको ज्ञान बिना सम्पर्क डेटा साझेदारी गर्न सक्छन्।"</string>
@@ -708,7 +708,7 @@
<string name="lockscreen_pattern_wrong" msgid="4317955014948108794">"फेरि प्रयास गर्नुहोस्"</string>
<string name="lockscreen_password_wrong" msgid="5737815393253165301">"फेरि प्रयास गर्नुहोस्"</string>
<string name="lockscreen_storage_locked" msgid="9167551160010625200">"सबै सुविधाहरू र डेटाका लागि अनलक गर्नुहोस्"</string>
- <string name="faceunlock_multiple_failures" msgid="754137583022792429">"अत्याधिक मोहडा खोल्ने प्रयासहरू बढी भए।"</string>
+ <string name="faceunlock_multiple_failures" msgid="754137583022792429">"अत्यधिक मोहडा खोल्ने प्रयासहरू बढी भए।"</string>
<string name="lockscreen_missing_sim_message_short" msgid="5099439277819215399">"SIM कार्ड छैन"</string>
<string name="lockscreen_missing_sim_message" product="tablet" msgid="151659196095791474">"ट्याब्लेटमा SIM कार्ड छैन।"</string>
<string name="lockscreen_missing_sim_message" product="tv" msgid="1943633865476989599">"TV मा कुनै SIM कार्ड छैन।"</string>
@@ -1775,6 +1775,8 @@
<string name="etws_primary_default_message_tsunami" msgid="1887685943498368548">"तटीय क्षेत्र र नदीछेउका ठाउँहरू छाडी उच्च सतहमा अवस्थित कुनै अझ सुरक्षित ठाउँमा जानुहोस्।"</string>
<string name="etws_primary_default_message_earthquake_and_tsunami" msgid="998797956848445862">"शान्त रहनुहोस् र नजिकै आश्रयस्थल खोज्नुहोस्।"</string>
<string name="etws_primary_default_message_test" msgid="2709597093560037455">"आपतकालीन सन्देशहरूको परीक्षण"</string>
+ <!-- no translation found for notification_reply_button_accessibility (3621714652387814344) -->
+ <skip />
<string name="etws_primary_default_message_others" msgid="6293148756130398971"></string>
<string name="mmcc_authentication_reject" msgid="7729819349669603406">"SIM लाई अनुमति छैन"</string>
<string name="mmcc_imsi_unknown_in_hlr" msgid="6321202257374418726">"SIM को प्रावधान छैन"</string>
diff --git a/core/res/res/values-nl/strings.xml b/core/res/res/values-nl/strings.xml
index 7207255..d690fc6 100644
--- a/core/res/res/values-nl/strings.xml
+++ b/core/res/res/values-nl/strings.xml
@@ -1150,7 +1150,7 @@
<string name="sms_short_code_confirm_allow" msgid="4458878637111023413">"Verzenden"</string>
<string name="sms_short_code_confirm_deny" msgid="2927389840209170706">"Annuleren"</string>
<string name="sms_short_code_remember_choice" msgid="5289538592272218136">"Mijn keuze onthouden"</string>
- <string name="sms_short_code_remember_undo_instruction" msgid="4960944133052287484">"U kunt dit later wijzigen in \'Instellingen\' > \'Apps\'"</string>
+ <string name="sms_short_code_remember_undo_instruction" msgid="4960944133052287484">"U kunt dit later wijzigen in Instellingen > Apps"</string>
<string name="sms_short_code_confirm_always_allow" msgid="3241181154869493368">"Altijd toestaan"</string>
<string name="sms_short_code_confirm_never_allow" msgid="446992765774269673">"Nooit toestaan"</string>
<string name="sim_removed_title" msgid="6227712319223226185">"Simkaart verwijderd"</string>
@@ -1769,6 +1769,8 @@
<string name="etws_primary_default_message_tsunami" msgid="1887685943498368548">"Verlaat kustgebieden en rivieroevers onmiddellijk en zoek een hoger gelegen gebied op."</string>
<string name="etws_primary_default_message_earthquake_and_tsunami" msgid="998797956848445862">"Blijf kalm en zoek onderdak in de buurt."</string>
<string name="etws_primary_default_message_test" msgid="2709597093560037455">"Test voor noodberichten"</string>
+ <!-- no translation found for notification_reply_button_accessibility (3621714652387814344) -->
+ <skip />
<string name="etws_primary_default_message_others" msgid="6293148756130398971"></string>
<string name="mmcc_authentication_reject" msgid="7729819349669603406">"Simkaart niet toegestaan"</string>
<string name="mmcc_imsi_unknown_in_hlr" msgid="6321202257374418726">"Simkaart niet geregistreerd"</string>
diff --git a/core/res/res/values-pa/strings.xml b/core/res/res/values-pa/strings.xml
index c779361..0a237b1 100644
--- a/core/res/res/values-pa/strings.xml
+++ b/core/res/res/values-pa/strings.xml
@@ -83,7 +83,7 @@
<string name="RestrictedOnAllVoiceTitle" msgid="158800171499150681">"ਕੋਈ ਆਵਾਜ਼ੀ/ਸੰਕਟਕਾਲੀਨ ਸੇਵਾ ਨਹੀਂ"</string>
<string name="RestrictedStateContent" msgid="4278821484643362350">"ਤੁਹਾਡੇ ਟਿਕਾਣੇ \'ਤੇ ਅਸਥਾਈ ਤੌਰ \'ਤੇ ਮੋਬਾਈਲ ਨੈੱਟਵਰਕ ਵੱਲੋਂ ਉਪਲਬਧ ਨਹੀਂ ਕਰਵਾਈ ਗਈ"</string>
<string name="NetworkPreferenceSwitchTitle" msgid="4008877505368566980">"ਨੈੱਟਵਰਕ ਤੱਕ ਪਹੁੰਚ ਨਹੀਂ ਕੀਤੀ ਜਾ ਸਕਦੀ"</string>
- <string name="NetworkPreferenceSwitchSummary" msgid="1203771446683319957">"ਸਿਗਨਲ ਪ੍ਰਾਪਤੀ ਨੂੰ ਬਿਹਤਰ ਬਣਾਉਣ ਲਈ, ਸੈਟਿੰਗਾਂ > ਨੈੱਟਵਰਕ ਅਤੇ ਇੰਟਰਨੈੱਟ > ਮੋਬਾਈਲ ਨੈੱਟਵਰਕ > ਤਰਜੀਹੀ ਨੈੱਟਵਰਕ ਦੀ ਕਿਸਮ \'ਤੇ ਚੁਣੀ ਗਈ ਕਿਸਮ ਨੂੰ ਬਦਲਣ ਦੀ ਕੋਸ਼ਿਸ਼ ਕਰੋ।"</string>
+ <string name="NetworkPreferenceSwitchSummary" msgid="1203771446683319957">"ਸਿਗਨਲ ਪ੍ਰਾਪਤੀ ਨੂੰ ਬਿਹਤਰ ਬਣਾਉਣ ਲਈ, ਸੈਟਿੰਗਾਂ > ਨੈੱਟਵਰਕ ਅਤੇ ਇੰਟਰਨੈੱਟ > ਮੋਬਾਈਲ ਨੈੱਟਵਰਕ > ਤਰਜੀਹੀ ਨੈੱਟਵਰਕ ਦੀ ਕਿਸਮ \'ਤੇ ਜਾਓ ਅਤੇ ਚੁਣੀ ਗਈ ਕਿਸਮ ਨੂੰ ਬਦਲਣ ਦੀ ਕੋਸ਼ਿਸ਼ ਕਰੋ।"</string>
<string name="notification_channel_network_alert" msgid="4427736684338074967">"ਸੁਚੇਤਨਾਵਾਂ"</string>
<string name="notification_channel_call_forward" msgid="2419697808481833249">"ਕਾਲ ਫਾਰਵਾਰਡਿੰਗ"</string>
<string name="notification_channel_emergency_callback" msgid="6686166232265733921">"ਸੰਕਟਕਾਲੀਨ ਕਾਲਬੈਕ ਮੋਡ"</string>
@@ -118,7 +118,9 @@
<string name="roamingText12" msgid="1189071119992726320">"ਰੋਮਿੰਗ ਬੈਨਰ ਬੰਦ"</string>
<string name="roamingTextSearching" msgid="8360141885972279963">"ਸੇਵਾ ਦੀ ਖੋਜ ਕਰ ਰਿਹਾ ਹੈ"</string>
<string name="wfcRegErrorTitle" msgid="2301376280632110664">"Wi-Fi ਕਾਲਿੰਗ"</string>
- <!-- no translation found for wfcOperatorErrorAlertMessages:0 (3910386316304772394) -->
+ <string-array name="wfcOperatorErrorAlertMessages">
+ <item msgid="3910386316304772394">"Wi-Fi ਤੋਂ ਕਾਲਾਂ ਕਰਨ ਅਤੇ ਸੁਨੇਹੇ ਭੇਜਣ ਦੇ ਲਈ, ਸਭ ਤੋਂ ਪਹਿਲਾਂ ਆਪਣੇ ਕੈਰੀਅਰ ਨੂੰ ਇਸ ਸੇਵਾ ਦੀ ਸਥਾਪਨਾ ਕਰਨ ਲਈ ਕਹੋ। ਫਿਰ ਸੈਟਿੰਗਾਂ ਵਿੱਚੋਂ Wi-Fi ਕਾਲਿੰਗ ਨੂੰ ਦੁਬਾਰਾ ਚਾਲੂ ਕਰੋ। (ਗੜਬੜੀ ਕੋਡ: <xliff:g id="CODE">%1$s</xliff:g>)"</item>
+ </string-array>
<string-array name="wfcOperatorErrorNotificationMessages">
<item msgid="6177300162212449033">"ਆਪਣੇ ਕੈਰੀਅਰ ਨਾਲ ਰਜਿਸਟਰ ਕਰੋ"</item>
</string-array>
@@ -1768,6 +1770,8 @@
<string name="etws_primary_default_message_tsunami" msgid="1887685943498368548">"ਤੁਰੰਤ ਤੱਟੀ ਖੇਤਰਾਂ ਅਤੇ ਨਦੀ ਦੇ ਕਿਨਾਰੇ ਵਾਲੇ ਖੇਤਰਾਂ ਨੂੰ ਖਾਲੀ ਕਰ ਕੇ ਕਿਸੇ ਸੁਰੱਖਿਅਤ ਸਥਾਨ \'ਤੇ ਚਲੇ ਜਾਓ ਜਿਵੇਂ ਕਿ ਉੱਚੀ ਜ਼ਮੀਨ।"</string>
<string name="etws_primary_default_message_earthquake_and_tsunami" msgid="998797956848445862">"ਸ਼ਾਂਤ ਰਹੋ ਅਤੇ ਆਸ-ਪਾਸ ਪਨਾਹ ਮੰਗੋ।"</string>
<string name="etws_primary_default_message_test" msgid="2709597093560037455">"ਸੰਕਟਕਾਲੀਨ ਸੰਦੇਸ਼ ਟੈਸਟ"</string>
+ <!-- no translation found for notification_reply_button_accessibility (3621714652387814344) -->
+ <skip />
<string name="etws_primary_default_message_others" msgid="6293148756130398971"></string>
<string name="mmcc_authentication_reject" msgid="7729819349669603406">"SIM ਦੀ ਇਜਾਜ਼ਤ ਨਹੀਂ ਹੈ"</string>
<string name="mmcc_imsi_unknown_in_hlr" msgid="6321202257374418726">"SIM ਦੀ ਵਿਵਸਥਾ ਨਹੀਂ ਹੈ"</string>
diff --git a/core/res/res/values-pl/strings.xml b/core/res/res/values-pl/strings.xml
index e36eaf3..b730e3c 100644
--- a/core/res/res/values-pl/strings.xml
+++ b/core/res/res/values-pl/strings.xml
@@ -1837,6 +1837,8 @@
<string name="etws_primary_default_message_tsunami" msgid="1887685943498368548">"Niezwłocznie ewakuuj się z regionów nabrzeżnych i położonych przy rzekach w bezpieczniejsze miejsce, np. na wzniesienie."</string>
<string name="etws_primary_default_message_earthquake_and_tsunami" msgid="998797956848445862">"Zachowaj spokój i poszukaj schronienia w pobliżu."</string>
<string name="etws_primary_default_message_test" msgid="2709597093560037455">"Test komunikatów alarmowych"</string>
+ <!-- no translation found for notification_reply_button_accessibility (3621714652387814344) -->
+ <skip />
<string name="etws_primary_default_message_others" msgid="6293148756130398971"></string>
<string name="mmcc_authentication_reject" msgid="7729819349669603406">"Niedozwolona karta SIM"</string>
<string name="mmcc_imsi_unknown_in_hlr" msgid="6321202257374418726">"Nieobsługiwana karta SIM"</string>
diff --git a/core/res/res/values-pt-rBR/strings.xml b/core/res/res/values-pt-rBR/strings.xml
index acaafd6..a373b45 100644
--- a/core/res/res/values-pt-rBR/strings.xml
+++ b/core/res/res/values-pt-rBR/strings.xml
@@ -1183,7 +1183,7 @@
<string name="usb_unsupported_audio_accessory_title" msgid="2256529893240208458">"Acessório de áudio não compatível"</string>
<string name="usb_unsupported_audio_accessory_message" msgid="7811865061127547035">"Toque para mais informações"</string>
<string name="adb_active_notification_title" msgid="6729044778949189918">"Depuração USB conectada"</string>
- <string name="adb_active_notification_message" msgid="4948470599328424059">"Toque para desativar a depuração do USB."</string>
+ <string name="adb_active_notification_message" msgid="4948470599328424059">"Toque para desativar a depuração USB."</string>
<string name="adb_active_notification_message" product="tv" msgid="8470296818270110396">"Selecione para desativar a depuração USB."</string>
<string name="taking_remote_bugreport_notification_title" msgid="6742483073875060934">"Gerando relatório do bug..."</string>
<string name="share_remote_bugreport_notification_title" msgid="4987095013583691873">"Compartilhar relatório do bug?"</string>
@@ -1769,6 +1769,8 @@
<string name="etws_primary_default_message_tsunami" msgid="1887685943498368548">"Saia imediatamente de regiões costeiras e áreas ribeirinhas e vá para um lugar mais seguro, como terrenos elevados."</string>
<string name="etws_primary_default_message_earthquake_and_tsunami" msgid="998797956848445862">"Fique calmo e procure um abrigo por perto."</string>
<string name="etws_primary_default_message_test" msgid="2709597093560037455">"Teste de mensagens de emergência"</string>
+ <!-- no translation found for notification_reply_button_accessibility (3621714652387814344) -->
+ <skip />
<string name="etws_primary_default_message_others" msgid="6293148756130398971"></string>
<string name="mmcc_authentication_reject" msgid="7729819349669603406">"SIM não permitido"</string>
<string name="mmcc_imsi_unknown_in_hlr" msgid="6321202257374418726">"SIM não aprovisionado"</string>
diff --git a/core/res/res/values-pt-rPT/strings.xml b/core/res/res/values-pt-rPT/strings.xml
index 3c1011b..4c3399d 100644
--- a/core/res/res/values-pt-rPT/strings.xml
+++ b/core/res/res/values-pt-rPT/strings.xml
@@ -1150,7 +1150,7 @@
<string name="sms_short_code_confirm_allow" msgid="4458878637111023413">"Enviar"</string>
<string name="sms_short_code_confirm_deny" msgid="2927389840209170706">"Cancelar"</string>
<string name="sms_short_code_remember_choice" msgid="5289538592272218136">"Memorizar a minha escolha"</string>
- <string name="sms_short_code_remember_undo_instruction" msgid="4960944133052287484">"Pode depois alterar isto em Definições > Aplicações"</string>
+ <string name="sms_short_code_remember_undo_instruction" msgid="4960944133052287484">"Pode alterar mais tarde em Definições > Aplicações"</string>
<string name="sms_short_code_confirm_always_allow" msgid="3241181154869493368">"Permitir Sempre"</string>
<string name="sms_short_code_confirm_never_allow" msgid="446992765774269673">"Nunca Permitir"</string>
<string name="sim_removed_title" msgid="6227712319223226185">"Cartão SIM removido"</string>
@@ -1184,7 +1184,7 @@
<string name="usb_unsupported_audio_accessory_message" msgid="7811865061127547035">"Toque para obter mais informações"</string>
<string name="adb_active_notification_title" msgid="6729044778949189918">"Depuração USB ligada"</string>
<string name="adb_active_notification_message" msgid="4948470599328424059">"Toque para desativar a depuração USB."</string>
- <string name="adb_active_notification_message" product="tv" msgid="8470296818270110396">"Seleccione para desativar depuração USB."</string>
+ <string name="adb_active_notification_message" product="tv" msgid="8470296818270110396">"Selecione para desativar a depuração por USB."</string>
<string name="taking_remote_bugreport_notification_title" msgid="6742483073875060934">"A criar relatório de erro…"</string>
<string name="share_remote_bugreport_notification_title" msgid="4987095013583691873">"Pretende partilhar o relatório de erro?"</string>
<string name="sharing_remote_bugreport_notification_title" msgid="7572089031496651372">"A partilhar relatório de erro…"</string>
@@ -1769,6 +1769,8 @@
<string name="etws_primary_default_message_tsunami" msgid="1887685943498368548">"Abandone imediatamente regiões costeiras e zonas ribeirinhas em direção a um local mais seguro, como um terreno elevado."</string>
<string name="etws_primary_default_message_earthquake_and_tsunami" msgid="998797956848445862">"Mantenha a calma e procure abrigo nas proximidades."</string>
<string name="etws_primary_default_message_test" msgid="2709597093560037455">"Teste de mensagens de emergência"</string>
+ <!-- no translation found for notification_reply_button_accessibility (3621714652387814344) -->
+ <skip />
<string name="etws_primary_default_message_others" msgid="6293148756130398971"></string>
<string name="mmcc_authentication_reject" msgid="7729819349669603406">"SIM não permitido"</string>
<string name="mmcc_imsi_unknown_in_hlr" msgid="6321202257374418726">"SIM não ativado"</string>
diff --git a/core/res/res/values-pt/strings.xml b/core/res/res/values-pt/strings.xml
index acaafd6..a373b45 100644
--- a/core/res/res/values-pt/strings.xml
+++ b/core/res/res/values-pt/strings.xml
@@ -1183,7 +1183,7 @@
<string name="usb_unsupported_audio_accessory_title" msgid="2256529893240208458">"Acessório de áudio não compatível"</string>
<string name="usb_unsupported_audio_accessory_message" msgid="7811865061127547035">"Toque para mais informações"</string>
<string name="adb_active_notification_title" msgid="6729044778949189918">"Depuração USB conectada"</string>
- <string name="adb_active_notification_message" msgid="4948470599328424059">"Toque para desativar a depuração do USB."</string>
+ <string name="adb_active_notification_message" msgid="4948470599328424059">"Toque para desativar a depuração USB."</string>
<string name="adb_active_notification_message" product="tv" msgid="8470296818270110396">"Selecione para desativar a depuração USB."</string>
<string name="taking_remote_bugreport_notification_title" msgid="6742483073875060934">"Gerando relatório do bug..."</string>
<string name="share_remote_bugreport_notification_title" msgid="4987095013583691873">"Compartilhar relatório do bug?"</string>
@@ -1769,6 +1769,8 @@
<string name="etws_primary_default_message_tsunami" msgid="1887685943498368548">"Saia imediatamente de regiões costeiras e áreas ribeirinhas e vá para um lugar mais seguro, como terrenos elevados."</string>
<string name="etws_primary_default_message_earthquake_and_tsunami" msgid="998797956848445862">"Fique calmo e procure um abrigo por perto."</string>
<string name="etws_primary_default_message_test" msgid="2709597093560037455">"Teste de mensagens de emergência"</string>
+ <!-- no translation found for notification_reply_button_accessibility (3621714652387814344) -->
+ <skip />
<string name="etws_primary_default_message_others" msgid="6293148756130398971"></string>
<string name="mmcc_authentication_reject" msgid="7729819349669603406">"SIM não permitido"</string>
<string name="mmcc_imsi_unknown_in_hlr" msgid="6321202257374418726">"SIM não aprovisionado"</string>
diff --git a/core/res/res/values-ro/strings.xml b/core/res/res/values-ro/strings.xml
index 33c36d89..83afac8 100644
--- a/core/res/res/values-ro/strings.xml
+++ b/core/res/res/values-ro/strings.xml
@@ -273,7 +273,7 @@
<string name="permgroupdesc_sms" msgid="4656988620100940350">"trimită și să vadă mesajele SMS"</string>
<string name="permgrouplab_storage" msgid="1971118770546336966">"Stocare"</string>
<string name="permgroupdesc_storage" msgid="637758554581589203">"acceseze fotografiile, conținutul media și fișierele de pe dispozitiv"</string>
- <string name="permgrouplab_microphone" msgid="171539900250043464">"Microfonul"</string>
+ <string name="permgrouplab_microphone" msgid="171539900250043464">"Microfon"</string>
<string name="permgroupdesc_microphone" msgid="4988812113943554584">"înregistreze sunet"</string>
<string name="permgrouplab_camera" msgid="4820372495894586615">"Camera foto"</string>
<string name="permgroupdesc_camera" msgid="3250611594678347720">"fotografieze și să înregistreze videoclipuri"</string>
@@ -1803,6 +1803,8 @@
<string name="etws_primary_default_message_tsunami" msgid="1887685943498368548">"Părăsiți imediat zonele de coastă și din apropierea râurilor și îndreptați-vă spre un loc mai sigur, cum ar fi o zonă aflată la înălțime."</string>
<string name="etws_primary_default_message_earthquake_and_tsunami" msgid="998797956848445862">"Păstrați-vă calmul și căutați un adăpost în apropiere."</string>
<string name="etws_primary_default_message_test" msgid="2709597093560037455">"Testarea mesajelor de urgență"</string>
+ <!-- no translation found for notification_reply_button_accessibility (3621714652387814344) -->
+ <skip />
<string name="etws_primary_default_message_others" msgid="6293148756130398971"></string>
<string name="mmcc_authentication_reject" msgid="7729819349669603406">"Cardul SIM nu este permis"</string>
<string name="mmcc_imsi_unknown_in_hlr" msgid="6321202257374418726">"Cardul SIM nu este activat"</string>
diff --git a/core/res/res/values-ru/strings.xml b/core/res/res/values-ru/strings.xml
index 853586f..913c93b 100644
--- a/core/res/res/values-ru/strings.xml
+++ b/core/res/res/values-ru/strings.xml
@@ -1228,7 +1228,7 @@
<string name="usb_unsupported_audio_accessory_message" msgid="7811865061127547035">"Нажмите, чтобы получить дополнительную информацию"</string>
<string name="adb_active_notification_title" msgid="6729044778949189918">"Отладка по USB разрешена"</string>
<string name="adb_active_notification_message" msgid="4948470599328424059">"Нажмите, чтобы отключить отладку по USB."</string>
- <string name="adb_active_notification_message" product="tv" msgid="8470296818270110396">"Нажмите, чтобы отключить отладку USB."</string>
+ <string name="adb_active_notification_message" product="tv" msgid="8470296818270110396">"Нажмите, чтобы отключить отладку по USB."</string>
<string name="taking_remote_bugreport_notification_title" msgid="6742483073875060934">"Подготовка отчета об ошибке"</string>
<string name="share_remote_bugreport_notification_title" msgid="4987095013583691873">"Разрешить доступ к информации об ошибке?"</string>
<string name="sharing_remote_bugreport_notification_title" msgid="7572089031496651372">"Отправка отчета об ошибке"</string>
@@ -1837,6 +1837,8 @@
<string name="etws_primary_default_message_tsunami" msgid="1887685943498368548">"Немедленно эвакуируйтесь из прибрежной зоны в более высокое место."</string>
<string name="etws_primary_default_message_earthquake_and_tsunami" msgid="998797956848445862">"Сохраняйте спокойствие и поищите укрытие поблизости."</string>
<string name="etws_primary_default_message_test" msgid="2709597093560037455">"Тестовое экстренное сообщение"</string>
+ <!-- no translation found for notification_reply_button_accessibility (3621714652387814344) -->
+ <skip />
<string name="etws_primary_default_message_others" msgid="6293148756130398971"></string>
<string name="mmcc_authentication_reject" msgid="7729819349669603406">"Использование SIM-карты запрещено"</string>
<string name="mmcc_imsi_unknown_in_hlr" msgid="6321202257374418726">"SIM-карта не активирована"</string>
diff --git a/core/res/res/values-si/strings.xml b/core/res/res/values-si/strings.xml
index 1f373fe..641bd40 100644
--- a/core/res/res/values-si/strings.xml
+++ b/core/res/res/values-si/strings.xml
@@ -1771,6 +1771,8 @@
<string name="etws_primary_default_message_tsunami" msgid="1887685943498368548">"මුහුදු බඩ ප්රදේශ සහ ගංඉවුරු ප්රදේශ සිට ඉහළ ප්රදේශයක් වැනි ආරක්ෂිත තැනකට දැන්ම යන්න."</string>
<string name="etws_primary_default_message_earthquake_and_tsunami" msgid="998797956848445862">"සන්සුන්ව ඉන්න සහ අවට ඇති නවාතැන් පහසුකම් බලන්න."</string>
<string name="etws_primary_default_message_test" msgid="2709597093560037455">"හදිසි පණිවිඩ පරීක්ෂණය"</string>
+ <!-- no translation found for notification_reply_button_accessibility (3621714652387814344) -->
+ <skip />
<string name="etws_primary_default_message_others" msgid="6293148756130398971"></string>
<string name="mmcc_authentication_reject" msgid="7729819349669603406">"SIM එක සඳහා ඉඩ නොදේ"</string>
<string name="mmcc_imsi_unknown_in_hlr" msgid="6321202257374418726">"SIM එක සක්රීය කර නොමැත"</string>
diff --git a/core/res/res/values-sk/strings.xml b/core/res/res/values-sk/strings.xml
index 47b0b85..d68ebc4 100644
--- a/core/res/res/values-sk/strings.xml
+++ b/core/res/res/values-sk/strings.xml
@@ -1228,7 +1228,7 @@
<string name="usb_unsupported_audio_accessory_message" msgid="7811865061127547035">"Ďalšie informácie zobrazíte klepnutím"</string>
<string name="adb_active_notification_title" msgid="6729044778949189918">"Ladenie cez USB pripojené"</string>
<string name="adb_active_notification_message" msgid="4948470599328424059">"Klepnutím zakážete ladenie cez USB."</string>
- <string name="adb_active_notification_message" product="tv" msgid="8470296818270110396">"Výberom zakážete ladenie USB."</string>
+ <string name="adb_active_notification_message" product="tv" msgid="8470296818270110396">"Vyberte, ak chcete zakázať ladenie cez USB."</string>
<string name="taking_remote_bugreport_notification_title" msgid="6742483073875060934">"Preberá sa hlásenie chyby…"</string>
<string name="share_remote_bugreport_notification_title" msgid="4987095013583691873">"Chcete zdieľať hlásenie chyby?"</string>
<string name="sharing_remote_bugreport_notification_title" msgid="7572089031496651372">"Zdieľa sa hlásenie chyby…"</string>
@@ -1837,6 +1837,8 @@
<string name="etws_primary_default_message_tsunami" msgid="1887685943498368548">"Okamžite začnite evakuáciu z prímorských a nábrežných oblastí na bezpečnejšie miesto, napríklad do vyššie položených regiónov."</string>
<string name="etws_primary_default_message_earthquake_and_tsunami" msgid="998797956848445862">"Zachovajte pokoj a vyhľadajte úkryt v okolí."</string>
<string name="etws_primary_default_message_test" msgid="2709597093560037455">"Test tiesňových správ"</string>
+ <!-- no translation found for notification_reply_button_accessibility (3621714652387814344) -->
+ <skip />
<string name="etws_primary_default_message_others" msgid="6293148756130398971"></string>
<string name="mmcc_authentication_reject" msgid="7729819349669603406">"SIM karta je zakázaná"</string>
<string name="mmcc_imsi_unknown_in_hlr" msgid="6321202257374418726">"SIM karta nie je k dispozícii"</string>
diff --git a/core/res/res/values-sl/strings.xml b/core/res/res/values-sl/strings.xml
index 457f324..48baf05 100644
--- a/core/res/res/values-sl/strings.xml
+++ b/core/res/res/values-sl/strings.xml
@@ -1837,6 +1837,8 @@
<string name="etws_primary_default_message_tsunami" msgid="1887685943498368548">"Takoj se umaknite z obalnih območij in bregov rek na varnejše mesto, na primer na višje ležeča mesta."</string>
<string name="etws_primary_default_message_earthquake_and_tsunami" msgid="998797956848445862">"Ostanite mirni in poiščite zavetje v bližini."</string>
<string name="etws_primary_default_message_test" msgid="2709597093560037455">"Preskus sporočil v sili"</string>
+ <!-- no translation found for notification_reply_button_accessibility (3621714652387814344) -->
+ <skip />
<string name="etws_primary_default_message_others" msgid="6293148756130398971"></string>
<string name="mmcc_authentication_reject" msgid="7729819349669603406">"Kartica SIM ni dovoljena"</string>
<string name="mmcc_imsi_unknown_in_hlr" msgid="6321202257374418726">"Kartica SIM ni omogočena za uporabo"</string>
diff --git a/core/res/res/values-sq/strings.xml b/core/res/res/values-sq/strings.xml
index 96f3ae6..381154f 100644
--- a/core/res/res/values-sq/strings.xml
+++ b/core/res/res/values-sq/strings.xml
@@ -1770,6 +1770,8 @@
<string name="etws_primary_default_message_tsunami" msgid="1887685943498368548">"Evakuohu menjëherë nga rajonet bregdetare dhe zonat pranë lumenjve drejt një vendi më të sigurt, si për shembull në një terren të ngritur."</string>
<string name="etws_primary_default_message_earthquake_and_tsunami" msgid="998797956848445862">"Qëndro i qetë dhe kërko strehim në afërsi."</string>
<string name="etws_primary_default_message_test" msgid="2709597093560037455">"Testim për mesazhet e urgjencës"</string>
+ <!-- no translation found for notification_reply_button_accessibility (3621714652387814344) -->
+ <skip />
<string name="etws_primary_default_message_others" msgid="6293148756130398971"></string>
<string name="mmcc_authentication_reject" msgid="7729819349669603406">"Karta SIM nuk lejohet"</string>
<string name="mmcc_imsi_unknown_in_hlr" msgid="6321202257374418726">"Karta SIM nuk është dhënë"</string>
diff --git a/core/res/res/values-sr/strings.xml b/core/res/res/values-sr/strings.xml
index 9d5963b..704869d 100644
--- a/core/res/res/values-sr/strings.xml
+++ b/core/res/res/values-sr/strings.xml
@@ -1204,7 +1204,7 @@
<string name="usb_notification_message" msgid="3370903770828407960">"Додирните за још опција."</string>
<string name="usb_unsupported_audio_accessory_title" msgid="2256529893240208458">"Додатна опрема за аудио садржај није подржана"</string>
<string name="usb_unsupported_audio_accessory_message" msgid="7811865061127547035">"Додирните за више информација"</string>
- <string name="adb_active_notification_title" msgid="6729044778949189918">"Отклањање грешака са USB-а је успостављено"</string>
+ <string name="adb_active_notification_title" msgid="6729044778949189918">"Отклањање грешака са USB-а је омогућено"</string>
<string name="adb_active_notification_message" msgid="4948470599328424059">"Додирните да бисте онемогућили отклањање грешака са USB-а."</string>
<string name="adb_active_notification_message" product="tv" msgid="8470296818270110396">"Изаберите да бисте онемогућили отклањања грешака са USB-а."</string>
<string name="taking_remote_bugreport_notification_title" msgid="6742483073875060934">"Извештај о грешци се генерише…"</string>
@@ -1803,6 +1803,8 @@
<string name="etws_primary_default_message_tsunami" msgid="1887685943498368548">"Одмах се склоните из приобалних региона и области поред река на неко безбедније место, на пример, на неко узвишење."</string>
<string name="etws_primary_default_message_earthquake_and_tsunami" msgid="998797956848445862">"Останите мирни и потражите склониште у околини."</string>
<string name="etws_primary_default_message_test" msgid="2709597093560037455">"Тестирање порука у хитним случајевима"</string>
+ <!-- no translation found for notification_reply_button_accessibility (3621714652387814344) -->
+ <skip />
<string name="etws_primary_default_message_others" msgid="6293148756130398971"></string>
<string name="mmcc_authentication_reject" msgid="7729819349669603406">"SIM картица није дозвољена"</string>
<string name="mmcc_imsi_unknown_in_hlr" msgid="6321202257374418726">"SIM картица није подешена"</string>
diff --git a/core/res/res/values-sv/strings.xml b/core/res/res/values-sv/strings.xml
index 59f59c6..7339480 100644
--- a/core/res/res/values-sv/strings.xml
+++ b/core/res/res/values-sv/strings.xml
@@ -1184,7 +1184,7 @@
<string name="usb_unsupported_audio_accessory_message" msgid="7811865061127547035">"Tryck för mer information"</string>
<string name="adb_active_notification_title" msgid="6729044778949189918">"USB-felsökning ansluten"</string>
<string name="adb_active_notification_message" msgid="4948470599328424059">"Tryck om du vill inaktivera USB-felsökning."</string>
- <string name="adb_active_notification_message" product="tv" msgid="8470296818270110396">"Välj att inaktivera USB-felsökning."</string>
+ <string name="adb_active_notification_message" product="tv" msgid="8470296818270110396">"Välj för att inaktivera USB-felsökning."</string>
<string name="taking_remote_bugreport_notification_title" msgid="6742483073875060934">"Felrapporten överförs …"</string>
<string name="share_remote_bugreport_notification_title" msgid="4987095013583691873">"Vill du dela felrapporten?"</string>
<string name="sharing_remote_bugreport_notification_title" msgid="7572089031496651372">"Felrapporten delas …"</string>
@@ -1769,6 +1769,8 @@
<string name="etws_primary_default_message_tsunami" msgid="1887685943498368548">"Utrym kust- och flodområden omedelbart och förflytta er till en säkrare plats, till exempel ett högt beläget område."</string>
<string name="etws_primary_default_message_earthquake_and_tsunami" msgid="998797956848445862">"Håll dig lugn och sök skydd i närheten."</string>
<string name="etws_primary_default_message_test" msgid="2709597093560037455">"Test för nödmeddelanden"</string>
+ <!-- no translation found for notification_reply_button_accessibility (3621714652387814344) -->
+ <skip />
<string name="etws_primary_default_message_others" msgid="6293148756130398971"></string>
<string name="mmcc_authentication_reject" msgid="7729819349669603406">"SIM-kort tillåts inte"</string>
<string name="mmcc_imsi_unknown_in_hlr" msgid="6321202257374418726">"SIM-kort tillhandahålls inte"</string>
diff --git a/core/res/res/values-sw/strings.xml b/core/res/res/values-sw/strings.xml
index 4728672..a855231 100644
--- a/core/res/res/values-sw/strings.xml
+++ b/core/res/res/values-sw/strings.xml
@@ -1767,6 +1767,8 @@
<string name="etws_primary_default_message_tsunami" msgid="1887685943498368548">"Ondoka mara moja kwenye maeneo ya ufuo na mito ili uende kwenye sehemu salama kama vile milimani."</string>
<string name="etws_primary_default_message_earthquake_and_tsunami" msgid="998797956848445862">"Tulia na utafute hifadhi ya karibu."</string>
<string name="etws_primary_default_message_test" msgid="2709597093560037455">"Jaribio la ujumbe wa dharura"</string>
+ <!-- no translation found for notification_reply_button_accessibility (3621714652387814344) -->
+ <skip />
<string name="etws_primary_default_message_others" msgid="6293148756130398971"></string>
<string name="mmcc_authentication_reject" msgid="7729819349669603406">"SIM imekataliwa"</string>
<string name="mmcc_imsi_unknown_in_hlr" msgid="6321202257374418726">"SIM haikubaliwi"</string>
diff --git a/core/res/res/values-ta/strings.xml b/core/res/res/values-ta/strings.xml
index e9ced05..45ac5c5 100644
--- a/core/res/res/values-ta/strings.xml
+++ b/core/res/res/values-ta/strings.xml
@@ -1770,6 +1770,8 @@
<string name="etws_primary_default_message_tsunami" msgid="1887685943498368548">"கடலோரப் பகுதிகளிலும் ஆற்றங்கரைகளிலும் வசிப்பவர்கள் உடனடியாகப் பாதுகாப்பான இடத்திற்குச் (மேட்டுப்பகுதி) செல்லவும்."</string>
<string name="etws_primary_default_message_earthquake_and_tsunami" msgid="998797956848445862">"பதட்டப்படாதீர்கள், அருகில் ஏதேனும் பாதுகாப்பான இடம் உள்ளதா எனப் பாருங்கள்."</string>
<string name="etws_primary_default_message_test" msgid="2709597093560037455">"அவசரக் காலச் செய்திகளுக்கான சோதனை"</string>
+ <!-- no translation found for notification_reply_button_accessibility (3621714652387814344) -->
+ <skip />
<string name="etws_primary_default_message_others" msgid="6293148756130398971"></string>
<string name="mmcc_authentication_reject" msgid="7729819349669603406">"சிம் அனுமதிக்கப்படவில்லை"</string>
<string name="mmcc_imsi_unknown_in_hlr" msgid="6321202257374418726">"சிம் அமைக்கப்படவில்லை"</string>
diff --git a/core/res/res/values-te/strings.xml b/core/res/res/values-te/strings.xml
index 375c82d..3078330 100644
--- a/core/res/res/values-te/strings.xml
+++ b/core/res/res/values-te/strings.xml
@@ -1770,6 +1770,8 @@
<string name="etws_primary_default_message_tsunami" msgid="1887685943498368548">"వెంటనే తీర ప్రాంతాలు మరియు నదీ పరీవాహక ప్రాంతాలను ఖాళీ చేసి మెట్ట ప్రాంతాలకు తరలి వెళ్లండి."</string>
<string name="etws_primary_default_message_earthquake_and_tsunami" msgid="998797956848445862">"ప్రశాంతంగా ఉండండి మరియు దగ్గర్లో తలదాచుకోండి."</string>
<string name="etws_primary_default_message_test" msgid="2709597093560037455">"అత్యవసర సందేశాల పరీక్ష"</string>
+ <!-- no translation found for notification_reply_button_accessibility (3621714652387814344) -->
+ <skip />
<string name="etws_primary_default_message_others" msgid="6293148756130398971"></string>
<string name="mmcc_authentication_reject" msgid="7729819349669603406">"SIM అనుమతించబడదు"</string>
<string name="mmcc_imsi_unknown_in_hlr" msgid="6321202257374418726">"SIM సక్రియం కాలేదు"</string>
diff --git a/core/res/res/values-th/strings.xml b/core/res/res/values-th/strings.xml
index 9a58edd..9be0d4a 100644
--- a/core/res/res/values-th/strings.xml
+++ b/core/res/res/values-th/strings.xml
@@ -1105,7 +1105,7 @@
<string name="network_available_sign_in" msgid="1848877297365446605">"ลงชื่อเข้าใช้เครือข่าย"</string>
<!-- no translation found for network_available_sign_in_detailed (8000081941447976118) -->
<skip />
- <string name="wifi_no_internet" msgid="8451173622563841546">"Wi-Fi ไม่สามารถเข้าถึงอินเทอร์เน็ต"</string>
+ <string name="wifi_no_internet" msgid="8451173622563841546">"Wi-Fi เชื่อมต่ออินเทอร์เน็ตไม่ได้"</string>
<string name="wifi_no_internet_detailed" msgid="8083079241212301741">"แตะเพื่อดูตัวเลือก"</string>
<string name="network_switch_metered" msgid="4671730921726992671">"เปลี่ยนเป็น <xliff:g id="NETWORK_TYPE">%1$s</xliff:g>"</string>
<string name="network_switch_metered_detail" msgid="5325661434777870353">"อุปกรณ์จะใช้ <xliff:g id="NEW_NETWORK">%1$s</xliff:g> เมื่อ <xliff:g id="PREVIOUS_NETWORK">%2$s</xliff:g> ไม่สามารถเข้าถึงอินเทอร์เน็ต อาจมีค่าบริการ"</string>
@@ -1182,7 +1182,7 @@
<string name="usb_notification_message" msgid="3370903770828407960">"แตะเพื่อดูตัวเลือกเพิ่มเติม"</string>
<string name="usb_unsupported_audio_accessory_title" msgid="2256529893240208458">"ไม่รองรับอุปกรณ์เสริมสำหรับเสียง"</string>
<string name="usb_unsupported_audio_accessory_message" msgid="7811865061127547035">"แตะเพื่อดูข้อมูลเพิ่มเติม"</string>
- <string name="adb_active_notification_title" msgid="6729044778949189918">"เชื่อมต่อการแก้ไขข้อบกพร่อง USB แล้ว"</string>
+ <string name="adb_active_notification_title" msgid="6729044778949189918">"เชื่อมต่อการแก้ไขข้อบกพร่องผ่าน USB แล้ว"</string>
<string name="adb_active_notification_message" msgid="4948470599328424059">"แตะเพื่อปิดใช้การแก้ไขข้อบกพร่องของ USB"</string>
<string name="adb_active_notification_message" product="tv" msgid="8470296818270110396">"เลือกเพื่อปิดใช้งานการแก้ไขข้อบกพร่อง USB"</string>
<string name="taking_remote_bugreport_notification_title" msgid="6742483073875060934">"กำลังสร้างรายงานข้อบกพร่อง…"</string>
@@ -1769,6 +1769,8 @@
<string name="etws_primary_default_message_tsunami" msgid="1887685943498368548">"อพยพออกจากจากเขตชายฝั่งทะเลและบริเวณริมแม่น้ำไปยังสถานที่ที่ปลอดภัยกว่า เช่น ที่สูง โดยทันที"</string>
<string name="etws_primary_default_message_earthquake_and_tsunami" msgid="998797956848445862">"ทำใจให้สงบและหาที่กำบังในบริเวณใกล้เคียง"</string>
<string name="etws_primary_default_message_test" msgid="2709597093560037455">"การทดสอบข้อความกรณีฉุกเฉิน"</string>
+ <!-- no translation found for notification_reply_button_accessibility (3621714652387814344) -->
+ <skip />
<string name="etws_primary_default_message_others" msgid="6293148756130398971"></string>
<string name="mmcc_authentication_reject" msgid="7729819349669603406">"ไม่อนุญาตให้ใช้ซิม"</string>
<string name="mmcc_imsi_unknown_in_hlr" msgid="6321202257374418726">"ไม่มีการจัดสรรซิม"</string>
diff --git a/core/res/res/values-tl/strings.xml b/core/res/res/values-tl/strings.xml
index 2c33a0f..a85e2e5 100644
--- a/core/res/res/values-tl/strings.xml
+++ b/core/res/res/values-tl/strings.xml
@@ -1769,6 +1769,8 @@
<string name="etws_primary_default_message_tsunami" msgid="1887685943498368548">"Umalis kaagad sa mga baybayin at pampang, at pumunta sa isang mas ligtas na lokasyon tulad ng isang mataas na lugar."</string>
<string name="etws_primary_default_message_earthquake_and_tsunami" msgid="998797956848445862">"Manatiling kalmado at maghanap ng matutuluyan sa malapit."</string>
<string name="etws_primary_default_message_test" msgid="2709597093560037455">"Pagsubok sa mga mensaheng pang-emergency"</string>
+ <!-- no translation found for notification_reply_button_accessibility (3621714652387814344) -->
+ <skip />
<string name="etws_primary_default_message_others" msgid="6293148756130398971"></string>
<string name="mmcc_authentication_reject" msgid="7729819349669603406">"Hindi pinahihintulutan ang SIM"</string>
<string name="mmcc_imsi_unknown_in_hlr" msgid="6321202257374418726">"Hindi naprobisyon ang SIM"</string>
diff --git a/core/res/res/values-tr/strings.xml b/core/res/res/values-tr/strings.xml
index 8c4c427..aa63562 100644
--- a/core/res/res/values-tr/strings.xml
+++ b/core/res/res/values-tr/strings.xml
@@ -1184,7 +1184,7 @@
<string name="usb_unsupported_audio_accessory_message" msgid="7811865061127547035">"Daha fazla bilgi için dokunun"</string>
<string name="adb_active_notification_title" msgid="6729044778949189918">"USB hata ayıklaması bağlandı"</string>
<string name="adb_active_notification_message" msgid="4948470599328424059">"USB hata ayıklama özelliğini devre dışı bırakmak için dokunun."</string>
- <string name="adb_active_notification_message" product="tv" msgid="8470296818270110396">"USB hata ayıklamasını devre dışı bırakmak için tıklayın."</string>
+ <string name="adb_active_notification_message" product="tv" msgid="8470296818270110396">"USB hata ayıklamasını devre dışı bırakmak için seçin."</string>
<string name="taking_remote_bugreport_notification_title" msgid="6742483073875060934">"Hata raporu alınıyor…"</string>
<string name="share_remote_bugreport_notification_title" msgid="4987095013583691873">"Hata raporu paylaşılsın mı?"</string>
<string name="sharing_remote_bugreport_notification_title" msgid="7572089031496651372">"Hata raporu paylaşılıyor..."</string>
@@ -1769,6 +1769,8 @@
<string name="etws_primary_default_message_tsunami" msgid="1887685943498368548">"Kıyı kesimlerini ve nehir kenarlarını hemen boşaltarak yüksek yerler gibi daha güvenli bölgelere gidin."</string>
<string name="etws_primary_default_message_earthquake_and_tsunami" msgid="998797956848445862">"Sakin olun ve yakınlarda sığınabileceğiniz bir yer bulun."</string>
<string name="etws_primary_default_message_test" msgid="2709597093560037455">"Acil durum mesajları testi"</string>
+ <!-- no translation found for notification_reply_button_accessibility (3621714652387814344) -->
+ <skip />
<string name="etws_primary_default_message_others" msgid="6293148756130398971"></string>
<string name="mmcc_authentication_reject" msgid="7729819349669603406">"SIM\'e izin verilmiyor"</string>
<string name="mmcc_imsi_unknown_in_hlr" msgid="6321202257374418726">"SIM için temel hazırlık yapılmadı"</string>
diff --git a/core/res/res/values-uk/strings.xml b/core/res/res/values-uk/strings.xml
index 79bf1f9..0e318e7 100644
--- a/core/res/res/values-uk/strings.xml
+++ b/core/res/res/values-uk/strings.xml
@@ -1052,7 +1052,7 @@
<string name="clearDefaultHintMsg" msgid="3252584689512077257">"Очистити налаштування за умовчанням у меню Налаштування системи > Програми > Завантажені."</string>
<string name="chooseActivity" msgid="7486876147751803333">"Виберіть дію"</string>
<string name="chooseUsbActivity" msgid="6894748416073583509">"Вибрати програму для пристрою USB"</string>
- <string name="noApplications" msgid="2991814273936504689">"Жодна програма не може виконати цю дію."</string>
+ <string name="noApplications" msgid="2991814273936504689">"Жодний додаток не може виконати цю дію."</string>
<string name="aerr_application" msgid="250320989337856518">"<xliff:g id="APPLICATION">%1$s</xliff:g>: збій у роботі"</string>
<string name="aerr_process" msgid="6201597323218674729">"<xliff:g id="PROCESS">%1$s</xliff:g>: збій у роботі"</string>
<string name="aerr_application_repeated" msgid="3146328699537439573">"Додаток <xliff:g id="APPLICATION">%1$s</xliff:g> періодично перестає працювати"</string>
@@ -1228,7 +1228,7 @@
<string name="usb_unsupported_audio_accessory_message" msgid="7811865061127547035">"Торкніться, щоб дізнатися більше"</string>
<string name="adb_active_notification_title" msgid="6729044778949189918">"Налагодження USB завершено"</string>
<string name="adb_active_notification_message" msgid="4948470599328424059">"Торкніться, щоб вимкнути налагодження USB."</string>
- <string name="adb_active_notification_message" product="tv" msgid="8470296818270110396">"Вибер., щоб вимкн. налагодж. USB."</string>
+ <string name="adb_active_notification_message" product="tv" msgid="8470296818270110396">"Виберіть, щоб вимкнути налагодження за USB"</string>
<string name="taking_remote_bugreport_notification_title" msgid="6742483073875060934">"Створюється повідомлення про помилку…"</string>
<string name="share_remote_bugreport_notification_title" msgid="4987095013583691873">"Надіслати звіт про помилку?"</string>
<string name="sharing_remote_bugreport_notification_title" msgid="7572089031496651372">"Надсилається звіт про помилку…"</string>
@@ -1837,6 +1837,8 @@
<string name="etws_primary_default_message_tsunami" msgid="1887685943498368548">"Негайно евакуюйтеся з прибережних районів і територій поблизу річок у безпечніше місце, як-от на територію на підвищенні."</string>
<string name="etws_primary_default_message_earthquake_and_tsunami" msgid="998797956848445862">"Не хвилюйтеся та знайдіть прихисток поблизу."</string>
<string name="etws_primary_default_message_test" msgid="2709597093560037455">"Перевірка екстрених повідомлень"</string>
+ <!-- no translation found for notification_reply_button_accessibility (3621714652387814344) -->
+ <skip />
<string name="etws_primary_default_message_others" msgid="6293148756130398971"></string>
<string name="mmcc_authentication_reject" msgid="7729819349669603406">"SIM-карта заборонена"</string>
<string name="mmcc_imsi_unknown_in_hlr" msgid="6321202257374418726">"SIM-карту не затверджено"</string>
diff --git a/core/res/res/values-ur/strings.xml b/core/res/res/values-ur/strings.xml
index 38353f1..da90d58 100644
--- a/core/res/res/values-ur/strings.xml
+++ b/core/res/res/values-ur/strings.xml
@@ -118,7 +118,9 @@
<string name="roamingText12" msgid="1189071119992726320">"رومنگ بینر آف"</string>
<string name="roamingTextSearching" msgid="8360141885972279963">"سروس کی تلاش کر رہا ہے"</string>
<string name="wfcRegErrorTitle" msgid="2301376280632110664">"Wi-Fi کالنگ"</string>
- <!-- no translation found for wfcOperatorErrorAlertMessages:0 (3910386316304772394) -->
+ <string-array name="wfcOperatorErrorAlertMessages">
+ <item msgid="3910386316304772394">"Wi-Fi سے کالز کرنے اور پیغامات بھیجنے کے لیے، پہلے اپنے کیریئر سے اس سروس کو سیٹ اپ کرنے کے لیے کہیں۔ پھر ترتیبات سے دوبارہ Wi-Fi کالنگ آن کریں۔ (خراب کوڈ: <xliff:g id="CODE">%1$s</xliff:g>)"</item>
+ </string-array>
<string-array name="wfcOperatorErrorNotificationMessages">
<item msgid="6177300162212449033">"اپنے کیریئر کے ساتھ رجسٹر کریں"</item>
</string-array>
@@ -1768,6 +1770,8 @@
<string name="etws_primary_default_message_tsunami" msgid="1887685943498368548">"ساحلی خطوں اور دریائی کناروں کے علاقوں کو فوری طور پر خالی کر کے اونچے ٹیلے جیسے کسی زیادہ محفوظ مقام پر چلے جائیں۔"</string>
<string name="etws_primary_default_message_earthquake_and_tsunami" msgid="998797956848445862">"پُرسکون رہیں اور قریبی پناہ حاصل کریں۔"</string>
<string name="etws_primary_default_message_test" msgid="2709597093560037455">"ایمرجنسی پیغامات کی جانچ"</string>
+ <!-- no translation found for notification_reply_button_accessibility (3621714652387814344) -->
+ <skip />
<string name="etws_primary_default_message_others" msgid="6293148756130398971"></string>
<string name="mmcc_authentication_reject" msgid="7729819349669603406">"SIM کی اجازت نہیں ہے"</string>
<string name="mmcc_imsi_unknown_in_hlr" msgid="6321202257374418726">"SIM فراہم کردہ نہیں ہے"</string>
diff --git a/core/res/res/values-uz/strings.xml b/core/res/res/values-uz/strings.xml
index b204401..d93a0f5 100644
--- a/core/res/res/values-uz/strings.xml
+++ b/core/res/res/values-uz/strings.xml
@@ -1770,6 +1770,8 @@
<string name="etws_primary_default_message_tsunami" msgid="1887685943498368548">"Qirg‘oq va daryo bo‘ylaridan yuqori tepalik kabi xavfsiz joylarga darhol evakuatsiya qiling."</string>
<string name="etws_primary_default_message_earthquake_and_tsunami" msgid="998797956848445862">"Tinchlaning va yaqin-atrofdan boshpana qidiring."</string>
<string name="etws_primary_default_message_test" msgid="2709597093560037455">"Favqulodda holatlar uchun sinov xabarlari"</string>
+ <!-- no translation found for notification_reply_button_accessibility (3621714652387814344) -->
+ <skip />
<string name="etws_primary_default_message_others" msgid="6293148756130398971"></string>
<string name="mmcc_authentication_reject" msgid="7729819349669603406">"SIM karta ishlatish taqiqlangan"</string>
<string name="mmcc_imsi_unknown_in_hlr" msgid="6321202257374418726">"SIM karta yo‘q"</string>
diff --git a/core/res/res/values-vi/strings.xml b/core/res/res/values-vi/strings.xml
index 689c31f..4e93512 100644
--- a/core/res/res/values-vi/strings.xml
+++ b/core/res/res/values-vi/strings.xml
@@ -1182,7 +1182,7 @@
<string name="usb_notification_message" msgid="3370903770828407960">"Nhấn để biết thêm tùy chọn."</string>
<string name="usb_unsupported_audio_accessory_title" msgid="2256529893240208458">"Phụ kiện âm thanh không được hỗ trợ"</string>
<string name="usb_unsupported_audio_accessory_message" msgid="7811865061127547035">"Nhấn để biết thêm thông tin"</string>
- <string name="adb_active_notification_title" msgid="6729044778949189918">"Gỡ lỗi USB đã được kết nối"</string>
+ <string name="adb_active_notification_title" msgid="6729044778949189918">"Đã kết nối gỡ lỗi USB"</string>
<string name="adb_active_notification_message" msgid="4948470599328424059">"Nhấn để vô hiệu hóa gỡ lỗi USB."</string>
<string name="adb_active_notification_message" product="tv" msgid="8470296818270110396">"Chọn để vô hiệu hóa gỡ lỗi USB."</string>
<string name="taking_remote_bugreport_notification_title" msgid="6742483073875060934">"Đang thu thập báo cáo lỗi…"</string>
@@ -1769,6 +1769,8 @@
<string name="etws_primary_default_message_tsunami" msgid="1887685943498368548">"Ngay lập tức sơ tán khỏi các vùng ven biển và khu vực ven sông để tới một nơi an toàn hơn như vùng đất cao."</string>
<string name="etws_primary_default_message_earthquake_and_tsunami" msgid="998797956848445862">"Hãy bình tĩnh và tìm kiếm nơi trú ẩn gần đó."</string>
<string name="etws_primary_default_message_test" msgid="2709597093560037455">"Kiểm tra thông báo khẩn cấp"</string>
+ <!-- no translation found for notification_reply_button_accessibility (3621714652387814344) -->
+ <skip />
<string name="etws_primary_default_message_others" msgid="6293148756130398971"></string>
<string name="mmcc_authentication_reject" msgid="7729819349669603406">"SIM không được cho phép"</string>
<string name="mmcc_imsi_unknown_in_hlr" msgid="6321202257374418726">"SIM không được cấp phép"</string>
diff --git a/core/res/res/values-zh-rCN/strings.xml b/core/res/res/values-zh-rCN/strings.xml
index d22c09c..0a39be0 100644
--- a/core/res/res/values-zh-rCN/strings.xml
+++ b/core/res/res/values-zh-rCN/strings.xml
@@ -1182,9 +1182,9 @@
<string name="usb_notification_message" msgid="3370903770828407960">"点按即可查看更多选项。"</string>
<string name="usb_unsupported_audio_accessory_title" msgid="2256529893240208458">"音频配件不受支持"</string>
<string name="usb_unsupported_audio_accessory_message" msgid="7811865061127547035">"点按即可了解详情"</string>
- <string name="adb_active_notification_title" msgid="6729044778949189918">"已连接到USB调试"</string>
+ <string name="adb_active_notification_title" msgid="6729044778949189918">"已连接到 USB 调试"</string>
<string name="adb_active_notification_message" msgid="4948470599328424059">"点按即可停用 USB 调试功能。"</string>
- <string name="adb_active_notification_message" product="tv" msgid="8470296818270110396">"选择停用USB调试。"</string>
+ <string name="adb_active_notification_message" product="tv" msgid="8470296818270110396">"选择即可停用 USB 调试功能。"</string>
<string name="taking_remote_bugreport_notification_title" msgid="6742483073875060934">"正在生成错误报告…"</string>
<string name="share_remote_bugreport_notification_title" msgid="4987095013583691873">"要分享错误报告吗?"</string>
<string name="sharing_remote_bugreport_notification_title" msgid="7572089031496651372">"正在分享错误报告…"</string>
@@ -1769,6 +1769,8 @@
<string name="etws_primary_default_message_tsunami" msgid="1887685943498368548">"请立即从沿海和河滨区域撤离到高地等较安全的地方。"</string>
<string name="etws_primary_default_message_earthquake_and_tsunami" msgid="998797956848445862">"请保持冷静,并寻找附近的避难地点。"</string>
<string name="etws_primary_default_message_test" msgid="2709597093560037455">"紧急消息测试"</string>
+ <!-- no translation found for notification_reply_button_accessibility (3621714652387814344) -->
+ <skip />
<string name="etws_primary_default_message_others" msgid="6293148756130398971"></string>
<string name="mmcc_authentication_reject" msgid="7729819349669603406">"不受允许的 SIM 卡"</string>
<string name="mmcc_imsi_unknown_in_hlr" msgid="6321202257374418726">"未配置的 SIM 卡"</string>
diff --git a/core/res/res/values-zh-rHK/strings.xml b/core/res/res/values-zh-rHK/strings.xml
index 76187d8..e9a19ca 100644
--- a/core/res/res/values-zh-rHK/strings.xml
+++ b/core/res/res/values-zh-rHK/strings.xml
@@ -83,7 +83,7 @@
<string name="RestrictedOnAllVoiceTitle" msgid="158800171499150681">"沒有語音/緊急服務"</string>
<string name="RestrictedStateContent" msgid="4278821484643362350">"您所在位置的流動網絡暫不提供這項服務"</string>
<string name="NetworkPreferenceSwitchTitle" msgid="4008877505368566980">"無法連接網絡"</string>
- <string name="NetworkPreferenceSwitchSummary" msgid="1203771446683319957">"如要改善接收品質,請前往 [設定] > [網絡與互聯網] > [流動網絡] > [偏好的網絡類型],然後選取其他網路類型。"</string>
+ <string name="NetworkPreferenceSwitchSummary" msgid="1203771446683319957">"如要接收更強訊號,請前往 [設定] > [網絡與互聯網] > [流動網絡] > [偏好的網絡類型] 更改網絡類型。"</string>
<string name="notification_channel_network_alert" msgid="4427736684338074967">"通知"</string>
<string name="notification_channel_call_forward" msgid="2419697808481833249">"來電轉駁"</string>
<string name="notification_channel_emergency_callback" msgid="6686166232265733921">"緊急回撥模式"</string>
@@ -1769,6 +1769,8 @@
<string name="etws_primary_default_message_tsunami" msgid="1887685943498368548">"請立即從沿海和河岸地區撤離,前往高地等較安全的地點。"</string>
<string name="etws_primary_default_message_earthquake_and_tsunami" msgid="998797956848445862">"請保持冷靜,並尋找附近的避難所。"</string>
<string name="etws_primary_default_message_test" msgid="2709597093560037455">"緊急訊息測試"</string>
+ <!-- no translation found for notification_reply_button_accessibility (3621714652387814344) -->
+ <skip />
<string name="etws_primary_default_message_others" msgid="6293148756130398971"></string>
<string name="mmcc_authentication_reject" msgid="7729819349669603406">"不允許使用 SIM 卡"</string>
<string name="mmcc_imsi_unknown_in_hlr" msgid="6321202257374418726">"無法識別 SIM 卡"</string>
diff --git a/core/res/res/values-zh-rTW/strings.xml b/core/res/res/values-zh-rTW/strings.xml
index 3af7373..a040520e 100644
--- a/core/res/res/values-zh-rTW/strings.xml
+++ b/core/res/res/values-zh-rTW/strings.xml
@@ -1184,7 +1184,7 @@
<string name="usb_unsupported_audio_accessory_message" msgid="7811865061127547035">"輕觸即可瞭解詳情"</string>
<string name="adb_active_notification_title" msgid="6729044778949189918">"已連接 USB 偵錯工具"</string>
<string name="adb_active_notification_message" msgid="4948470599328424059">"輕觸即可停用 USB 偵錯功能。"</string>
- <string name="adb_active_notification_message" product="tv" msgid="8470296818270110396">"選取以停用 USB 偵錯。"</string>
+ <string name="adb_active_notification_message" product="tv" msgid="8470296818270110396">"選取這個選項以停用 USB 偵錯功能。"</string>
<string name="taking_remote_bugreport_notification_title" msgid="6742483073875060934">"正在接收錯誤報告…"</string>
<string name="share_remote_bugreport_notification_title" msgid="4987095013583691873">"要分享錯誤報告嗎?"</string>
<string name="sharing_remote_bugreport_notification_title" msgid="7572089031496651372">"正在分享錯誤報告…"</string>
@@ -1769,6 +1769,8 @@
<string name="etws_primary_default_message_tsunami" msgid="1887685943498368548">"請立即從沿海與河岸地區撤離,前往高地這類較安全的地點。"</string>
<string name="etws_primary_default_message_earthquake_and_tsunami" msgid="998797956848445862">"請保持冷靜並尋找附近的避難地點。"</string>
<string name="etws_primary_default_message_test" msgid="2709597093560037455">"緊急訊息測試"</string>
+ <!-- no translation found for notification_reply_button_accessibility (3621714652387814344) -->
+ <skip />
<string name="etws_primary_default_message_others" msgid="6293148756130398971"></string>
<string name="mmcc_authentication_reject" msgid="7729819349669603406">"不受允許的 SIM 卡"</string>
<string name="mmcc_imsi_unknown_in_hlr" msgid="6321202257374418726">"未佈建的 SIM 卡"</string>
diff --git a/core/res/res/values-zu/strings.xml b/core/res/res/values-zu/strings.xml
index 77bcd84..5ab61a6 100644
--- a/core/res/res/values-zu/strings.xml
+++ b/core/res/res/values-zu/strings.xml
@@ -1769,6 +1769,8 @@
<string name="etws_primary_default_message_tsunami" msgid="1887685943498368548">"Phuma ngokushesha kusukela kuzifunda ezingasolwandle nasezindaweni zemifula uye endaweni ephephile efana nendawo ephakeme."</string>
<string name="etws_primary_default_message_earthquake_and_tsunami" msgid="998797956848445862">"Hlala ubeke umoya phansi uphinde ufune ukukhuselwa eduze."</string>
<string name="etws_primary_default_message_test" msgid="2709597093560037455">"Ukuhlolwa kwemilayezo yesimo esiphuthumayo"</string>
+ <!-- no translation found for notification_reply_button_accessibility (3621714652387814344) -->
+ <skip />
<string name="etws_primary_default_message_others" msgid="6293148756130398971"></string>
<string name="mmcc_authentication_reject" msgid="7729819349669603406">"I-SIM ayivunyelwe"</string>
<string name="mmcc_imsi_unknown_in_hlr" msgid="6321202257374418726">"I-SIM ayinikezelwe"</string>
diff --git a/core/res/res/values/config.xml b/core/res/res/values/config.xml
index 31c6039..802f027 100644
--- a/core/res/res/values/config.xml
+++ b/core/res/res/values/config.xml
@@ -289,6 +289,13 @@
Settings.Global.NETWORK_AVOID_BAD_WIFI. This is the default value of that setting. -->
<integer translatable="false" name="config_networkAvoidBadWifi">1</integer>
+ <!-- If the hardware supports specially marking packets that caused a wakeup of the
+ main CPU, set this value to the mark used. -->
+ <integer name="config_networkWakeupPacketMark">0</integer>
+
+ <!-- Mask to use when checking skb mark defined in config_networkWakeupPacketMark above. -->
+ <integer name="config_networkWakeupPacketMask">0</integer>
+
<!-- Default value for ConnectivityManager.getMultipathPreference() on metered networks. Actual
device behaviour is controlled by Settings.Global.NETWORK_METERED_MULTIPATH_PREFERENCE.
This is the default value of that setting. -->
@@ -404,24 +411,45 @@
-->
<integer translatable="false" name="config_wifi_wakeup_available">0</integer>
- <!-- Array of ConnectivityManager.TYPE_xxxx values allowable for tethering -->
- <!-- Common options are [1, 4] for TYPE_WIFI and TYPE_MOBILE_DUN or
- <!== [0,1,5,7] for TYPE_MOBILE, TYPE_WIFI, TYPE_MOBILE_HIPRI and TYPE_BLUETOOTH -->
- <!-- This list is also modified by code within the framework, including:
+ <!-- Array of ConnectivityManager.TYPE_xxxx values allowable for tethering.
+
+ Common options are [1, 4] for TYPE_WIFI and TYPE_MOBILE_DUN or
+ [1,7,0] for TYPE_WIFI, TYPE_BLUETOOTH, and TYPE_MOBILE.
+
+ This list is also modified by code within the framework, including:
- TYPE_ETHERNET (9) is prepended to this list, and
- - the output of TelephonyManager.getTetherApnRequired()
- determines whether both TYPE_MOBILE (0) and TYPE_HIPRI (5)
- or TYPE_MOBILE_DUN (4) are appended (if not already present).
+
+ - the return value of TelephonyManager.getTetherApnRequired()
+ determines how the array is further modified:
+
+ * DUN_REQUIRED
+ TYPE_MOBILE is removed (if present)
+ TYPE_MOBILE_HIPRI is removed (if present)
+ TYPE_MOBILE_DUN is appended (if not already present)
+
+ * DUN_NOT_REQUIRED
+ TYPE_MOBILE_DUN is removed (if present)
+ TYPE_MOBILE is appended (if not already present)
+ TYPE_MOBILE_HIPRI is appended (if not already present)
+
+ * DUN_UNSPECIFIED
+ if any of TYPE_MOBILE{,_DUN,_HIPRI} are present:
+ change nothing
+ else:
+ TYPE_MOBILE is appended
+ TYPE_MOBILE_HIPRI is appended
For other changes applied to this list, now and in the future, see
com.android.server.connectivity.tethering.TetheringConfiguration.
+
+ Note also: the order of this is important. The first upstream type
+ for which a satisfying network exists is used.
-->
<integer-array translatable="false" name="config_tether_upstream_types">
- <item>0</item>
<item>1</item>
- <item>5</item>
<item>7</item>
+ <item>0</item>
</integer-array>
<!-- If the DUN connection for this CDMA device supports more than just DUN -->
diff --git a/core/res/res/values/dimens.xml b/core/res/res/values/dimens.xml
index fa33d56..9f9c883 100644
--- a/core/res/res/values/dimens.xml
+++ b/core/res/res/values/dimens.xml
@@ -533,6 +533,8 @@
<dimen name="content_rect_bottom_clip_allowance">20dp</dimen>
<dimen name="chooser_grid_padding">0dp</dimen>
+ <!-- Spacing around the background change frome service to non-service -->
+ <dimen name="chooser_service_spacing">8dp</dimen>
<item type="dimen" name="aerr_padding_list_top">15dp</item>
<item type="dimen" name="aerr_padding_list_bottom">8dp</item>
diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml
index 2599b2a..6d6064f 100644
--- a/core/res/res/values/symbols.xml
+++ b/core/res/res/values/symbols.xml
@@ -1827,6 +1827,8 @@
<java-symbol type="integer" name="config_networkNotifySwitchType" />
<java-symbol type="array" name="config_networkNotifySwitches" />
<java-symbol type="integer" name="config_networkAvoidBadWifi" />
+ <java-symbol type="integer" name="config_networkWakeupPacketMark" />
+ <java-symbol type="integer" name="config_networkWakeupPacketMask" />
<java-symbol type="integer" name="config_networkMeteredMultipathPreference" />
<java-symbol type="integer" name="config_notificationsBatteryFullARGB" />
<java-symbol type="integer" name="config_notificationsBatteryLedOff" />
@@ -3050,4 +3052,6 @@
<java-symbol type="string" name="popup_window_default_title" />
<java-symbol type="bool" name="config_showAreaUpdateInfoSettings" />
+ <java-symbol type="layout" name="shutdown_dialog" />
+ <java-symbol type="dimen" name="chooser_service_spacing" />
</resources>
diff --git a/core/tests/coretests/src/android/database/DatabaseGeneralTest.java b/core/tests/coretests/src/android/database/DatabaseGeneralTest.java
index c7cb43d..7800f4a 100644
--- a/core/tests/coretests/src/android/database/DatabaseGeneralTest.java
+++ b/core/tests/coretests/src/android/database/DatabaseGeneralTest.java
@@ -18,11 +18,12 @@
import static android.database.DatabaseUtils.InsertHelper.TABLE_INFO_PRAGMA_COLUMNNAME_INDEX;
import static android.database.DatabaseUtils.InsertHelper.TABLE_INFO_PRAGMA_DEFAULT_INDEX;
+
import android.content.ContentValues;
import android.content.Context;
import android.database.sqlite.SQLiteDatabase;
+import android.database.sqlite.SQLiteDebug;
import android.database.sqlite.SQLiteException;
-import android.os.Handler;
import android.os.Parcel;
import android.test.AndroidTestCase;
import android.test.PerformanceTestCase;
@@ -40,6 +41,9 @@
import java.util.List;
import java.util.Locale;
+/**
+ * Usage: bit FrameworksCoreTests:android.database.DatabaseGeneralTest
+ */
public class DatabaseGeneralTest extends AndroidTestCase implements PerformanceTestCase {
private static final String TAG = "DatabaseGeneralTest";
@@ -68,7 +72,7 @@
@Override
protected void tearDown() throws Exception {
mDatabase.close();
- mDatabaseFile.delete();
+ SQLiteDatabase.deleteDatabase(mDatabaseFile);
super.tearDown();
}
@@ -1044,6 +1048,52 @@
}
}
+ @SmallTest
+ public void testOpenDatabaseLookasideConfig() {
+ // First check that lookaside is active
+ verifyLookasideStats(false);
+ // Reopen test db with lookaside disabled
+ mDatabase.close();
+ SQLiteDatabase.OpenParams params = new SQLiteDatabase.OpenParams.Builder()
+ .setLookasideConfig(0, 0).build();
+ mDatabase = SQLiteDatabase.openDatabase(mDatabaseFile.getPath(), params);
+ verifyLookasideStats(true);
+ }
+
+ @SmallTest
+ public void testOpenParamsSetLookasideConfigValidation() {
+ try {
+ SQLiteDatabase.OpenParams params = new SQLiteDatabase.OpenParams.Builder()
+ .setLookasideConfig(-1, 0).build();
+ fail("Negative slot size should be rejected");
+ } catch (IllegalArgumentException expected) {
+ }
+ try {
+ SQLiteDatabase.OpenParams params = new SQLiteDatabase.OpenParams.Builder()
+ .setLookasideConfig(0, -10).build();
+ fail("Negative slot count should be rejected");
+ } catch (IllegalArgumentException expected) {
+ }
+ }
+
+ void verifyLookasideStats(boolean expectDisabled) {
+ boolean dbStatFound = false;
+ SQLiteDebug.PagerStats info = SQLiteDebug.getDatabaseInfo();
+ for (SQLiteDebug.DbStats dbStat : info.dbStats) {
+ if (dbStat.dbName.endsWith(mDatabaseFile.getName())) {
+ dbStatFound = true;
+ Log.i(TAG, "Lookaside for " + dbStat.dbName + " " + dbStat.lookaside);
+ if (expectDisabled) {
+ assertTrue("lookaside slots count should be zero", dbStat.lookaside == 0);
+ } else {
+ assertTrue("lookaside slots count should be greater than zero",
+ dbStat.lookaside > 0);
+ }
+ }
+ }
+ assertTrue("No dbstat found for " + mDatabaseFile.getName(), dbStatFound);
+ }
+
@LargeTest
public void testDefaultDatabaseErrorHandler() {
DefaultDatabaseErrorHandler errorHandler = new DefaultDatabaseErrorHandler();
diff --git a/core/tests/coretests/src/android/database/SQLiteOpenHelperTest.java b/core/tests/coretests/src/android/database/SQLiteOpenHelperTest.java
new file mode 100644
index 0000000..75eeb93
--- /dev/null
+++ b/core/tests/coretests/src/android/database/SQLiteOpenHelperTest.java
@@ -0,0 +1,171 @@
+/*
+ * 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.database;
+
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
+
+import android.content.Context;
+import android.database.sqlite.SQLiteDatabase;
+import android.database.sqlite.SQLiteDatabaseConfiguration;
+import android.database.sqlite.SQLiteDebug;
+import android.database.sqlite.SQLiteOpenHelper;
+import android.support.test.InstrumentationRegistry;
+import android.support.test.filters.SmallTest;
+import android.support.test.runner.AndroidJUnit4;
+import android.util.Log;
+
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * Tests for {@link SQLiteOpenHelper}
+ *
+ * <p>Run with: bit FrameworksCoreTests:android.database.SQLiteOpenHelperTest
+ */
+@RunWith(AndroidJUnit4.class)
+@SmallTest
+public class SQLiteOpenHelperTest {
+ private static final String TAG = "SQLiteOpenHelperTest";
+
+ private TestHelper mTestHelper;
+ private Context mContext;
+ private List<SQLiteOpenHelper> mHelpersToClose;
+
+ private static class TestHelper extends SQLiteOpenHelper {
+ TestHelper(Context context) { // In-memory
+ super(context, null, null, 1);
+ }
+
+ TestHelper(Context context, String name) {
+ super(context, name, null, 1);
+ }
+
+ @Override
+ public void onCreate(SQLiteDatabase db) {
+ }
+
+ @Override
+ public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
+ }
+ }
+
+ @Before
+ public void setup() {
+ mContext = InstrumentationRegistry.getContext();
+ mTestHelper = new TestHelper(mContext, "openhelper_test");
+ mHelpersToClose = new ArrayList<>();
+ mHelpersToClose.add(mTestHelper);
+ }
+
+ @After
+ public void teardown() {
+ for (SQLiteOpenHelper helper : mHelpersToClose) {
+ try {
+ helper.close();
+ if (mTestHelper.getDatabaseName() != null) {
+ SQLiteDatabase.deleteDatabase(
+ mContext.getDatabasePath(mTestHelper.getDatabaseName()));
+ }
+ } catch (RuntimeException ex) {
+ Log.w(TAG, "Error occured when closing db helper " + helper, ex);
+ }
+ }
+ }
+
+ @Test
+ public void testLookasideDefault() throws Exception {
+ assertNotNull(mTestHelper.getWritableDatabase());
+ verifyLookasideStats(false);
+ }
+
+ @Test
+ public void testLookasideDisabled() throws Exception {
+ mTestHelper.setLookasideConfig(0, 0);
+ assertNotNull(mTestHelper.getWritableDatabase());
+ verifyLookasideStats(true);
+ }
+
+ @Test
+ public void testInMemoryLookasideDisabled() throws Exception {
+ TestHelper memHelper = new TestHelper(mContext);
+ mHelpersToClose.add(memHelper);
+ memHelper.setLookasideConfig(0, 0);
+ assertNotNull(memHelper.getWritableDatabase());
+ verifyLookasideStats(SQLiteDatabaseConfiguration.MEMORY_DB_PATH, true);
+ }
+
+ @Test
+ public void testInMemoryLookasideDefault() throws Exception {
+ TestHelper memHelper = new TestHelper(mContext);
+ mHelpersToClose.add(memHelper);
+ assertNotNull(memHelper.getWritableDatabase());
+ verifyLookasideStats(SQLiteDatabaseConfiguration.MEMORY_DB_PATH, false);
+ }
+
+ @Test
+ public void testSetLookasideConfigValidation() {
+ try {
+ mTestHelper.setLookasideConfig(-1, 0);
+ fail("Negative slot size should be rejected");
+ } catch (IllegalArgumentException expected) {
+ }
+ try {
+ mTestHelper.setLookasideConfig(0, -10);
+ fail("Negative slot count should be rejected");
+ } catch (IllegalArgumentException expected) {
+ }
+ try {
+ mTestHelper.setLookasideConfig(1, 0);
+ fail("Illegal config should be rejected");
+ } catch (IllegalArgumentException expected) {
+ }
+ try {
+ mTestHelper.setLookasideConfig(0, 1);
+ fail("Illegal config should be rejected");
+ } catch (IllegalArgumentException expected) {
+ }
+ }
+
+ private void verifyLookasideStats(boolean expectDisabled) {
+ verifyLookasideStats(mTestHelper.getDatabaseName(), expectDisabled);
+ }
+
+ private static void verifyLookasideStats(String dbName, boolean expectDisabled) {
+ boolean dbStatFound = false;
+ SQLiteDebug.PagerStats info = SQLiteDebug.getDatabaseInfo();
+ for (SQLiteDebug.DbStats dbStat : info.dbStats) {
+ if (dbStat.dbName.endsWith(dbName)) {
+ dbStatFound = true;
+ Log.i(TAG, "Lookaside for " + dbStat.dbName + " " + dbStat.lookaside);
+ if (expectDisabled) {
+ assertTrue("lookaside slots count should be zero", dbStat.lookaside == 0);
+ } else {
+ assertTrue("lookaside slots count should be greater than zero",
+ dbStat.lookaside > 0);
+ }
+ }
+ }
+ assertTrue("No dbstat found for " + dbName, dbStatFound);
+ }
+}
diff --git a/core/tests/coretests/src/android/database/run_newdb_perf_test.sh b/core/tests/coretests/src/android/database/run_newdb_perf_test.sh
new file mode 100755
index 0000000..10a62e6
--- /dev/null
+++ b/core/tests/coretests/src/android/database/run_newdb_perf_test.sh
@@ -0,0 +1,28 @@
+#!/bin/bash -
+# 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.
+
+make -j44 FrameworksCoreTests
+adb install -r -g ${ANDROID_PRODUCT_OUT}/data/app/FrameworksCoreTests/FrameworksCoreTests.apk
+adb logcat -c
+
+echo "Running benchmark 5 times"
+for i in {1..5}
+do
+ adb shell am instrument -e class 'android.database.NewDatabasePerformanceTestSuite' -w 'com.android.frameworks.coretests/android.support.test.runner.AndroidJUnitRunner'
+done
+
+adb logcat -d > /tmp/testlogcat.txt
+
+python frameworks/base/core/tests/coretests/src/android/database/process_newdb_perf_test_logs.py /tmp/testlogcat.txt
\ No newline at end of file
diff --git a/core/tests/coretests/src/android/util/SparseLongArrayTest.java b/core/tests/coretests/src/android/util/SparseLongArrayTest.java
new file mode 100644
index 0000000..5a5e893
--- /dev/null
+++ b/core/tests/coretests/src/android/util/SparseLongArrayTest.java
@@ -0,0 +1,156 @@
+/*
+ * Copyright (C) 2007 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.util;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
+
+import android.support.annotation.NonNull;
+import android.support.test.filters.SmallTest;
+import android.support.test.runner.AndroidJUnit4;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import java.util.Random;
+
+/**
+ * Internal tests for {@link SparseLongArray}.
+ */
+@SmallTest
+@RunWith(AndroidJUnit4.class)
+public class SparseLongArrayTest {
+
+ private static final int TEST_SIZE = 1000;
+
+ private SparseLongArray mSparseLongArray;
+ private int[] mKeys;
+ private long[] mValues;
+ private Random mRandom;
+
+ private static boolean isSame(@NonNull SparseLongArray array1,
+ @NonNull SparseLongArray array2) {
+ if (array1.size() != array2.size()) {
+ return false;
+ }
+ for (int i = 0; i < array1.size(); i++) {
+ if (array1.keyAt(i) != array2.keyAt(i) || array1.valueAt(i) != array2.valueAt(i)) {
+ return false;
+ }
+ }
+ return true;
+ }
+
+ private void assertRemoved(int startIndex, int endIndex) {
+ for (int i = 0; i < TEST_SIZE; i++) {
+ if (i >= startIndex && i <= endIndex) {
+ assertEquals("Entry not removed", Long.MIN_VALUE,
+ mSparseLongArray.get(mKeys[i], Long.MIN_VALUE));
+ } else {
+ assertEquals("Untouched entry corrupted", mValues[i],
+ mSparseLongArray.get(mKeys[i]));
+ }
+ }
+ }
+
+ /**
+ * Generates a sorted array of distinct and random keys
+ *
+ * @param size the number of keys to return in the array. Should be < (2^31)/1000.
+ * @return the array of keys
+ */
+ private int[] generateRandomKeys(int size) {
+ final int[] keys = new int[size];
+ keys[0] = -1 * mRandom.nextInt(size * 500);
+ for (int i = 1; i < size; i++) {
+ keys[i] = keys[i - 1] + 1 + mRandom.nextInt(1000);
+ assertTrue(keys[i] > keys[i - 1]);
+ }
+ return keys;
+ }
+
+ @Before
+ public void setUp() {
+ mSparseLongArray = new SparseLongArray();
+ mRandom = new Random(12345);
+ mKeys = generateRandomKeys(TEST_SIZE);
+ mValues = new long[TEST_SIZE];
+ for (int i = 0; i < TEST_SIZE; i++) {
+ mValues[i] = i + 1;
+ mSparseLongArray.put(mKeys[i], mValues[i]);
+ }
+ }
+
+ @Test
+ public void testRemoveAtRange_removeHead() {
+ mSparseLongArray.removeAtRange(0, 100);
+ assertEquals(TEST_SIZE - 100, mSparseLongArray.size());
+ assertRemoved(0, 99);
+ }
+
+ @Test
+ public void testRemoveAtRange_removeTail() {
+ mSparseLongArray.removeAtRange(TEST_SIZE - 200, 200);
+ assertEquals(TEST_SIZE - 200, mSparseLongArray.size());
+ assertRemoved(TEST_SIZE - 200, TEST_SIZE - 1);
+ }
+
+ @Test
+ public void testRemoveAtRange_removeOverflow() {
+ mSparseLongArray.removeAtRange(TEST_SIZE - 100, 200);
+ assertEquals(TEST_SIZE - 100, mSparseLongArray.size());
+ assertRemoved(TEST_SIZE - 100, TEST_SIZE - 1);
+ }
+
+ @Test
+ public void testRemoveAtRange_removeEverything() {
+ mSparseLongArray.removeAtRange(0, TEST_SIZE);
+ assertEquals(0, mSparseLongArray.size());
+ assertRemoved(0, TEST_SIZE - 1);
+ }
+
+ @Test
+ public void testRemoveAtRange_removeMiddle() {
+ mSparseLongArray.removeAtRange(200, 200);
+ assertEquals(TEST_SIZE - 200, mSparseLongArray.size());
+ assertRemoved(200, 399);
+ }
+
+ @Test
+ public void testRemoveAtRange_removeSingle() {
+ mSparseLongArray.removeAtRange(300, 1);
+ assertEquals(TEST_SIZE - 1, mSparseLongArray.size());
+ assertRemoved(300, 300);
+ }
+
+ @Test
+ public void testRemoveAtRange_compareRemoveAt() {
+ final SparseLongArray sparseLongArray2 = mSparseLongArray.clone();
+ assertTrue(isSame(mSparseLongArray, sparseLongArray2));
+
+ final int startIndex = 101;
+ final int endIndex = 200;
+ mSparseLongArray.removeAtRange(startIndex, endIndex - startIndex + 1);
+ for (int i = endIndex; i >= startIndex; i--) {
+ sparseLongArray2.removeAt(i);
+ }
+ assertEquals(TEST_SIZE - (endIndex - startIndex + 1), mSparseLongArray.size());
+ assertRemoved(startIndex, endIndex);
+ assertTrue(isSame(sparseLongArray2, mSparseLongArray));
+ }
+}
diff --git a/core/tests/coretests/src/com/android/internal/os/BatteryStatsBackgroundStatsTest.java b/core/tests/coretests/src/com/android/internal/os/BatteryStatsBackgroundStatsTest.java
index c539f78..7a6b8d5f 100644
--- a/core/tests/coretests/src/com/android/internal/os/BatteryStatsBackgroundStatsTest.java
+++ b/core/tests/coretests/src/com/android/internal/os/BatteryStatsBackgroundStatsTest.java
@@ -280,7 +280,7 @@
// Stop timer
curr = 1000 * (clocks.realtime = clocks.uptime = 161);
- bi.noteJobFinishLocked(jobName, UID);
+ bi.noteJobFinishLocked(jobName, UID, 0);
// Move to background
curr = 1000 * (clocks.realtime = clocks.uptime = 202);
@@ -296,7 +296,7 @@
// Stop timer
curr = 1000 * (clocks.realtime = clocks.uptime = 409);
- bi.noteJobFinishLocked(jobName, UID);
+ bi.noteJobFinishLocked(jobName, UID, 0);
// Test
curr = 1000 * (clocks.realtime = clocks.uptime = 657);
@@ -319,7 +319,7 @@
final String jobName2 = "second_job";
bi.noteJobStartLocked(jobName2, UID);
assertEquals(2, bi.getUidStats().get(UID).getJobStats().size());
- bi.noteJobFinishLocked(jobName2, UID);
+ bi.noteJobFinishLocked(jobName2, UID, 0);
}
@SmallTest
diff --git a/core/tests/coretests/src/com/android/internal/os/BatteryStatsHelperTest.java b/core/tests/coretests/src/com/android/internal/os/BatteryStatsHelperTest.java
index f01c33f..e81f678 100644
--- a/core/tests/coretests/src/com/android/internal/os/BatteryStatsHelperTest.java
+++ b/core/tests/coretests/src/com/android/internal/os/BatteryStatsHelperTest.java
@@ -18,9 +18,12 @@
package com.android.internal.os;
+import static android.os.BatteryStats.Uid.PROCESS_STATE_TOP;
+
import static com.google.common.truth.Truth.assertThat;
import static org.mockito.Matchers.any;
+import static org.mockito.Matchers.anyInt;
import static org.mockito.Matchers.anyLong;
import static org.mockito.Matchers.eq;
import static org.mockito.Mockito.RETURNS_DEEP_STUBS;
@@ -54,11 +57,16 @@
@SmallTest
public class BatteryStatsHelperTest extends TestCase {
private static final long TIME_FOREGROUND_ACTIVITY_ZERO = 0;
- private static final long TIME_FOREGROUND_ACTIVITY = 100 * DateUtils.MINUTE_IN_MILLIS;
+ private static final long TIME_FOREGROUND_ACTIVITY = 100 * DateUtils.MINUTE_IN_MILLIS * 1000;
+ private static final long TIME_STATE_FOREGROUND_MS = 10 * DateUtils.MINUTE_IN_MILLIS;
+ private static final long TIME_STATE_FOREGROUND_US = TIME_STATE_FOREGROUND_MS * 1000;
private static final int UID = 123456;
private static final double BATTERY_SCREEN_USAGE = 300;
private static final double BATTERY_SYSTEM_USAGE = 600;
+ private static final double BATTERY_WIFI_USAGE = 200;
+ private static final double BATTERY_IDLE_USAGE = 600;
+ private static final double BATTERY_BLUETOOTH_USAGE = 300;
private static final double BATTERY_OVERACCOUNTED_USAGE = 500;
private static final double BATTERY_UNACCOUNTED_USAGE = 700;
private static final double BATTERY_APP_USAGE = 100;
@@ -68,6 +76,12 @@
@Mock
private BatteryStats.Uid mUid;
@Mock
+ private BatterySipper mWifiBatterySipper;
+ @Mock
+ private BatterySipper mBluetoothBatterySipper;
+ @Mock
+ private BatterySipper mIdleBatterySipper;
+ @Mock
private BatterySipper mNormalBatterySipper;
@Mock
private BatterySipper mScreenBatterySipper;
@@ -109,6 +123,15 @@
mUnaccountedBatterySipper.drainType = BatterySipper.DrainType.UNACCOUNTED;
mUnaccountedBatterySipper.totalPowerMah = BATTERY_UNACCOUNTED_USAGE;
+ mWifiBatterySipper.drainType = BatterySipper.DrainType.WIFI;
+ mWifiBatterySipper.totalPowerMah = BATTERY_WIFI_USAGE;
+
+ mBluetoothBatterySipper.drainType = BatterySipper.DrainType.BLUETOOTH;
+ mBluetoothBatterySipper.totalPowerMah = BATTERY_BLUETOOTH_USAGE;
+
+ mIdleBatterySipper.drainType = BatterySipper.DrainType.IDLE;
+ mIdleBatterySipper.totalPowerMah = BATTERY_IDLE_USAGE;
+
mContext = InstrumentationRegistry.getContext();
mBatteryStatsHelper = spy(new BatteryStatsHelper(mContext));
mBatteryStatsHelper.setPackageManager(mPackageManager);
@@ -165,6 +188,9 @@
sippers.add(mSystemBatterySipper);
sippers.add(mOvercountedBatterySipper);
sippers.add(mUnaccountedBatterySipper);
+ sippers.add(mWifiBatterySipper);
+ sippers.add(mBluetoothBatterySipper);
+ sippers.add(mIdleBatterySipper);
doReturn(true).when(mBatteryStatsHelper).isTypeSystem(mSystemBatterySipper);
doNothing().when(mBatteryStatsHelper).smearScreenBatterySipper(any(), any());
@@ -219,6 +245,19 @@
assertThat(mBatteryStatsHelper.isTypeService(mNormalBatterySipper)).isTrue();
}
+ @Test
+ public void testGetProcessForegroundTimeMs_largerActivityTime_returnMinTime() {
+ doReturn(TIME_STATE_FOREGROUND_US + 500).when(mBatteryStatsHelper)
+ .getForegroundActivityTotalTimeUs(eq(mUid), anyLong());
+ doReturn(TIME_STATE_FOREGROUND_US).when(mUid).getProcessStateTime(eq(PROCESS_STATE_TOP),
+ anyLong(), anyInt());
+
+ final long time = mBatteryStatsHelper.getProcessForegroundTimeMs(mUid,
+ BatteryStats.STATS_SINCE_CHARGED);
+
+ assertThat(time).isEqualTo(TIME_STATE_FOREGROUND_MS);
+ }
+
private BatterySipper createTestSmearBatterySipper(long activityTime, double totalPowerMah,
int uidCode, boolean isUidNull) {
final BatterySipper sipper = mock(BatterySipper.class);
@@ -227,8 +266,8 @@
doReturn(uidCode).when(sipper).getUid();
if (!isUidNull) {
final BatteryStats.Uid uid = mock(BatteryStats.Uid.class, RETURNS_DEEP_STUBS);
- doReturn(activityTime).when(mBatteryStatsHelper).getForegroundActivityTotalTimeMs(
- eq(uid), anyLong());
+ doReturn(activityTime).when(mBatteryStatsHelper).getProcessForegroundTimeMs(eq(uid),
+ anyInt());
doReturn(uidCode).when(uid).getUid();
sipper.uidObj = uid;
}
@@ -236,5 +275,4 @@
return sipper;
}
-
}
diff --git a/core/tests/coretests/src/com/android/internal/os/BatteryStatsUserLifecycleTests.java b/core/tests/coretests/src/com/android/internal/os/BatteryStatsUserLifecycleTests.java
new file mode 100644
index 0000000..450473d
--- /dev/null
+++ b/core/tests/coretests/src/com/android/internal/os/BatteryStatsUserLifecycleTests.java
@@ -0,0 +1,167 @@
+/*
+ * 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.internal.os;
+
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assume.assumeTrue;
+
+import android.app.ActivityManager;
+import android.app.IActivityManager;
+import android.app.IStopUserCallback;
+import android.content.Context;
+import android.content.pm.UserInfo;
+import android.os.RemoteException;
+import android.os.UserHandle;
+import android.os.UserManager;
+import android.support.test.InstrumentationRegistry;
+import android.support.test.filters.LargeTest;
+import android.support.test.runner.AndroidJUnit4;
+import android.support.test.uiautomator.UiDevice;
+import android.util.ArraySet;
+
+import org.junit.After;
+import org.junit.Before;
+import org.junit.BeforeClass;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.TimeUnit;
+
+@LargeTest
+@RunWith(AndroidJUnit4.class)
+public class BatteryStatsUserLifecycleTests {
+
+ private static final long POLL_INTERVAL_MS = 500;
+ private static final long USER_REMOVE_TIMEOUT_MS = 5_000;
+ private static final long STOP_USER_TIMEOUT_MS = 10_000;
+ private static final long BATTERYSTATS_POLLING_TIMEOUT_MS = 5_000;
+
+ private static final String CPU_DATA_TAG = "cpu";
+ private static final String CPU_FREQ_DATA_TAG = "ctf";
+
+ private int mTestUserId = UserHandle.USER_NULL;
+ private Context mContext;
+ private UserManager mUm;
+ private IActivityManager mIam;
+
+ @BeforeClass
+ public static void setUpOnce() {
+ assumeTrue(UserManager.getMaxSupportedUsers() > 1);
+ }
+
+ @Before
+ public void setUp() throws Exception {
+ mContext = InstrumentationRegistry.getTargetContext();
+ mUm = UserManager.get(mContext);
+ mIam = ActivityManager.getService();
+ final UserInfo user = mUm.createUser("Test_user_" + System.currentTimeMillis() / 1000, 0);
+ assertNotNull("Unable to create test user", user);
+ mTestUserId = user.id;
+ batteryOnScreenOff();
+ }
+
+ @Test
+ public void testNoCpuDataForRemovedUser() throws Exception {
+ mIam.startUserInBackground(mTestUserId);
+ waitUntilTrue("No uids for started user " + mTestUserId,
+ () -> getNumberOfUidsInBatteryStats() > 0, BATTERYSTATS_POLLING_TIMEOUT_MS);
+
+ CountDownLatch stopUserLatch = new CountDownLatch(1);
+ mIam.stopUser(mTestUserId, true, new IStopUserCallback.Stub() {
+ @Override
+ public void userStopped(int userId) throws RemoteException {
+ stopUserLatch.countDown();
+ }
+
+ @Override
+ public void userStopAborted(int userId) throws RemoteException {
+ }
+ });
+ assertTrue("User " + mTestUserId + " could not be stopped",
+ stopUserLatch.await(STOP_USER_TIMEOUT_MS, TimeUnit.MILLISECONDS));
+
+ mUm.removeUser(mTestUserId);
+ waitUntilTrue("Unable to remove user " + mTestUserId, () -> {
+ for (UserInfo user : mUm.getUsers()) {
+ if (user.id == mTestUserId) {
+ return false;
+ }
+ }
+ return true;
+ }, USER_REMOVE_TIMEOUT_MS);
+ waitUntilTrue("Uids still found for removed user " + mTestUserId,
+ () -> getNumberOfUidsInBatteryStats() == 0, BATTERYSTATS_POLLING_TIMEOUT_MS);
+ }
+
+ @After
+ public void tearDown() throws Exception {
+ batteryOffScreenOn();
+ if (mTestUserId != UserHandle.USER_NULL) {
+ mUm.removeUser(mTestUserId);
+ }
+ }
+
+ private int getNumberOfUidsInBatteryStats() throws Exception {
+ ArraySet<Integer> uids = new ArraySet<>();
+ final String dumpsys = executeShellCommand("dumpsys batterystats --checkin");
+ for (String line : dumpsys.split("\n")) {
+ final String[] parts = line.trim().split(",");
+ if (parts.length < 5 ||
+ (!parts[3].equals(CPU_DATA_TAG) && !parts[3].equals(CPU_FREQ_DATA_TAG))) {
+ continue;
+ }
+ try {
+ final int uid = Integer.parseInt(parts[1]);
+ if (UserHandle.getUserId(uid) == mTestUserId) {
+ uids.add(uid);
+ }
+ } catch (NumberFormatException nexc) {
+ // ignore
+ }
+ }
+ return uids.size();
+ }
+
+ protected void batteryOnScreenOff() throws Exception {
+ executeShellCommand("dumpsys battery unplug");
+ executeShellCommand("dumpsys batterystats enable pretend-screen-off");
+ }
+
+ protected void batteryOffScreenOn() throws Exception {
+ executeShellCommand("dumpsys battery reset");
+ executeShellCommand("dumpsys batterystats disable pretend-screen-off");
+ }
+
+ private String executeShellCommand(String cmd) throws Exception {
+ return UiDevice.getInstance(
+ InstrumentationRegistry.getInstrumentation()).executeShellCommand(cmd);
+ }
+
+ private void waitUntilTrue(String message, Condition condition, long timeout) throws Exception {
+ final long deadLine = System.currentTimeMillis() + timeout;
+ while (System.currentTimeMillis() <= deadLine && !condition.isTrue()) {
+ Thread.sleep(POLL_INTERVAL_MS);
+ }
+ assertTrue(message, condition.isTrue());
+ }
+
+ private interface Condition {
+ boolean isTrue() throws Exception;
+ }
+}
diff --git a/data/etc/privapp-permissions-platform.xml b/data/etc/privapp-permissions-platform.xml
index 8bfb6f3..19cc7b3 100644
--- a/data/etc/privapp-permissions-platform.xml
+++ b/data/etc/privapp-permissions-platform.xml
@@ -147,6 +147,7 @@
<permission name="android.permission.MANAGE_USERS"/>
<permission name="android.permission.MODIFY_PHONE_STATE"/>
<permission name="android.permission.PERFORM_CDMA_PROVISIONING"/>
+ <permission name="android.permission.READ_NETWORK_USAGE_HISTORY"/>
<permission name="android.permission.READ_PRIVILEGED_PHONE_STATE"/>
<permission name="android.permission.READ_SEARCH_INDEXABLES"/>
<permission name="android.permission.REBOOT"/>
diff --git a/graphics/java/android/graphics/drawable/TransitionDrawable.java b/graphics/java/android/graphics/drawable/TransitionDrawable.java
index 0122338..3dfd680 100644
--- a/graphics/java/android/graphics/drawable/TransitionDrawable.java
+++ b/graphics/java/android/graphics/drawable/TransitionDrawable.java
@@ -118,6 +118,18 @@
}
/**
+ * Show the second layer on top of the first layer immediately
+ *
+ * @hide
+ */
+ public void showSecondLayer() {
+ mAlpha = 255;
+ mReverse = false;
+ mTransitionState = TRANSITION_NONE;
+ invalidateSelf();
+ }
+
+ /**
* Show only the first layer.
*/
public void resetTransition() {
diff --git a/legacy-test/Android.mk b/legacy-test/Android.mk
index ae5ae1a..ef2950b 100644
--- a/legacy-test/Android.mk
+++ b/legacy-test/Android.mk
@@ -31,6 +31,20 @@
include $(BUILD_JAVA_LIBRARY)
+# Build the repackaged-legacy-test library
+# ========================================
+# This contains repackaged versions of the classes from legacy-test.
+include $(CLEAR_VARS)
+
+LOCAL_SRC_FILES := $(call all-java-files-under, src)
+
+LOCAL_MODULE := repackaged-legacy-test
+LOCAL_NO_STANDARD_LIBRARIES := true
+LOCAL_JAVA_LIBRARIES := core-oj core-libart framework
+LOCAL_JARJAR_RULES := $(LOCAL_PATH)/jarjar-rules.txt
+
+include $(BUILD_STATIC_JAVA_LIBRARY)
+
# Generate the stub source files for legacy.test.stubs
# ====================================================
include $(CLEAR_VARS)
diff --git a/legacy-test/jarjar-rules.txt b/legacy-test/jarjar-rules.txt
new file mode 100644
index 0000000..9077e6f
--- /dev/null
+++ b/legacy-test/jarjar-rules.txt
@@ -0,0 +1,2 @@
+rule junit.** repackaged.junit.@1
+rule android.test.** repackaged.android.test.@1
diff --git a/libs/hwui/Android.bp b/libs/hwui/Android.bp
index 303d05f..113a477 100644
--- a/libs/hwui/Android.bp
+++ b/libs/hwui/Android.bp
@@ -201,6 +201,8 @@
"PathParser.cpp",
"PathTessellator.cpp",
"PixelBuffer.cpp",
+ "ProfileData.cpp",
+ "ProfileDataContainer.cpp",
"ProfileRenderer.cpp",
"Program.cpp",
"ProgramCache.cpp",
diff --git a/libs/hwui/JankTracker.cpp b/libs/hwui/JankTracker.cpp
index 028d9f7..9d11828 100644
--- a/libs/hwui/JankTracker.cpp
+++ b/libs/hwui/JankTracker.cpp
@@ -34,14 +34,6 @@
namespace android {
namespace uirenderer {
-static const char* JANK_TYPE_NAMES[] = {
- "Missed Vsync",
- "High input latency",
- "Slow UI thread",
- "Slow bitmap uploads",
- "Slow issue draw commands",
-};
-
struct Comparison {
FrameInfoIndex start;
FrameInfoIndex end;
@@ -68,70 +60,13 @@
*/
static const int64_t EXEMPT_FRAMES_FLAGS = FrameInfoFlags::SurfaceCanvas;
-// The bucketing algorithm controls so to speak
-// If a frame is <= to this it goes in bucket 0
-static const uint32_t kBucketMinThreshold = 5;
-// If a frame is > this, start counting in increments of 2ms
-static const uint32_t kBucket2msIntervals = 32;
-// If a frame is > this, start counting in increments of 4ms
-static const uint32_t kBucket4msIntervals = 48;
-
// For testing purposes to try and eliminate test infra overhead we will
// consider any unknown delay of frame start as part of the test infrastructure
// and filter it out of the frame profile data
static FrameInfoIndex sFrameStart = FrameInfoIndex::IntendedVsync;
-// The interval of the slow frame histogram
-static const uint32_t kSlowFrameBucketIntervalMs = 50;
-// The start point of the slow frame bucket in ms
-static const uint32_t kSlowFrameBucketStartMs = 150;
-
-// This will be called every frame, performance sensitive
-// Uses bit twiddling to avoid branching while achieving the packing desired
-static uint32_t frameCountIndexForFrameTime(nsecs_t frameTime) {
- uint32_t index = static_cast<uint32_t>(ns2ms(frameTime));
- // If index > kBucketMinThreshold mask will be 0xFFFFFFFF as a result
- // of negating 1 (twos compliment, yaay) else mask will be 0
- uint32_t mask = -(index > kBucketMinThreshold);
- // If index > threshold, this will essentially perform:
- // amountAboveThreshold = index - threshold;
- // index = threshold + (amountAboveThreshold / 2)
- // However if index is <= this will do nothing. It will underflow, do
- // a right shift by 0 (no-op), then overflow back to the original value
- index = ((index - kBucket4msIntervals) >> (index > kBucket4msIntervals))
- + kBucket4msIntervals;
- index = ((index - kBucket2msIntervals) >> (index > kBucket2msIntervals))
- + kBucket2msIntervals;
- // If index was < minThreshold at the start of all this it's going to
- // be a pretty garbage value right now. However, mask is 0 so we'll end
- // up with the desired result of 0.
- index = (index - kBucketMinThreshold) & mask;
- return index;
-}
-
-// Only called when dumping stats, less performance sensitive
-int32_t JankTracker::frameTimeForFrameCountIndex(uint32_t index) {
- index = index + kBucketMinThreshold;
- if (index > kBucket2msIntervals) {
- index += (index - kBucket2msIntervals);
- }
- if (index > kBucket4msIntervals) {
- // This works because it was already doubled by the above if
- // 1 is added to shift slightly more towards the middle of the bucket
- index += (index - kBucket4msIntervals) + 1;
- }
- return index;
-}
-
-int32_t JankTracker::frameTimeForSlowFrameCountIndex(uint32_t index) {
- return (index * kSlowFrameBucketIntervalMs) + kSlowFrameBucketStartMs;
-}
-
-JankTracker::JankTracker(const DisplayInfo& displayInfo) {
- // By default this will use malloc memory. It may be moved later to ashmem
- // if there is shared space for it and a request comes in to do that.
- mData = new ProfileData;
- reset();
+JankTracker::JankTracker(ProfileDataContainer* globalData, const DisplayInfo& displayInfo) {
+ mGlobalData = globalData;
nsecs_t frameIntervalNanos = static_cast<nsecs_t>(1_s / displayInfo.fps);
#if USE_HWC2
nsecs_t sfOffset = frameIntervalNanos - (displayInfo.presentationDeadline - 1_ms);
@@ -151,82 +86,6 @@
setFrameInterval(frameIntervalNanos);
}
-JankTracker::~JankTracker() {
- freeData();
-}
-
-void JankTracker::freeData() {
- if (mIsMapped) {
- munmap(mData, sizeof(ProfileData));
- } else {
- delete mData;
- }
- mIsMapped = false;
- mData = nullptr;
-}
-
-void JankTracker::rotateStorage() {
- // If we are mapped we want to stop using the ashmem backend and switch to malloc
- // We are expecting a switchStorageToAshmem call to follow this, but it's not guaranteed
- // If we aren't sitting on top of ashmem then just do a reset() as it's functionally
- // equivalent do a free, malloc, reset.
- if (mIsMapped) {
- freeData();
- mData = new ProfileData;
- }
- reset();
-}
-
-void JankTracker::switchStorageToAshmem(int ashmemfd) {
- int regionSize = ashmem_get_size_region(ashmemfd);
- if (regionSize < 0) {
- int err = errno;
- ALOGW("Failed to get ashmem region size from fd %d, err %d %s", ashmemfd, err, strerror(err));
- return;
- }
- if (regionSize < static_cast<int>(sizeof(ProfileData))) {
- ALOGW("Ashmem region is too small! Received %d, required %u",
- regionSize, static_cast<unsigned int>(sizeof(ProfileData)));
- return;
- }
- ProfileData* newData = reinterpret_cast<ProfileData*>(
- mmap(NULL, sizeof(ProfileData), PROT_READ | PROT_WRITE,
- MAP_SHARED, ashmemfd, 0));
- if (newData == MAP_FAILED) {
- int err = errno;
- ALOGW("Failed to move profile data to ashmem fd %d, error = %d",
- ashmemfd, err);
- return;
- }
-
- // The new buffer may have historical data that we want to build on top of
- // But let's make sure we don't overflow Just In Case
- uint32_t divider = 0;
- if (newData->totalFrameCount > (1 << 24)) {
- divider = 4;
- }
- for (size_t i = 0; i < mData->jankTypeCounts.size(); i++) {
- newData->jankTypeCounts[i] >>= divider;
- newData->jankTypeCounts[i] += mData->jankTypeCounts[i];
- }
- for (size_t i = 0; i < mData->frameCounts.size(); i++) {
- newData->frameCounts[i] >>= divider;
- newData->frameCounts[i] += mData->frameCounts[i];
- }
- newData->jankFrameCount >>= divider;
- newData->jankFrameCount += mData->jankFrameCount;
- newData->totalFrameCount >>= divider;
- newData->totalFrameCount += mData->totalFrameCount;
- if (newData->statStartTime > mData->statStartTime
- || newData->statStartTime == 0) {
- newData->statStartTime = mData->statStartTime;
- }
-
- freeData();
- mData = newData;
- mIsMapped = true;
-}
-
void JankTracker::setFrameInterval(nsecs_t frameInterval) {
mFrameInterval = frameInterval;
mThresholds[kMissedVsync] = 1;
@@ -250,8 +109,7 @@
}
-void JankTracker::addFrame(const FrameInfo& frame) {
- mData->totalFrameCount++;
+void JankTracker::finishFrame(const FrameInfo& frame) {
// Fast-path for jank-free frames
int64_t totalDuration = frame.duration(sFrameStart, FrameInfoIndex::FrameCompleted);
if (mDequeueTimeForgiveness
@@ -271,11 +129,11 @@
}
}
LOG_ALWAYS_FATAL_IF(totalDuration <= 0, "Impossible totalDuration %" PRId64, totalDuration);
- uint32_t framebucket = frameCountIndexForFrameTime(totalDuration);
- LOG_ALWAYS_FATAL_IF(framebucket < 0, "framebucket < 0 (%u)", framebucket);
+ mData->reportFrame(totalDuration);
+ (*mGlobalData)->reportFrame(totalDuration);
+
// Keep the fast path as fast as possible.
if (CC_LIKELY(totalDuration < mFrameInterval)) {
- mData->frameCounts[framebucket]++;
return;
}
@@ -284,22 +142,14 @@
return;
}
- if (framebucket <= mData->frameCounts.size()) {
- mData->frameCounts[framebucket]++;
- } else {
- framebucket = (ns2ms(totalDuration) - kSlowFrameBucketStartMs)
- / kSlowFrameBucketIntervalMs;
- framebucket = std::min(framebucket,
- static_cast<uint32_t>(mData->slowFrameCounts.size() - 1));
- mData->slowFrameCounts[framebucket]++;
- }
-
- mData->jankFrameCount++;
+ mData->reportJank();
+ (*mGlobalData)->reportJank();
for (int i = 0; i < NUM_BUCKETS; i++) {
int64_t delta = frame.duration(COMPARISONS[i].start, COMPARISONS[i].end);
if (delta >= mThresholds[i] && delta < IGNORE_EXCEEDING) {
- mData->jankTypeCounts[i]++;
+ mData->reportJankType((JankType) i);
+ (*mGlobalData)->reportJankType((JankType) i);
}
}
}
@@ -320,58 +170,39 @@
if (sFrameStart != FrameInfoIndex::IntendedVsync) {
dprintf(fd, "\nNote: Data has been filtered!");
}
- dprintf(fd, "\nStats since: %" PRIu64 "ns", data->statStartTime);
- dprintf(fd, "\nTotal frames rendered: %u", data->totalFrameCount);
- dprintf(fd, "\nJanky frames: %u (%.2f%%)", data->jankFrameCount,
- (float) data->jankFrameCount / (float) data->totalFrameCount * 100.0f);
- dprintf(fd, "\n50th percentile: %ums", findPercentile(data, 50));
- dprintf(fd, "\n90th percentile: %ums", findPercentile(data, 90));
- dprintf(fd, "\n95th percentile: %ums", findPercentile(data, 95));
- dprintf(fd, "\n99th percentile: %ums", findPercentile(data, 99));
- for (int i = 0; i < NUM_BUCKETS; i++) {
- dprintf(fd, "\nNumber %s: %u", JANK_TYPE_NAMES[i], data->jankTypeCounts[i]);
- }
- dprintf(fd, "\nHISTOGRAM:");
- for (size_t i = 0; i < data->frameCounts.size(); i++) {
- dprintf(fd, " %ums=%u", frameTimeForFrameCountIndex(i),
- data->frameCounts[i]);
- }
- for (size_t i = 0; i < data->slowFrameCounts.size(); i++) {
- dprintf(fd, " %ums=%u", frameTimeForSlowFrameCountIndex(i),
- data->slowFrameCounts[i]);
- }
+ data->dump(fd);
dprintf(fd, "\n");
}
+void JankTracker::dumpFrames(int fd) {
+ FILE* file = fdopen(fd, "a");
+ fprintf(file, "\n\n---PROFILEDATA---\n");
+ for (size_t i = 0; i < static_cast<size_t>(FrameInfoIndex::NumIndexes); i++) {
+ fprintf(file, "%s", FrameInfoNames[i].c_str());
+ fprintf(file, ",");
+ }
+ for (size_t i = 0; i < mFrames.size(); i++) {
+ FrameInfo& frame = mFrames[i];
+ if (frame[FrameInfoIndex::SyncStart] == 0) {
+ continue;
+ }
+ fprintf(file, "\n");
+ for (int i = 0; i < static_cast<int>(FrameInfoIndex::NumIndexes); i++) {
+ fprintf(file, "%" PRId64 ",", frame[i]);
+ }
+ }
+ fprintf(file, "\n---PROFILEDATA---\n\n");
+ fflush(file);
+}
+
void JankTracker::reset() {
- mData->jankTypeCounts.fill(0);
- mData->frameCounts.fill(0);
- mData->slowFrameCounts.fill(0);
- mData->totalFrameCount = 0;
- mData->jankFrameCount = 0;
- mData->statStartTime = systemTime(CLOCK_MONOTONIC);
+ mFrames.clear();
+ mData->reset();
+ (*mGlobalData)->reset();
sFrameStart = Properties::filterOutTestOverhead
? FrameInfoIndex::HandleInputStart
: FrameInfoIndex::IntendedVsync;
}
-uint32_t JankTracker::findPercentile(const ProfileData* data, int percentile) {
- int pos = percentile * data->totalFrameCount / 100;
- int remaining = data->totalFrameCount - pos;
- for (int i = data->slowFrameCounts.size() - 1; i >= 0; i--) {
- remaining -= data->slowFrameCounts[i];
- if (remaining <= 0) {
- return (i * kSlowFrameBucketIntervalMs) + kSlowFrameBucketStartMs;
- }
- }
- for (int i = data->frameCounts.size() - 1; i >= 0; i--) {
- remaining -= data->frameCounts[i];
- if (remaining <= 0) {
- return frameTimeForFrameCountIndex(i);
- }
- }
- return 0;
-}
-
} /* namespace uirenderer */
} /* namespace android */
diff --git a/libs/hwui/JankTracker.h b/libs/hwui/JankTracker.h
index 6ff5d89..e56c079 100644
--- a/libs/hwui/JankTracker.h
+++ b/libs/hwui/JankTracker.h
@@ -17,6 +17,8 @@
#define JANKTRACKER_H_
#include "FrameInfo.h"
+#include "ProfileData.h"
+#include "ProfileDataContainer.h"
#include "renderthread/TimeLord.h"
#include "utils/RingBuffer.h"
@@ -29,31 +31,6 @@
namespace android {
namespace uirenderer {
-enum JankType {
- kMissedVsync = 0,
- kHighInputLatency,
- kSlowUI,
- kSlowSync,
- kSlowRT,
-
- // must be last
- NUM_BUCKETS,
-};
-
-// Try to keep as small as possible, should match ASHMEM_SIZE in
-// GraphicsStatsService.java
-struct ProfileData {
- std::array<uint32_t, NUM_BUCKETS> jankTypeCounts;
- // See comments on kBucket* constants for what this holds
- std::array<uint32_t, 57> frameCounts;
- // Holds a histogram of frame times in 50ms increments from 150ms to 5s
- std::array<uint16_t, 97> slowFrameCounts;
-
- uint32_t totalFrameCount;
- uint32_t jankFrameCount;
- nsecs_t statStartTime;
-};
-
enum class JankTrackerType {
// The default, means there's no description set
Generic,
@@ -72,31 +49,27 @@
// TODO: Replace DrawProfiler with this
class JankTracker {
public:
- explicit JankTracker(const DisplayInfo& displayInfo);
- ~JankTracker();
+ explicit JankTracker(ProfileDataContainer* globalData, const DisplayInfo& displayInfo);
void setDescription(JankTrackerType type, const std::string&& name) {
mDescription.type = type;
mDescription.name = name;
}
- void addFrame(const FrameInfo& frame);
+ FrameInfo* startFrame() { return &mFrames.next(); }
+ void finishFrame(const FrameInfo& frame);
- void dump(int fd) { dumpData(fd, &mDescription, mData); }
+ void dumpStats(int fd) { dumpData(fd, &mDescription, mData.get()); }
+ void dumpFrames(int fd);
void reset();
- void rotateStorage();
- void switchStorageToAshmem(int ashmemfd);
-
- uint32_t findPercentile(int p) { return findPercentile(mData, p); }
- static int32_t frameTimeForFrameCountIndex(uint32_t index);
- static int32_t frameTimeForSlowFrameCountIndex(uint32_t index);
+ // Exposed for FrameInfoVisualizer
+ // TODO: Figure out a better way to handle this
+ RingBuffer<FrameInfo, 120>& frames() { return mFrames; }
private:
- void freeData();
void setFrameInterval(nsecs_t frameIntervalNanos);
- static uint32_t findPercentile(const ProfileData* data, int p);
static void dumpData(int fd, const ProfileDataDescription* description, const ProfileData* data);
std::array<int64_t, NUM_BUCKETS> mThresholds;
@@ -109,9 +82,12 @@
// This is only used if we are in pipelined mode and are using HWC2,
// otherwise it's 0.
nsecs_t mDequeueTimeForgiveness = 0;
- ProfileData* mData;
- bool mIsMapped = false;
+ ProfileDataContainer mData;
+ ProfileDataContainer* mGlobalData;
ProfileDataDescription mDescription;
+
+ // Ring buffer large enough for 2 seconds worth of frames
+ RingBuffer<FrameInfo, 120> mFrames;
};
} /* namespace uirenderer */
diff --git a/libs/hwui/ProfileData.cpp b/libs/hwui/ProfileData.cpp
new file mode 100644
index 0000000..a295c5d
--- /dev/null
+++ b/libs/hwui/ProfileData.cpp
@@ -0,0 +1,177 @@
+/*
+ * 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.
+ */
+
+#include "ProfileData.h"
+
+#include <cinttypes>
+
+namespace android {
+namespace uirenderer {
+
+static const char* JANK_TYPE_NAMES[] = {
+ "Missed Vsync",
+ "High input latency",
+ "Slow UI thread",
+ "Slow bitmap uploads",
+ "Slow issue draw commands",
+};
+
+// The bucketing algorithm controls so to speak
+// If a frame is <= to this it goes in bucket 0
+static const uint32_t kBucketMinThreshold = 5;
+// If a frame is > this, start counting in increments of 2ms
+static const uint32_t kBucket2msIntervals = 32;
+// If a frame is > this, start counting in increments of 4ms
+static const uint32_t kBucket4msIntervals = 48;
+
+// The interval of the slow frame histogram
+static const uint32_t kSlowFrameBucketIntervalMs = 50;
+// The start point of the slow frame bucket in ms
+static const uint32_t kSlowFrameBucketStartMs = 150;
+
+// This will be called every frame, performance sensitive
+// Uses bit twiddling to avoid branching while achieving the packing desired
+static uint32_t frameCountIndexForFrameTime(nsecs_t frameTime) {
+ uint32_t index = static_cast<uint32_t>(ns2ms(frameTime));
+ // If index > kBucketMinThreshold mask will be 0xFFFFFFFF as a result
+ // of negating 1 (twos compliment, yaay) else mask will be 0
+ uint32_t mask = -(index > kBucketMinThreshold);
+ // If index > threshold, this will essentially perform:
+ // amountAboveThreshold = index - threshold;
+ // index = threshold + (amountAboveThreshold / 2)
+ // However if index is <= this will do nothing. It will underflow, do
+ // a right shift by 0 (no-op), then overflow back to the original value
+ index = ((index - kBucket4msIntervals) >> (index > kBucket4msIntervals))
+ + kBucket4msIntervals;
+ index = ((index - kBucket2msIntervals) >> (index > kBucket2msIntervals))
+ + kBucket2msIntervals;
+ // If index was < minThreshold at the start of all this it's going to
+ // be a pretty garbage value right now. However, mask is 0 so we'll end
+ // up with the desired result of 0.
+ index = (index - kBucketMinThreshold) & mask;
+ return index;
+}
+
+// Only called when dumping stats, less performance sensitive
+uint32_t ProfileData::frameTimeForFrameCountIndex(uint32_t index) {
+ index = index + kBucketMinThreshold;
+ if (index > kBucket2msIntervals) {
+ index += (index - kBucket2msIntervals);
+ }
+ if (index > kBucket4msIntervals) {
+ // This works because it was already doubled by the above if
+ // 1 is added to shift slightly more towards the middle of the bucket
+ index += (index - kBucket4msIntervals) + 1;
+ }
+ return index;
+}
+
+uint32_t ProfileData::frameTimeForSlowFrameCountIndex(uint32_t index) {
+ return (index * kSlowFrameBucketIntervalMs) + kSlowFrameBucketStartMs;
+}
+
+void ProfileData::mergeWith(const ProfileData& other) {
+ // Make sure we don't overflow Just In Case
+ uint32_t divider = 0;
+ if (mTotalFrameCount > (1 << 24)) {
+ divider = 4;
+ }
+ for (size_t i = 0; i < other.mJankTypeCounts.size(); i++) {
+ mJankTypeCounts[i] >>= divider;
+ mJankTypeCounts[i] += other.mJankTypeCounts[i];
+ }
+ for (size_t i = 0; i < other.mFrameCounts.size(); i++) {
+ mFrameCounts[i] >>= divider;
+ mFrameCounts[i] += other.mFrameCounts[i];
+ }
+ mJankFrameCount >>= divider;
+ mJankFrameCount += other.mJankFrameCount;
+ mTotalFrameCount >>= divider;
+ mTotalFrameCount += other.mTotalFrameCount;
+ if (mStatStartTime > other.mStatStartTime
+ || mStatStartTime == 0) {
+ mStatStartTime = other.mStatStartTime;
+ }
+}
+
+void ProfileData::dump(int fd) const {
+ dprintf(fd, "\nStats since: %" PRIu64 "ns", mStatStartTime);
+ dprintf(fd, "\nTotal frames rendered: %u", mTotalFrameCount);
+ dprintf(fd, "\nJanky frames: %u (%.2f%%)", mJankFrameCount,
+ (float) mJankFrameCount / (float) mTotalFrameCount * 100.0f);
+ dprintf(fd, "\n50th percentile: %ums", findPercentile(50));
+ dprintf(fd, "\n90th percentile: %ums", findPercentile(90));
+ dprintf(fd, "\n95th percentile: %ums", findPercentile(95));
+ dprintf(fd, "\n99th percentile: %ums", findPercentile(99));
+ for (int i = 0; i < NUM_BUCKETS; i++) {
+ dprintf(fd, "\nNumber %s: %u", JANK_TYPE_NAMES[i], mJankTypeCounts[i]);
+ }
+ dprintf(fd, "\nHISTOGRAM:");
+ histogramForEach([fd](HistogramEntry entry) {
+ dprintf(fd, " %ums=%u", entry.renderTimeMs, entry.frameCount);
+ });
+}
+
+uint32_t ProfileData::findPercentile(int percentile) const {
+ int pos = percentile * mTotalFrameCount / 100;
+ int remaining = mTotalFrameCount - pos;
+ for (int i = mSlowFrameCounts.size() - 1; i >= 0; i--) {
+ remaining -= mSlowFrameCounts[i];
+ if (remaining <= 0) {
+ return (i * kSlowFrameBucketIntervalMs) + kSlowFrameBucketStartMs;
+ }
+ }
+ for (int i = mFrameCounts.size() - 1; i >= 0; i--) {
+ remaining -= mFrameCounts[i];
+ if (remaining <= 0) {
+ return frameTimeForFrameCountIndex(i);
+ }
+ }
+ return 0;
+}
+
+void ProfileData::reset() {
+ mJankTypeCounts.fill(0);
+ mFrameCounts.fill(0);
+ mSlowFrameCounts.fill(0);
+ mTotalFrameCount = 0;
+ mJankFrameCount = 0;
+ mStatStartTime = systemTime(CLOCK_MONOTONIC);
+}
+
+void ProfileData::reportFrame(int64_t duration) {
+ mTotalFrameCount++;
+ uint32_t framebucket = frameCountIndexForFrameTime(duration);
+ if (framebucket <= mFrameCounts.size()) {
+ mFrameCounts[framebucket]++;
+ } else {
+ framebucket = (ns2ms(duration) - kSlowFrameBucketStartMs) / kSlowFrameBucketIntervalMs;
+ framebucket = std::min(framebucket, static_cast<uint32_t>(mSlowFrameCounts.size() - 1));
+ mSlowFrameCounts[framebucket]++;
+ }
+}
+
+void ProfileData::histogramForEach(const std::function<void(HistogramEntry)>& callback) const {
+ for (size_t i = 0; i < mFrameCounts.size(); i++) {
+ callback(HistogramEntry{frameTimeForFrameCountIndex(i), mFrameCounts[i]});
+ }
+ for (size_t i = 0; i < mSlowFrameCounts.size(); i++) {
+ callback(HistogramEntry{frameTimeForSlowFrameCountIndex(i), mSlowFrameCounts[i]});
+ }
+}
+
+} /* namespace uirenderer */
+} /* namespace android */
\ No newline at end of file
diff --git a/libs/hwui/ProfileData.h b/libs/hwui/ProfileData.h
new file mode 100644
index 0000000..d53ee29
--- /dev/null
+++ b/libs/hwui/ProfileData.h
@@ -0,0 +1,109 @@
+/*
+ * 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.
+ */
+
+#pragma once
+
+#include "utils/Macros.h"
+
+#include <utils/Timers.h>
+
+#include <array>
+#include <functional>
+#include <tuple>
+
+namespace android {
+namespace uirenderer {
+
+enum JankType {
+ kMissedVsync = 0,
+ kHighInputLatency,
+ kSlowUI,
+ kSlowSync,
+ kSlowRT,
+
+ // must be last
+ NUM_BUCKETS,
+};
+
+// For testing
+class MockProfileData;
+
+// Try to keep as small as possible, should match ASHMEM_SIZE in
+// GraphicsStatsService.java
+class ProfileData {
+ PREVENT_COPY_AND_ASSIGN(ProfileData);
+
+public:
+ ProfileData() { reset(); }
+
+ void reset();
+ void mergeWith(const ProfileData& other);
+ void dump(int fd) const;
+ uint32_t findPercentile(int percentile) const;
+
+ void reportFrame(int64_t duration);
+ void reportJank() { mJankFrameCount++; }
+ void reportJankType(JankType type) { mJankTypeCounts[static_cast<int>(type)]++; }
+
+ uint32_t totalFrameCount() const { return mTotalFrameCount; }
+ uint32_t jankFrameCount() const { return mJankFrameCount; }
+ nsecs_t statsStartTime() const { return mStatStartTime; }
+ uint32_t jankTypeCount(JankType type) const { return mJankTypeCounts[static_cast<int>(type)]; }
+
+ struct HistogramEntry {
+ uint32_t renderTimeMs;
+ uint32_t frameCount;
+ };
+ void histogramForEach(const std::function<void(HistogramEntry)>& callback) const;
+
+ constexpr static int HistogramSize() {
+ return std::tuple_size<decltype(ProfileData::mFrameCounts)>::value
+ + std::tuple_size<decltype(ProfileData::mSlowFrameCounts)>::value;
+ }
+
+ // Visible for testing
+ static uint32_t frameTimeForFrameCountIndex(uint32_t index);
+ static uint32_t frameTimeForSlowFrameCountIndex(uint32_t index);
+
+private:
+ // Open our guts up to unit tests
+ friend class MockProfileData;
+
+ std::array <uint32_t, NUM_BUCKETS> mJankTypeCounts;
+ // See comments on kBucket* constants for what this holds
+ std::array<uint32_t, 57> mFrameCounts;
+ // Holds a histogram of frame times in 50ms increments from 150ms to 5s
+ std::array<uint16_t, 97> mSlowFrameCounts;
+
+ uint32_t mTotalFrameCount;
+ uint32_t mJankFrameCount;
+ nsecs_t mStatStartTime;
+};
+
+// For testing
+class MockProfileData : public ProfileData {
+public:
+ std::array<uint32_t, NUM_BUCKETS>& editJankTypeCounts() { return mJankTypeCounts; }
+ std::array<uint32_t, 57>& editFrameCounts() { return mFrameCounts; }
+ std::array<uint16_t, 97>& editSlowFrameCounts() { return mSlowFrameCounts; }
+ uint32_t& editTotalFrameCount() { return mTotalFrameCount; }
+ uint32_t& editJankFrameCount() { return mJankFrameCount; }
+ nsecs_t& editStatStartTime() { return mStatStartTime; }
+};
+
+} /* namespace uirenderer */
+} /* namespace android */
+
diff --git a/libs/hwui/ProfileDataContainer.cpp b/libs/hwui/ProfileDataContainer.cpp
new file mode 100644
index 0000000..cbf3eb3
--- /dev/null
+++ b/libs/hwui/ProfileDataContainer.cpp
@@ -0,0 +1,78 @@
+/*
+ * 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.
+ */
+
+#include "ProfileDataContainer.h"
+
+#include <log/log.h>
+#include <cutils/ashmem.h>
+
+#include <sys/mman.h>
+
+namespace android {
+namespace uirenderer {
+
+void ProfileDataContainer::freeData() {
+ if (mIsMapped) {
+ munmap(mData, sizeof(ProfileData));
+ } else {
+ delete mData;
+ }
+ mIsMapped = false;
+ mData = nullptr;
+}
+
+void ProfileDataContainer::rotateStorage() {
+ // If we are mapped we want to stop using the ashmem backend and switch to malloc
+ // We are expecting a switchStorageToAshmem call to follow this, but it's not guaranteed
+ // If we aren't sitting on top of ashmem then just do a reset() as it's functionally
+ // equivalent do a free, malloc, reset.
+ if (mIsMapped) {
+ freeData();
+ mData = new ProfileData;
+ }
+ mData->reset();
+}
+
+void ProfileDataContainer::switchStorageToAshmem(int ashmemfd) {
+ int regionSize = ashmem_get_size_region(ashmemfd);
+ if (regionSize < 0) {
+ int err = errno;
+ ALOGW("Failed to get ashmem region size from fd %d, err %d %s", ashmemfd, err, strerror(err));
+ return;
+ }
+ if (regionSize < static_cast<int>(sizeof(ProfileData))) {
+ ALOGW("Ashmem region is too small! Received %d, required %u",
+ regionSize, static_cast<unsigned int>(sizeof(ProfileData)));
+ return;
+ }
+ ProfileData* newData = reinterpret_cast<ProfileData*>(
+ mmap(NULL, sizeof(ProfileData), PROT_READ | PROT_WRITE,
+ MAP_SHARED, ashmemfd, 0));
+ if (newData == MAP_FAILED) {
+ int err = errno;
+ ALOGW("Failed to move profile data to ashmem fd %d, error = %d",
+ ashmemfd, err);
+ return;
+ }
+
+ newData->mergeWith(*mData);
+ freeData();
+ mData = newData;
+ mIsMapped = true;
+}
+
+} /* namespace uirenderer */
+} /* namespace android */
\ No newline at end of file
diff --git a/libs/hwui/ProfileDataContainer.h b/libs/hwui/ProfileDataContainer.h
new file mode 100644
index 0000000..d2de241
--- /dev/null
+++ b/libs/hwui/ProfileDataContainer.h
@@ -0,0 +1,48 @@
+/*
+ * 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.
+ */
+
+#pragma once
+
+#include "ProfileData.h"
+#include "utils/Macros.h"
+
+namespace android {
+namespace uirenderer {
+
+class ProfileDataContainer {
+ PREVENT_COPY_AND_ASSIGN(ProfileDataContainer);
+public:
+ explicit ProfileDataContainer() {}
+
+ ~ProfileDataContainer() { freeData(); }
+
+ void rotateStorage();
+ void switchStorageToAshmem(int ashmemfd);
+
+ ProfileData* get() { return mData; }
+ ProfileData* operator->() { return mData; }
+
+private:
+ void freeData();
+
+ // By default this will use malloc memory. It may be moved later to ashmem
+ // if there is shared space for it and a request comes in to do that.
+ ProfileData* mData = new ProfileData;
+ bool mIsMapped = false;
+};
+
+} /* namespace uirenderer */
+} /* namespace android */
\ No newline at end of file
diff --git a/libs/hwui/renderthread/CanvasContext.cpp b/libs/hwui/renderthread/CanvasContext.cpp
index 7799248..5d7f594 100644
--- a/libs/hwui/renderthread/CanvasContext.cpp
+++ b/libs/hwui/renderthread/CanvasContext.cpp
@@ -142,8 +142,8 @@
: mRenderThread(thread)
, mOpaque(!translucent)
, mAnimationContext(contextFactory->createAnimationContext(mRenderThread.timeLord()))
- , mJankTracker(thread.mainDisplayInfo())
- , mProfiler(mFrames)
+ , mJankTracker(&thread.globalProfileData(), thread.mainDisplayInfo())
+ , mProfiler(mJankTracker.frames())
, mContentDrawBounds(0, 0, 0, 0)
, mRenderPipeline(std::move(renderPipeline)) {
rootRenderNode->makeRoot();
@@ -321,7 +321,7 @@
// If the previous frame was dropped we don't need to hold onto it, so
// just keep using the previous frame's structure instead
if (!wasSkipped(mCurrentFrameInfo)) {
- mCurrentFrameInfo = &mFrames.next();
+ mCurrentFrameInfo = mJankTracker.startFrame();
}
mCurrentFrameInfo->importUiThreadInfo(uiFrameInfo);
mCurrentFrameInfo->set(FrameInfoIndex::SyncQueued) = syncQueued;
@@ -485,8 +485,7 @@
}
#endif
- mJankTracker.addFrame(*mCurrentFrameInfo);
- mRenderThread.jankTracker().addFrame(*mCurrentFrameInfo);
+ mJankTracker.finishFrame(*mCurrentFrameInfo);
if (CC_UNLIKELY(mFrameMetricsReporter.get() != nullptr)) {
mFrameMetricsReporter->reportFrameMetrics(mCurrentFrameInfo->data());
}
@@ -625,30 +624,12 @@
}
void CanvasContext::dumpFrames(int fd) {
- mJankTracker.dump(fd);
- FILE* file = fdopen(fd, "a");
- fprintf(file, "\n\n---PROFILEDATA---\n");
- for (size_t i = 0; i < static_cast<size_t>(FrameInfoIndex::NumIndexes); i++) {
- fprintf(file, "%s", FrameInfoNames[i].c_str());
- fprintf(file, ",");
- }
- for (size_t i = 0; i < mFrames.size(); i++) {
- FrameInfo& frame = mFrames[i];
- if (frame[FrameInfoIndex::SyncStart] == 0) {
- continue;
- }
- fprintf(file, "\n");
- for (int i = 0; i < static_cast<int>(FrameInfoIndex::NumIndexes); i++) {
- fprintf(file, "%" PRId64 ",", frame[i]);
- }
- }
- fprintf(file, "\n---PROFILEDATA---\n\n");
- fflush(file);
+ mJankTracker.dumpStats(fd);
+ mJankTracker.dumpFrames(fd);
}
void CanvasContext::resetFrameStats() {
- mFrames.clear();
- mRenderThread.jankTracker().reset();
+ mJankTracker.reset();
}
void CanvasContext::setName(const std::string&& name) {
diff --git a/libs/hwui/renderthread/CanvasContext.h b/libs/hwui/renderthread/CanvasContext.h
index b1f4050..aa6d2f3 100644
--- a/libs/hwui/renderthread/CanvasContext.h
+++ b/libs/hwui/renderthread/CanvasContext.h
@@ -29,7 +29,6 @@
#include "RenderNode.h"
#include "thread/Task.h"
#include "thread/TaskProcessor.h"
-#include "utils/RingBuffer.h"
#include "renderthread/RenderTask.h"
#include "renderthread/RenderThread.h"
@@ -253,8 +252,6 @@
std::vector< sp<RenderNode> > mRenderNodes;
FrameInfo* mCurrentFrameInfo = nullptr;
- // Ring buffer large enough for 2 seconds worth of frames
- RingBuffer<FrameInfo, 120> mFrames;
std::string mName;
JankTracker mJankTracker;
FrameInfoVisualizer mProfiler;
diff --git a/libs/hwui/renderthread/RenderProxy.cpp b/libs/hwui/renderthread/RenderProxy.cpp
index 80c2955..370cf52 100644
--- a/libs/hwui/renderthread/RenderProxy.cpp
+++ b/libs/hwui/renderthread/RenderProxy.cpp
@@ -427,12 +427,12 @@
if (args->dumpFlags & DumpFlags::FrameStats) {
args->context->dumpFrames(args->fd);
}
+ if (args->dumpFlags & DumpFlags::JankStats) {
+ args->thread->globalProfileData()->dump(args->fd);
+ }
if (args->dumpFlags & DumpFlags::Reset) {
args->context->resetFrameStats();
}
- if (args->dumpFlags & DumpFlags::JankStats) {
- args->thread->jankTracker().dump(args->fd);
- }
return nullptr;
}
@@ -458,7 +458,7 @@
CREATE_BRIDGE2(frameTimePercentile, RenderThread* thread, int percentile) {
return reinterpret_cast<void*>(static_cast<uintptr_t>(
- args->thread->jankTracker().findPercentile(args->percentile)));
+ args->thread->globalProfileData()->findPercentile(args->percentile)));
}
uint32_t RenderProxy::frameTimePercentile(int p) {
@@ -483,7 +483,7 @@
}
CREATE_BRIDGE2(setProcessStatsBuffer, RenderThread* thread, int fd) {
- args->thread->jankTracker().switchStorageToAshmem(args->fd);
+ args->thread->globalProfileData().switchStorageToAshmem(args->fd);
close(args->fd);
return nullptr;
}
@@ -497,7 +497,7 @@
}
CREATE_BRIDGE1(rotateProcessStatsBuffer, RenderThread* thread) {
- args->thread->jankTracker().rotateStorage();
+ args->thread->globalProfileData().rotateStorage();
return nullptr;
}
diff --git a/libs/hwui/renderthread/RenderThread.cpp b/libs/hwui/renderthread/RenderThread.cpp
index 13af2c4..72a428f 100644
--- a/libs/hwui/renderthread/RenderThread.cpp
+++ b/libs/hwui/renderthread/RenderThread.cpp
@@ -200,13 +200,12 @@
initializeDisplayEventReceiver();
mEglManager = new EglManager(*this);
mRenderState = new RenderState(*this);
- mJankTracker = new JankTracker(mDisplayInfo);
mVkManager = new VulkanManager(*this);
mCacheManager = new CacheManager(mDisplayInfo);
}
void RenderThread::dumpGraphicsMemory(int fd) {
- jankTracker().dump(fd);
+ globalProfileData()->dump(fd);
String8 cachesOutput;
String8 pipeline;
diff --git a/libs/hwui/renderthread/RenderThread.h b/libs/hwui/renderthread/RenderThread.h
index d984257..bef47b3 100644
--- a/libs/hwui/renderthread/RenderThread.h
+++ b/libs/hwui/renderthread/RenderThread.h
@@ -97,7 +97,7 @@
TimeLord& timeLord() { return mTimeLord; }
RenderState& renderState() const { return *mRenderState; }
EglManager& eglManager() const { return *mEglManager; }
- JankTracker& jankTracker() { return *mJankTracker; }
+ ProfileDataContainer& globalProfileData() { return mGlobalProfileData; }
Readback& readback();
const DisplayInfo& mainDisplayInfo() { return mDisplayInfo; }
@@ -160,7 +160,7 @@
RenderState* mRenderState;
EglManager* mEglManager;
- JankTracker* mJankTracker = nullptr;
+ ProfileDataContainer mGlobalProfileData;
Readback* mReadback = nullptr;
sk_sp<GrContext> mGrContext;
diff --git a/libs/hwui/service/GraphicsStatsService.cpp b/libs/hwui/service/GraphicsStatsService.cpp
index 87eaa6a..3a77195 100644
--- a/libs/hwui/service/GraphicsStatsService.cpp
+++ b/libs/hwui/service/GraphicsStatsService.cpp
@@ -38,9 +38,7 @@
constexpr int32_t sHeaderSize = 4;
static_assert(sizeof(sCurrentFileVersion) == sHeaderSize, "Header size is wrong");
-constexpr int sHistogramSize =
- std::tuple_size<decltype(ProfileData::frameCounts)>::value +
- std::tuple_size<decltype(ProfileData::slowFrameCounts)>::value;
+constexpr int sHistogramSize = ProfileData::HistogramSize();
static void mergeProfileDataIntoProto(service::GraphicsStatsProto* proto,
const std::string& package, int versionCode, int64_t startTime, int64_t endTime,
@@ -172,18 +170,18 @@
proto->set_package_name(package);
proto->set_version_code(versionCode);
auto summary = proto->mutable_summary();
- summary->set_total_frames(summary->total_frames() + data->totalFrameCount);
- summary->set_janky_frames(summary->janky_frames() + data->jankFrameCount);
+ summary->set_total_frames(summary->total_frames() + data->totalFrameCount());
+ summary->set_janky_frames(summary->janky_frames() + data->jankFrameCount());
summary->set_missed_vsync_count(
- summary->missed_vsync_count() + data->jankTypeCounts[kMissedVsync]);
+ summary->missed_vsync_count() + data->jankTypeCount(kMissedVsync));
summary->set_high_input_latency_count(
- summary->high_input_latency_count() + data->jankTypeCounts[kHighInputLatency]);
+ summary->high_input_latency_count() + data->jankTypeCount(kHighInputLatency));
summary->set_slow_ui_thread_count(
- summary->slow_ui_thread_count() + data->jankTypeCounts[kSlowUI]);
+ summary->slow_ui_thread_count() + data->jankTypeCount(kSlowUI));
summary->set_slow_bitmap_upload_count(
- summary->slow_bitmap_upload_count() + data->jankTypeCounts[kSlowSync]);
+ summary->slow_bitmap_upload_count() + data->jankTypeCount(kSlowSync));
summary->set_slow_draw_count(
- summary->slow_draw_count() + data->jankTypeCounts[kSlowRT]);
+ summary->slow_draw_count() + data->jankTypeCount(kSlowRT));
bool creatingHistogram = false;
if (proto->histogram_size() == 0) {
@@ -193,33 +191,20 @@
LOG_ALWAYS_FATAL("Histogram size mismatch, proto is %d expected %d",
proto->histogram_size(), sHistogramSize);
}
- for (size_t i = 0; i < data->frameCounts.size(); i++) {
+ int index = 0;
+ data->histogramForEach([&](ProfileData::HistogramEntry entry) {
service::GraphicsStatsHistogramBucketProto* bucket;
- int32_t renderTime = JankTracker::frameTimeForFrameCountIndex(i);
if (creatingHistogram) {
bucket = proto->add_histogram();
- bucket->set_render_millis(renderTime);
+ bucket->set_render_millis(entry.renderTimeMs);
} else {
- bucket = proto->mutable_histogram(i);
- LOG_ALWAYS_FATAL_IF(bucket->render_millis() != renderTime,
- "Frame time mistmatch %d vs. %d", bucket->render_millis(), renderTime);
+ bucket = proto->mutable_histogram(index);
+ LOG_ALWAYS_FATAL_IF(bucket->render_millis() != static_cast<int32_t>(entry.renderTimeMs),
+ "Frame time mistmatch %d vs. %u", bucket->render_millis(), entry.renderTimeMs);
}
- bucket->set_frame_count(bucket->frame_count() + data->frameCounts[i]);
- }
- for (size_t i = 0; i < data->slowFrameCounts.size(); i++) {
- service::GraphicsStatsHistogramBucketProto* bucket;
- int32_t renderTime = JankTracker::frameTimeForSlowFrameCountIndex(i);
- if (creatingHistogram) {
- bucket = proto->add_histogram();
- bucket->set_render_millis(renderTime);
- } else {
- constexpr int offset = std::tuple_size<decltype(ProfileData::frameCounts)>::value;
- bucket = proto->mutable_histogram(offset + i);
- LOG_ALWAYS_FATAL_IF(bucket->render_millis() != renderTime,
- "Frame time mistmatch %d vs. %d", bucket->render_millis(), renderTime);
- }
- bucket->set_frame_count(bucket->frame_count() + data->slowFrameCounts[i]);
- }
+ bucket->set_frame_count(bucket->frame_count() + entry.frameCount);
+ index++;
+ });
}
static int32_t findPercentile(service::GraphicsStatsProto* proto, int percentile) {
diff --git a/libs/hwui/tests/unit/GraphicsStatsServiceTests.cpp b/libs/hwui/tests/unit/GraphicsStatsServiceTests.cpp
index f6f7337..fda3a79 100644
--- a/libs/hwui/tests/unit/GraphicsStatsServiceTests.cpp
+++ b/libs/hwui/tests/unit/GraphicsStatsServiceTests.cpp
@@ -61,17 +61,17 @@
TEST(GraphicsStats, saveLoad) {
std::string path = findRootPath() + "/test_saveLoad";
std::string packageName = "com.test.saveLoad";
- ProfileData mockData;
- mockData.jankFrameCount = 20;
- mockData.totalFrameCount = 100;
- mockData.statStartTime = 10000;
+ MockProfileData mockData;
+ mockData.editJankFrameCount() = 20;
+ mockData.editTotalFrameCount() = 100;
+ mockData.editStatStartTime() = 10000;
// Fill with patterned data we can recognize but which won't map to a
// memset or basic for iteration count
- for (size_t i = 0; i < mockData.frameCounts.size(); i++) {
- mockData.frameCounts[i] = ((i % 10) + 1) * 2;
+ for (size_t i = 0; i < mockData.editFrameCounts().size(); i++) {
+ mockData.editFrameCounts()[i] = ((i % 10) + 1) * 2;
}
- for (size_t i = 0; i < mockData.slowFrameCounts.size(); i++) {
- mockData.slowFrameCounts[i] = (i % 5) + 1;
+ for (size_t i = 0; i < mockData.editSlowFrameCounts().size(); i++) {
+ mockData.editSlowFrameCounts()[i] = (i % 5) + 1;
}
GraphicsStatsService::saveBuffer(path, packageName, 5, 3000, 7000, &mockData);
service::GraphicsStatsProto loadedProto;
@@ -87,17 +87,17 @@
ASSERT_TRUE(loadedProto.has_summary());
EXPECT_EQ(20, loadedProto.summary().janky_frames());
EXPECT_EQ(100, loadedProto.summary().total_frames());
- EXPECT_EQ(mockData.frameCounts.size() + mockData.slowFrameCounts.size(),
+ EXPECT_EQ(mockData.editFrameCounts().size() + mockData.editSlowFrameCounts().size(),
(size_t) loadedProto.histogram_size());
for (size_t i = 0; i < (size_t) loadedProto.histogram_size(); i++) {
int expectedCount, expectedBucket;
- if (i < mockData.frameCounts.size()) {
+ if (i < mockData.editFrameCounts().size()) {
expectedCount = ((i % 10) + 1) * 2;
- expectedBucket = JankTracker::frameTimeForFrameCountIndex(i);
+ expectedBucket = ProfileData::frameTimeForFrameCountIndex(i);
} else {
- int temp = i - mockData.frameCounts.size();
+ int temp = i - mockData.editFrameCounts().size();
expectedCount = (temp % 5) + 1;
- expectedBucket = JankTracker::frameTimeForSlowFrameCountIndex(temp);
+ expectedBucket = ProfileData::frameTimeForSlowFrameCountIndex(temp);
}
EXPECT_EQ(expectedCount, loadedProto.histogram().Get(i).frame_count());
EXPECT_EQ(expectedBucket, loadedProto.histogram().Get(i).render_millis());
@@ -107,26 +107,26 @@
TEST(GraphicsStats, merge) {
std::string path = findRootPath() + "/test_merge";
std::string packageName = "com.test.merge";
- ProfileData mockData;
- mockData.jankFrameCount = 20;
- mockData.totalFrameCount = 100;
- mockData.statStartTime = 10000;
+ MockProfileData mockData;
+ mockData.editJankFrameCount() = 20;
+ mockData.editTotalFrameCount() = 100;
+ mockData.editStatStartTime() = 10000;
// Fill with patterned data we can recognize but which won't map to a
// memset or basic for iteration count
- for (size_t i = 0; i < mockData.frameCounts.size(); i++) {
- mockData.frameCounts[i] = ((i % 10) + 1) * 2;
+ for (size_t i = 0; i < mockData.editFrameCounts().size(); i++) {
+ mockData.editFrameCounts()[i] = ((i % 10) + 1) * 2;
}
- for (size_t i = 0; i < mockData.slowFrameCounts.size(); i++) {
- mockData.slowFrameCounts[i] = (i % 5) + 1;
+ for (size_t i = 0; i < mockData.editSlowFrameCounts().size(); i++) {
+ mockData.editSlowFrameCounts()[i] = (i % 5) + 1;
}
GraphicsStatsService::saveBuffer(path, packageName, 5, 3000, 7000, &mockData);
- mockData.jankFrameCount = 50;
- mockData.totalFrameCount = 500;
- for (size_t i = 0; i < mockData.frameCounts.size(); i++) {
- mockData.frameCounts[i] = (i % 5) + 1;
+ mockData.editJankFrameCount() = 50;
+ mockData.editTotalFrameCount() = 500;
+ for (size_t i = 0; i < mockData.editFrameCounts().size(); i++) {
+ mockData.editFrameCounts()[i] = (i % 5) + 1;
}
- for (size_t i = 0; i < mockData.slowFrameCounts.size(); i++) {
- mockData.slowFrameCounts[i] = ((i % 10) + 1) * 2;
+ for (size_t i = 0; i < mockData.editSlowFrameCounts().size(); i++) {
+ mockData.editSlowFrameCounts()[i] = ((i % 10) + 1) * 2;
}
GraphicsStatsService::saveBuffer(path, packageName, 5, 7050, 10000, &mockData);
@@ -143,19 +143,19 @@
ASSERT_TRUE(loadedProto.has_summary());
EXPECT_EQ(20 + 50, loadedProto.summary().janky_frames());
EXPECT_EQ(100 + 500, loadedProto.summary().total_frames());
- EXPECT_EQ(mockData.frameCounts.size() + mockData.slowFrameCounts.size(),
+ EXPECT_EQ(mockData.editFrameCounts().size() + mockData.editSlowFrameCounts().size(),
(size_t) loadedProto.histogram_size());
for (size_t i = 0; i < (size_t) loadedProto.histogram_size(); i++) {
int expectedCount, expectedBucket;
- if (i < mockData.frameCounts.size()) {
+ if (i < mockData.editFrameCounts().size()) {
expectedCount = ((i % 10) + 1) * 2;
expectedCount += (i % 5) + 1;
- expectedBucket = JankTracker::frameTimeForFrameCountIndex(i);
+ expectedBucket = ProfileData::frameTimeForFrameCountIndex(i);
} else {
- int temp = i - mockData.frameCounts.size();
+ int temp = i - mockData.editFrameCounts().size();
expectedCount = (temp % 5) + 1;
expectedCount += ((temp % 10) + 1) * 2;
- expectedBucket = JankTracker::frameTimeForSlowFrameCountIndex(temp);
+ expectedBucket = ProfileData::frameTimeForSlowFrameCountIndex(temp);
}
EXPECT_EQ(expectedCount, loadedProto.histogram().Get(i).frame_count());
EXPECT_EQ(expectedBucket, loadedProto.histogram().Get(i).render_millis());
diff --git a/native/android/include/android/multinetwork.h b/native/android/include/android/multinetwork.h
new file mode 120000
index 0000000..0feab3a
--- /dev/null
+++ b/native/android/include/android/multinetwork.h
@@ -0,0 +1 @@
+../../../../../native/include/android/multinetwork.h
\ No newline at end of file
diff --git a/native/android/include/multinetwork.h b/native/android/include/multinetwork.h
deleted file mode 120000
index f9d051a..0000000
--- a/native/android/include/multinetwork.h
+++ /dev/null
@@ -1 +0,0 @@
-../../../../native/include/android/multinetwork.h
\ No newline at end of file
diff --git a/packages/CarrierDefaultApp/res/values-ca/strings.xml b/packages/CarrierDefaultApp/res/values-ca/strings.xml
index c1ddbd39..66a8f37 100644
--- a/packages/CarrierDefaultApp/res/values-ca/strings.xml
+++ b/packages/CarrierDefaultApp/res/values-ca/strings.xml
@@ -10,7 +10,7 @@
<string name="no_mobile_data_connection_title" msgid="7449525772416200578">"No hi ha connexió de dades mòbils"</string>
<string name="no_mobile_data_connection" msgid="544980465184147010">"Afegeix un pla de dades o d\'itinerància amb %s"</string>
<string name="mobile_data_status_notification_channel_name" msgid="833999690121305708">"Estat de les dades mòbils"</string>
- <string name="action_bar_label" msgid="4290345990334377177">"Inicia la sessió a la xarxa de telefonia mòbil"</string>
+ <string name="action_bar_label" msgid="4290345990334377177">"Inicia la sessió a la xarxa mòbil"</string>
<string name="ssl_error_warning" msgid="3127935140338254180">"La xarxa a què et vols connectar té problemes de seguretat."</string>
<string name="ssl_error_example" msgid="6188711843183058764">"Per exemple, la pàgina d\'inici de sessió podria no pertànyer a l\'organització que es mostra."</string>
<string name="ssl_error_continue" msgid="1138548463994095584">"Continua igualment mitjançant el navegador"</string>
diff --git a/packages/PrintSpooler/res/values-b+sr+Latn/strings.xml b/packages/PrintSpooler/res/values-b+sr+Latn/strings.xml
index 49fe52b..9c29ff2 100644
--- a/packages/PrintSpooler/res/values-b+sr+Latn/strings.xml
+++ b/packages/PrintSpooler/res/values-b+sr+Latn/strings.xml
@@ -16,7 +16,7 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="app_label" msgid="4469836075319831821">"Štamp. iz memor."</string>
+ <string name="app_label" msgid="4469836075319831821">"Štampanje iz memorije"</string>
<string name="more_options_button" msgid="2243228396432556771">"Još opcija"</string>
<string name="label_destination" msgid="9132510997381599275">"Odredište"</string>
<string name="label_copies" msgid="3634531042822968308">"Kopije"</string>
diff --git a/packages/PrintSpooler/res/values-sr/strings.xml b/packages/PrintSpooler/res/values-sr/strings.xml
index c20a5af..cb23c3c 100644
--- a/packages/PrintSpooler/res/values-sr/strings.xml
+++ b/packages/PrintSpooler/res/values-sr/strings.xml
@@ -16,7 +16,7 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="app_label" msgid="4469836075319831821">"Штамп. из мемор."</string>
+ <string name="app_label" msgid="4469836075319831821">"Штампање из меморије"</string>
<string name="more_options_button" msgid="2243228396432556771">"Још опција"</string>
<string name="label_destination" msgid="9132510997381599275">"Одредиште"</string>
<string name="label_copies" msgid="3634531042822968308">"Копије"</string>
diff --git a/packages/SettingsLib/res/values-af/strings.xml b/packages/SettingsLib/res/values-af/strings.xml
index 6576035..7e50996 100644
--- a/packages/SettingsLib/res/values-af/strings.xml
+++ b/packages/SettingsLib/res/values-af/strings.xml
@@ -55,6 +55,14 @@
<string name="bluetooth_connected_no_a2dp" msgid="4576188601581440337">"Gekoppel (geen media nie)"</string>
<string name="bluetooth_connected_no_map" msgid="6504436917057479986">"Gekoppel (geen boodskaptoegang nie)"</string>
<string name="bluetooth_connected_no_headset_no_a2dp" msgid="9195757766755553810">"Gekoppel (geen foon of media nie)"</string>
+ <!-- no translation found for bluetooth_connected_battery_level (7049181126136692368) -->
+ <skip />
+ <!-- no translation found for bluetooth_connected_no_headset_battery_level (5504193961248406027) -->
+ <skip />
+ <!-- no translation found for bluetooth_connected_no_a2dp_battery_level (4751724026365870779) -->
+ <skip />
+ <!-- no translation found for bluetooth_connected_no_headset_no_a2dp_battery_level (1549265779323455261) -->
+ <skip />
<string name="bluetooth_profile_a2dp" msgid="2031475486179830674">"Media-oudio"</string>
<string name="bluetooth_profile_headset" msgid="7815495680863246034">"Foonoproepe"</string>
<string name="bluetooth_profile_opp" msgid="9168139293654233697">"Lêeroordrag"</string>
diff --git a/packages/SettingsLib/res/values-am/strings.xml b/packages/SettingsLib/res/values-am/strings.xml
index d7ddedc..79cedfa 100644
--- a/packages/SettingsLib/res/values-am/strings.xml
+++ b/packages/SettingsLib/res/values-am/strings.xml
@@ -55,6 +55,14 @@
<string name="bluetooth_connected_no_a2dp" msgid="4576188601581440337">"ተያይዟል (ምንም ማህደረ መረጃ የለም)"</string>
<string name="bluetooth_connected_no_map" msgid="6504436917057479986">"ተገናኝቷል (ምንም የመልዕክት መዳረሻ የለም)"</string>
<string name="bluetooth_connected_no_headset_no_a2dp" msgid="9195757766755553810">"ተያይዟል (ምንም ስልክ ወይም ማህደረ መረጃ የለም)"</string>
+ <!-- no translation found for bluetooth_connected_battery_level (7049181126136692368) -->
+ <skip />
+ <!-- no translation found for bluetooth_connected_no_headset_battery_level (5504193961248406027) -->
+ <skip />
+ <!-- no translation found for bluetooth_connected_no_a2dp_battery_level (4751724026365870779) -->
+ <skip />
+ <!-- no translation found for bluetooth_connected_no_headset_no_a2dp_battery_level (1549265779323455261) -->
+ <skip />
<string name="bluetooth_profile_a2dp" msgid="2031475486179830674">"የማህደረ መረጃ ኦዲዮ"</string>
<string name="bluetooth_profile_headset" msgid="7815495680863246034">"የስልክ ጥሪዎች"</string>
<string name="bluetooth_profile_opp" msgid="9168139293654233697">"ፋይል ማስተላለፍ"</string>
diff --git a/packages/SettingsLib/res/values-ar/strings.xml b/packages/SettingsLib/res/values-ar/strings.xml
index c879100..d1b13a4 100644
--- a/packages/SettingsLib/res/values-ar/strings.xml
+++ b/packages/SettingsLib/res/values-ar/strings.xml
@@ -55,6 +55,14 @@
<string name="bluetooth_connected_no_a2dp" msgid="4576188601581440337">"متصل (بجهاز غير الوسائط)"</string>
<string name="bluetooth_connected_no_map" msgid="6504436917057479986">"تم الاتصال (يتعذر الدخول إلى الرسائل)"</string>
<string name="bluetooth_connected_no_headset_no_a2dp" msgid="9195757766755553810">"متصل (بجهاز غير الهاتف أو الوسائط)"</string>
+ <!-- no translation found for bluetooth_connected_battery_level (7049181126136692368) -->
+ <skip />
+ <!-- no translation found for bluetooth_connected_no_headset_battery_level (5504193961248406027) -->
+ <skip />
+ <!-- no translation found for bluetooth_connected_no_a2dp_battery_level (4751724026365870779) -->
+ <skip />
+ <!-- no translation found for bluetooth_connected_no_headset_no_a2dp_battery_level (1549265779323455261) -->
+ <skip />
<string name="bluetooth_profile_a2dp" msgid="2031475486179830674">"الإعدادات الصوتية للوسائط"</string>
<string name="bluetooth_profile_headset" msgid="7815495680863246034">"المكالمات الهاتفية"</string>
<string name="bluetooth_profile_opp" msgid="9168139293654233697">"نقل الملف"</string>
@@ -110,7 +118,7 @@
<string name="unknown" msgid="1592123443519355854">"غير معروف"</string>
<string name="running_process_item_user_label" msgid="3129887865552025943">"المستخدم: <xliff:g id="USER_NAME">%1$s</xliff:g>"</string>
<string name="launch_defaults_some" msgid="313159469856372621">"تم تعيين بعض الإعدادات الافتراضية"</string>
- <string name="launch_defaults_none" msgid="4241129108140034876">"لم يتم تعيين إعدادات افتراضية"</string>
+ <string name="launch_defaults_none" msgid="4241129108140034876">"لم يتم تعيين إعدادات تلقائية"</string>
<string name="tts_settings" msgid="8186971894801348327">"إعدادات تحويل النص إلى كلام"</string>
<string name="tts_settings_title" msgid="1237820681016639683">"إخراج تحويل النص إلى كلام"</string>
<string name="tts_default_rate_title" msgid="6030550998379310088">"معدل سرعة الكلام"</string>
diff --git a/packages/SettingsLib/res/values-az/strings.xml b/packages/SettingsLib/res/values-az/strings.xml
index 6b32c35..95ea112 100644
--- a/packages/SettingsLib/res/values-az/strings.xml
+++ b/packages/SettingsLib/res/values-az/strings.xml
@@ -55,6 +55,14 @@
<string name="bluetooth_connected_no_a2dp" msgid="4576188601581440337">"Qoşuludur (media yoxdur)"</string>
<string name="bluetooth_connected_no_map" msgid="6504436917057479986">"Qoşulu (mesaj girişi yoxdur)"</string>
<string name="bluetooth_connected_no_headset_no_a2dp" msgid="9195757766755553810">"Bağlantı yaradılıb (telefon və ya media deyil)"</string>
+ <!-- no translation found for bluetooth_connected_battery_level (7049181126136692368) -->
+ <skip />
+ <!-- no translation found for bluetooth_connected_no_headset_battery_level (5504193961248406027) -->
+ <skip />
+ <!-- no translation found for bluetooth_connected_no_a2dp_battery_level (4751724026365870779) -->
+ <skip />
+ <!-- no translation found for bluetooth_connected_no_headset_no_a2dp_battery_level (1549265779323455261) -->
+ <skip />
<string name="bluetooth_profile_a2dp" msgid="2031475486179830674">"Media audio"</string>
<string name="bluetooth_profile_headset" msgid="7815495680863246034">"Telefon zəngləri"</string>
<string name="bluetooth_profile_opp" msgid="9168139293654233697">"Fayl transferi"</string>
diff --git a/packages/SettingsLib/res/values-b+sr+Latn/strings.xml b/packages/SettingsLib/res/values-b+sr+Latn/strings.xml
index 0f323dd..7a2ee50 100644
--- a/packages/SettingsLib/res/values-b+sr+Latn/strings.xml
+++ b/packages/SettingsLib/res/values-b+sr+Latn/strings.xml
@@ -55,6 +55,14 @@
<string name="bluetooth_connected_no_a2dp" msgid="4576188601581440337">"Povezano (bez medija)"</string>
<string name="bluetooth_connected_no_map" msgid="6504436917057479986">"Povezano je (nema pristupa porukama)"</string>
<string name="bluetooth_connected_no_headset_no_a2dp" msgid="9195757766755553810">"Povezano (bez telefona ili medija)"</string>
+ <!-- no translation found for bluetooth_connected_battery_level (7049181126136692368) -->
+ <skip />
+ <!-- no translation found for bluetooth_connected_no_headset_battery_level (5504193961248406027) -->
+ <skip />
+ <!-- no translation found for bluetooth_connected_no_a2dp_battery_level (4751724026365870779) -->
+ <skip />
+ <!-- no translation found for bluetooth_connected_no_headset_no_a2dp_battery_level (1549265779323455261) -->
+ <skip />
<string name="bluetooth_profile_a2dp" msgid="2031475486179830674">"Zvuk medija"</string>
<string name="bluetooth_profile_headset" msgid="7815495680863246034">"Telefonski pozivi"</string>
<string name="bluetooth_profile_opp" msgid="9168139293654233697">"Prenos datoteke"</string>
@@ -352,7 +360,7 @@
<string name="disabled" msgid="9206776641295849915">"Onemogućeno"</string>
<string name="external_source_trusted" msgid="2707996266575928037">"Dozvoljeno"</string>
<string name="external_source_untrusted" msgid="2677442511837596726">"Nije dozvoljeno"</string>
- <string name="install_other_apps" msgid="6986686991775883017">"Instalirajte nepozn. apl."</string>
+ <string name="install_other_apps" msgid="6986686991775883017">"Instaliranje nepoznatih aplikacija"</string>
<string name="home" msgid="3256884684164448244">"Početna za Podešavanja"</string>
<string-array name="battery_labels">
<item msgid="8494684293649631252">"0%"</item>
diff --git a/packages/SettingsLib/res/values-be/strings.xml b/packages/SettingsLib/res/values-be/strings.xml
index 5f7332c..834e689 100644
--- a/packages/SettingsLib/res/values-be/strings.xml
+++ b/packages/SettingsLib/res/values-be/strings.xml
@@ -55,6 +55,14 @@
<string name="bluetooth_connected_no_a2dp" msgid="4576188601581440337">"Падключэнне (без носьбіта)"</string>
<string name="bluetooth_connected_no_map" msgid="6504436917057479986">"Падлучана (без доступу да паведамленняў)"</string>
<string name="bluetooth_connected_no_headset_no_a2dp" msgid="9195757766755553810">"Падключаны (без тэлефона або носьбіта)"</string>
+ <!-- no translation found for bluetooth_connected_battery_level (7049181126136692368) -->
+ <skip />
+ <!-- no translation found for bluetooth_connected_no_headset_battery_level (5504193961248406027) -->
+ <skip />
+ <!-- no translation found for bluetooth_connected_no_a2dp_battery_level (4751724026365870779) -->
+ <skip />
+ <!-- no translation found for bluetooth_connected_no_headset_no_a2dp_battery_level (1549265779323455261) -->
+ <skip />
<string name="bluetooth_profile_a2dp" msgid="2031475486179830674">"Аўдыё медыяпрылады"</string>
<string name="bluetooth_profile_headset" msgid="7815495680863246034">"Тэлефонныя выклікі"</string>
<string name="bluetooth_profile_opp" msgid="9168139293654233697">"Перадача файлаў"</string>
diff --git a/packages/SettingsLib/res/values-bg/strings.xml b/packages/SettingsLib/res/values-bg/strings.xml
index b69e290..ce9ee56 100644
--- a/packages/SettingsLib/res/values-bg/strings.xml
+++ b/packages/SettingsLib/res/values-bg/strings.xml
@@ -55,6 +55,14 @@
<string name="bluetooth_connected_no_a2dp" msgid="4576188601581440337">"Свързано (без мултимедията)"</string>
<string name="bluetooth_connected_no_map" msgid="6504436917057479986">"Има връзка (няма достъп до съобщенията)"</string>
<string name="bluetooth_connected_no_headset_no_a2dp" msgid="9195757766755553810">"Свързано (без телефона или мултимедията)"</string>
+ <!-- no translation found for bluetooth_connected_battery_level (7049181126136692368) -->
+ <skip />
+ <!-- no translation found for bluetooth_connected_no_headset_battery_level (5504193961248406027) -->
+ <skip />
+ <!-- no translation found for bluetooth_connected_no_a2dp_battery_level (4751724026365870779) -->
+ <skip />
+ <!-- no translation found for bluetooth_connected_no_headset_no_a2dp_battery_level (1549265779323455261) -->
+ <skip />
<string name="bluetooth_profile_a2dp" msgid="2031475486179830674">"Мултимедийно аудио"</string>
<string name="bluetooth_profile_headset" msgid="7815495680863246034">"Телефонни обаждания"</string>
<string name="bluetooth_profile_opp" msgid="9168139293654233697">"Прехвърляне на файл"</string>
diff --git a/packages/SettingsLib/res/values-bn/strings.xml b/packages/SettingsLib/res/values-bn/strings.xml
index e8faf5d..5093a6a 100644
--- a/packages/SettingsLib/res/values-bn/strings.xml
+++ b/packages/SettingsLib/res/values-bn/strings.xml
@@ -55,6 +55,14 @@
<string name="bluetooth_connected_no_a2dp" msgid="4576188601581440337">"সংযুক্ত (কোনো মিডিয়া নেই)"</string>
<string name="bluetooth_connected_no_map" msgid="6504436917057479986">"সংযুক্ত (কোনো বার্তা অ্যাক্সেস নেই)"</string>
<string name="bluetooth_connected_no_headset_no_a2dp" msgid="9195757766755553810">"সংযুক্ত (কোনো ফোন বা মিডিয়া নেই)"</string>
+ <!-- no translation found for bluetooth_connected_battery_level (7049181126136692368) -->
+ <skip />
+ <!-- no translation found for bluetooth_connected_no_headset_battery_level (5504193961248406027) -->
+ <skip />
+ <!-- no translation found for bluetooth_connected_no_a2dp_battery_level (4751724026365870779) -->
+ <skip />
+ <!-- no translation found for bluetooth_connected_no_headset_no_a2dp_battery_level (1549265779323455261) -->
+ <skip />
<string name="bluetooth_profile_a2dp" msgid="2031475486179830674">"মিডিয়া অডিও"</string>
<string name="bluetooth_profile_headset" msgid="7815495680863246034">"ফোন কল"</string>
<string name="bluetooth_profile_opp" msgid="9168139293654233697">"ফাইল স্থানান্তর"</string>
diff --git a/packages/SettingsLib/res/values-bs/strings.xml b/packages/SettingsLib/res/values-bs/strings.xml
index deab61d..1af6e30 100644
--- a/packages/SettingsLib/res/values-bs/strings.xml
+++ b/packages/SettingsLib/res/values-bs/strings.xml
@@ -55,6 +55,14 @@
<string name="bluetooth_connected_no_a2dp" msgid="4576188601581440337">"Povezano (bez medija)"</string>
<string name="bluetooth_connected_no_map" msgid="6504436917057479986">"Povezano (bez pristupa porukama)"</string>
<string name="bluetooth_connected_no_headset_no_a2dp" msgid="9195757766755553810">"Povezano (bez zvuka telefona ili medija)"</string>
+ <!-- no translation found for bluetooth_connected_battery_level (7049181126136692368) -->
+ <skip />
+ <!-- no translation found for bluetooth_connected_no_headset_battery_level (5504193961248406027) -->
+ <skip />
+ <!-- no translation found for bluetooth_connected_no_a2dp_battery_level (4751724026365870779) -->
+ <skip />
+ <!-- no translation found for bluetooth_connected_no_headset_no_a2dp_battery_level (1549265779323455261) -->
+ <skip />
<string name="bluetooth_profile_a2dp" msgid="2031475486179830674">"Zvuk medija"</string>
<string name="bluetooth_profile_headset" msgid="7815495680863246034">"Telefonski pozivi"</string>
<string name="bluetooth_profile_opp" msgid="9168139293654233697">"Prenošenje fajla"</string>
diff --git a/packages/SettingsLib/res/values-ca/strings.xml b/packages/SettingsLib/res/values-ca/strings.xml
index 438cbbb..a5524ae 100644
--- a/packages/SettingsLib/res/values-ca/strings.xml
+++ b/packages/SettingsLib/res/values-ca/strings.xml
@@ -55,6 +55,14 @@
<string name="bluetooth_connected_no_a2dp" msgid="4576188601581440337">"Connectat (sense fitxers multimèdia)"</string>
<string name="bluetooth_connected_no_map" msgid="6504436917057479986">"Connectat (no hi ha accés als missatges)"</string>
<string name="bluetooth_connected_no_headset_no_a2dp" msgid="9195757766755553810">"Connectat (sense telèfon o disp. mult.)"</string>
+ <!-- no translation found for bluetooth_connected_battery_level (7049181126136692368) -->
+ <skip />
+ <!-- no translation found for bluetooth_connected_no_headset_battery_level (5504193961248406027) -->
+ <skip />
+ <!-- no translation found for bluetooth_connected_no_a2dp_battery_level (4751724026365870779) -->
+ <skip />
+ <!-- no translation found for bluetooth_connected_no_headset_no_a2dp_battery_level (1549265779323455261) -->
+ <skip />
<string name="bluetooth_profile_a2dp" msgid="2031475486179830674">"Àudio multimèdia"</string>
<string name="bluetooth_profile_headset" msgid="7815495680863246034">"Trucades telefòniques"</string>
<string name="bluetooth_profile_opp" msgid="9168139293654233697">"Transferència del fitxer"</string>
diff --git a/packages/SettingsLib/res/values-cs/strings.xml b/packages/SettingsLib/res/values-cs/strings.xml
index 2b8f811..8d82e80 100644
--- a/packages/SettingsLib/res/values-cs/strings.xml
+++ b/packages/SettingsLib/res/values-cs/strings.xml
@@ -55,6 +55,14 @@
<string name="bluetooth_connected_no_a2dp" msgid="4576188601581440337">"Připojeno (žádná média)"</string>
<string name="bluetooth_connected_no_map" msgid="6504436917057479986">"Připojeno (bez přístupu ke zprávám)"</string>
<string name="bluetooth_connected_no_headset_no_a2dp" msgid="9195757766755553810">"Připojeno (žádný telefon nebo média)"</string>
+ <!-- no translation found for bluetooth_connected_battery_level (7049181126136692368) -->
+ <skip />
+ <!-- no translation found for bluetooth_connected_no_headset_battery_level (5504193961248406027) -->
+ <skip />
+ <!-- no translation found for bluetooth_connected_no_a2dp_battery_level (4751724026365870779) -->
+ <skip />
+ <!-- no translation found for bluetooth_connected_no_headset_no_a2dp_battery_level (1549265779323455261) -->
+ <skip />
<string name="bluetooth_profile_a2dp" msgid="2031475486179830674">"Zvuk médií"</string>
<string name="bluetooth_profile_headset" msgid="7815495680863246034">"Telefonní hovory"</string>
<string name="bluetooth_profile_opp" msgid="9168139293654233697">"Přenos souborů"</string>
diff --git a/packages/SettingsLib/res/values-da/strings.xml b/packages/SettingsLib/res/values-da/strings.xml
index c82a0cb..73662943 100644
--- a/packages/SettingsLib/res/values-da/strings.xml
+++ b/packages/SettingsLib/res/values-da/strings.xml
@@ -55,6 +55,14 @@
<string name="bluetooth_connected_no_a2dp" msgid="4576188601581440337">"Tilsluttet (intet medie)"</string>
<string name="bluetooth_connected_no_map" msgid="6504436917057479986">"Forbundet (ingen adgang til meddelelse)"</string>
<string name="bluetooth_connected_no_headset_no_a2dp" msgid="9195757766755553810">"Forbundet (ingen telefon eller medier)"</string>
+ <!-- no translation found for bluetooth_connected_battery_level (7049181126136692368) -->
+ <skip />
+ <!-- no translation found for bluetooth_connected_no_headset_battery_level (5504193961248406027) -->
+ <skip />
+ <!-- no translation found for bluetooth_connected_no_a2dp_battery_level (4751724026365870779) -->
+ <skip />
+ <!-- no translation found for bluetooth_connected_no_headset_no_a2dp_battery_level (1549265779323455261) -->
+ <skip />
<string name="bluetooth_profile_a2dp" msgid="2031475486179830674">"Medielyd"</string>
<string name="bluetooth_profile_headset" msgid="7815495680863246034">"Telefonopkald"</string>
<string name="bluetooth_profile_opp" msgid="9168139293654233697">"Filoverførsel"</string>
diff --git a/packages/SettingsLib/res/values-de/strings.xml b/packages/SettingsLib/res/values-de/strings.xml
index a6e0fd9b..ccfa675 100644
--- a/packages/SettingsLib/res/values-de/strings.xml
+++ b/packages/SettingsLib/res/values-de/strings.xml
@@ -55,6 +55,14 @@
<string name="bluetooth_connected_no_a2dp" msgid="4576188601581440337">"Verbunden (außer Audiomedien)"</string>
<string name="bluetooth_connected_no_map" msgid="6504436917057479986">"Verbunden (ohne Nachrichtenzugriff)"</string>
<string name="bluetooth_connected_no_headset_no_a2dp" msgid="9195757766755553810">"Verbunden (außer Telefon- und Audiomedien)"</string>
+ <!-- no translation found for bluetooth_connected_battery_level (7049181126136692368) -->
+ <skip />
+ <!-- no translation found for bluetooth_connected_no_headset_battery_level (5504193961248406027) -->
+ <skip />
+ <!-- no translation found for bluetooth_connected_no_a2dp_battery_level (4751724026365870779) -->
+ <skip />
+ <!-- no translation found for bluetooth_connected_no_headset_no_a2dp_battery_level (1549265779323455261) -->
+ <skip />
<string name="bluetooth_profile_a2dp" msgid="2031475486179830674">"Media-Audio"</string>
<string name="bluetooth_profile_headset" msgid="7815495680863246034">"Telefonanrufe"</string>
<string name="bluetooth_profile_opp" msgid="9168139293654233697">"Dateiübertragung"</string>
diff --git a/packages/SettingsLib/res/values-el/strings.xml b/packages/SettingsLib/res/values-el/strings.xml
index 7ae2778..e424b28 100644
--- a/packages/SettingsLib/res/values-el/strings.xml
+++ b/packages/SettingsLib/res/values-el/strings.xml
@@ -55,6 +55,14 @@
<string name="bluetooth_connected_no_a2dp" msgid="4576188601581440337">"Συνδεδεμένο (όχι μέσα)"</string>
<string name="bluetooth_connected_no_map" msgid="6504436917057479986">"Συνδεδεμένο (χωρίς πρόσβαση μηνύματος)"</string>
<string name="bluetooth_connected_no_headset_no_a2dp" msgid="9195757766755553810">"Συνδεδεμένο (χωρίς τηλέφωνο ή πολυμέσα)"</string>
+ <!-- no translation found for bluetooth_connected_battery_level (7049181126136692368) -->
+ <skip />
+ <!-- no translation found for bluetooth_connected_no_headset_battery_level (5504193961248406027) -->
+ <skip />
+ <!-- no translation found for bluetooth_connected_no_a2dp_battery_level (4751724026365870779) -->
+ <skip />
+ <!-- no translation found for bluetooth_connected_no_headset_no_a2dp_battery_level (1549265779323455261) -->
+ <skip />
<string name="bluetooth_profile_a2dp" msgid="2031475486179830674">"Ήχος πολυμέσων"</string>
<string name="bluetooth_profile_headset" msgid="7815495680863246034">"Τηλεφωνικές κλήσεις"</string>
<string name="bluetooth_profile_opp" msgid="9168139293654233697">"Μεταφορά αρχείου"</string>
diff --git a/packages/SettingsLib/res/values-en-rAU/strings.xml b/packages/SettingsLib/res/values-en-rAU/strings.xml
index d10726f..de32f3c 100644
--- a/packages/SettingsLib/res/values-en-rAU/strings.xml
+++ b/packages/SettingsLib/res/values-en-rAU/strings.xml
@@ -55,6 +55,14 @@
<string name="bluetooth_connected_no_a2dp" msgid="4576188601581440337">"Connected (no media)"</string>
<string name="bluetooth_connected_no_map" msgid="6504436917057479986">"Connected (no message access)"</string>
<string name="bluetooth_connected_no_headset_no_a2dp" msgid="9195757766755553810">"Connected (no phone or media)"</string>
+ <!-- no translation found for bluetooth_connected_battery_level (7049181126136692368) -->
+ <skip />
+ <!-- no translation found for bluetooth_connected_no_headset_battery_level (5504193961248406027) -->
+ <skip />
+ <!-- no translation found for bluetooth_connected_no_a2dp_battery_level (4751724026365870779) -->
+ <skip />
+ <!-- no translation found for bluetooth_connected_no_headset_no_a2dp_battery_level (1549265779323455261) -->
+ <skip />
<string name="bluetooth_profile_a2dp" msgid="2031475486179830674">"Media audio"</string>
<string name="bluetooth_profile_headset" msgid="7815495680863246034">"Phone calls"</string>
<string name="bluetooth_profile_opp" msgid="9168139293654233697">"File transfer"</string>
diff --git a/packages/SettingsLib/res/values-en-rGB/strings.xml b/packages/SettingsLib/res/values-en-rGB/strings.xml
index d10726f..de32f3c 100644
--- a/packages/SettingsLib/res/values-en-rGB/strings.xml
+++ b/packages/SettingsLib/res/values-en-rGB/strings.xml
@@ -55,6 +55,14 @@
<string name="bluetooth_connected_no_a2dp" msgid="4576188601581440337">"Connected (no media)"</string>
<string name="bluetooth_connected_no_map" msgid="6504436917057479986">"Connected (no message access)"</string>
<string name="bluetooth_connected_no_headset_no_a2dp" msgid="9195757766755553810">"Connected (no phone or media)"</string>
+ <!-- no translation found for bluetooth_connected_battery_level (7049181126136692368) -->
+ <skip />
+ <!-- no translation found for bluetooth_connected_no_headset_battery_level (5504193961248406027) -->
+ <skip />
+ <!-- no translation found for bluetooth_connected_no_a2dp_battery_level (4751724026365870779) -->
+ <skip />
+ <!-- no translation found for bluetooth_connected_no_headset_no_a2dp_battery_level (1549265779323455261) -->
+ <skip />
<string name="bluetooth_profile_a2dp" msgid="2031475486179830674">"Media audio"</string>
<string name="bluetooth_profile_headset" msgid="7815495680863246034">"Phone calls"</string>
<string name="bluetooth_profile_opp" msgid="9168139293654233697">"File transfer"</string>
diff --git a/packages/SettingsLib/res/values-en-rIN/strings.xml b/packages/SettingsLib/res/values-en-rIN/strings.xml
index d10726f..de32f3c 100644
--- a/packages/SettingsLib/res/values-en-rIN/strings.xml
+++ b/packages/SettingsLib/res/values-en-rIN/strings.xml
@@ -55,6 +55,14 @@
<string name="bluetooth_connected_no_a2dp" msgid="4576188601581440337">"Connected (no media)"</string>
<string name="bluetooth_connected_no_map" msgid="6504436917057479986">"Connected (no message access)"</string>
<string name="bluetooth_connected_no_headset_no_a2dp" msgid="9195757766755553810">"Connected (no phone or media)"</string>
+ <!-- no translation found for bluetooth_connected_battery_level (7049181126136692368) -->
+ <skip />
+ <!-- no translation found for bluetooth_connected_no_headset_battery_level (5504193961248406027) -->
+ <skip />
+ <!-- no translation found for bluetooth_connected_no_a2dp_battery_level (4751724026365870779) -->
+ <skip />
+ <!-- no translation found for bluetooth_connected_no_headset_no_a2dp_battery_level (1549265779323455261) -->
+ <skip />
<string name="bluetooth_profile_a2dp" msgid="2031475486179830674">"Media audio"</string>
<string name="bluetooth_profile_headset" msgid="7815495680863246034">"Phone calls"</string>
<string name="bluetooth_profile_opp" msgid="9168139293654233697">"File transfer"</string>
diff --git a/packages/SettingsLib/res/values-es-rUS/strings.xml b/packages/SettingsLib/res/values-es-rUS/strings.xml
index 2949012..f261cbf 100644
--- a/packages/SettingsLib/res/values-es-rUS/strings.xml
+++ b/packages/SettingsLib/res/values-es-rUS/strings.xml
@@ -55,6 +55,14 @@
<string name="bluetooth_connected_no_a2dp" msgid="4576188601581440337">"Conectado (sin audio multimedia)"</string>
<string name="bluetooth_connected_no_map" msgid="6504436917057479986">"Conectado (sin acceso a mensajes)"</string>
<string name="bluetooth_connected_no_headset_no_a2dp" msgid="9195757766755553810">"Conectado (sin tel. ni audio multimedia)"</string>
+ <!-- no translation found for bluetooth_connected_battery_level (7049181126136692368) -->
+ <skip />
+ <!-- no translation found for bluetooth_connected_no_headset_battery_level (5504193961248406027) -->
+ <skip />
+ <!-- no translation found for bluetooth_connected_no_a2dp_battery_level (4751724026365870779) -->
+ <skip />
+ <!-- no translation found for bluetooth_connected_no_headset_no_a2dp_battery_level (1549265779323455261) -->
+ <skip />
<string name="bluetooth_profile_a2dp" msgid="2031475486179830674">"Audio multimedia"</string>
<string name="bluetooth_profile_headset" msgid="7815495680863246034">"Llamadas telefónicas"</string>
<string name="bluetooth_profile_opp" msgid="9168139293654233697">"Transferencia de archivos"</string>
diff --git a/packages/SettingsLib/res/values-es/strings.xml b/packages/SettingsLib/res/values-es/strings.xml
index 487d847..d52ac06 100644
--- a/packages/SettingsLib/res/values-es/strings.xml
+++ b/packages/SettingsLib/res/values-es/strings.xml
@@ -55,6 +55,14 @@
<string name="bluetooth_connected_no_a2dp" msgid="4576188601581440337">"Conectado (sin audio multimedia)"</string>
<string name="bluetooth_connected_no_map" msgid="6504436917057479986">"Conectado (sin acceso a mensajes)"</string>
<string name="bluetooth_connected_no_headset_no_a2dp" msgid="9195757766755553810">"Conectado (sin teléfono ni multimedia)"</string>
+ <!-- no translation found for bluetooth_connected_battery_level (7049181126136692368) -->
+ <skip />
+ <!-- no translation found for bluetooth_connected_no_headset_battery_level (5504193961248406027) -->
+ <skip />
+ <!-- no translation found for bluetooth_connected_no_a2dp_battery_level (4751724026365870779) -->
+ <skip />
+ <!-- no translation found for bluetooth_connected_no_headset_no_a2dp_battery_level (1549265779323455261) -->
+ <skip />
<string name="bluetooth_profile_a2dp" msgid="2031475486179830674">"Audio multimedia"</string>
<string name="bluetooth_profile_headset" msgid="7815495680863246034">"Llamadas de teléfono"</string>
<string name="bluetooth_profile_opp" msgid="9168139293654233697">"Transferencia de archivos"</string>
diff --git a/packages/SettingsLib/res/values-et/strings.xml b/packages/SettingsLib/res/values-et/strings.xml
index 91e75912..5cb3e2a 100644
--- a/packages/SettingsLib/res/values-et/strings.xml
+++ b/packages/SettingsLib/res/values-et/strings.xml
@@ -55,6 +55,14 @@
<string name="bluetooth_connected_no_a2dp" msgid="4576188601581440337">"Ühendatud (meediat pole)"</string>
<string name="bluetooth_connected_no_map" msgid="6504436917057479986">"Ühendatud (sõnumita juurdepääs)"</string>
<string name="bluetooth_connected_no_headset_no_a2dp" msgid="9195757766755553810">"Ühendatud (pole telefoni ega meediat)"</string>
+ <!-- no translation found for bluetooth_connected_battery_level (7049181126136692368) -->
+ <skip />
+ <!-- no translation found for bluetooth_connected_no_headset_battery_level (5504193961248406027) -->
+ <skip />
+ <!-- no translation found for bluetooth_connected_no_a2dp_battery_level (4751724026365870779) -->
+ <skip />
+ <!-- no translation found for bluetooth_connected_no_headset_no_a2dp_battery_level (1549265779323455261) -->
+ <skip />
<string name="bluetooth_profile_a2dp" msgid="2031475486179830674">"Meedia heli"</string>
<string name="bluetooth_profile_headset" msgid="7815495680863246034">"Telefonikõned"</string>
<string name="bluetooth_profile_opp" msgid="9168139293654233697">"Failiedastus"</string>
diff --git a/packages/SettingsLib/res/values-eu/strings.xml b/packages/SettingsLib/res/values-eu/strings.xml
index 7f00f08..e4b6c95 100644
--- a/packages/SettingsLib/res/values-eu/strings.xml
+++ b/packages/SettingsLib/res/values-eu/strings.xml
@@ -55,6 +55,14 @@
<string name="bluetooth_connected_no_a2dp" msgid="4576188601581440337">"Konektatuta (ez dago euskarririk)"</string>
<string name="bluetooth_connected_no_map" msgid="6504436917057479986">"Konektatuta (mezuetarako sarbiderik ez)"</string>
<string name="bluetooth_connected_no_headset_no_a2dp" msgid="9195757766755553810">"Konektatuta (ez dago telef./euskarririk)"</string>
+ <!-- no translation found for bluetooth_connected_battery_level (7049181126136692368) -->
+ <skip />
+ <!-- no translation found for bluetooth_connected_no_headset_battery_level (5504193961248406027) -->
+ <skip />
+ <!-- no translation found for bluetooth_connected_no_a2dp_battery_level (4751724026365870779) -->
+ <skip />
+ <!-- no translation found for bluetooth_connected_no_headset_no_a2dp_battery_level (1549265779323455261) -->
+ <skip />
<string name="bluetooth_profile_a2dp" msgid="2031475486179830674">"Euskarriaren audioa"</string>
<string name="bluetooth_profile_headset" msgid="7815495680863246034">"Telefono-deiak"</string>
<string name="bluetooth_profile_opp" msgid="9168139293654233697">"Fitxategi-transferentzia"</string>
diff --git a/packages/SettingsLib/res/values-fa/strings.xml b/packages/SettingsLib/res/values-fa/strings.xml
index fac966a..bf10b1a 100644
--- a/packages/SettingsLib/res/values-fa/strings.xml
+++ b/packages/SettingsLib/res/values-fa/strings.xml
@@ -55,6 +55,14 @@
<string name="bluetooth_connected_no_a2dp" msgid="4576188601581440337">"متصل شد (بدون رسانه)"</string>
<string name="bluetooth_connected_no_map" msgid="6504436917057479986">"متصل (عدم دسترسی به پیام)"</string>
<string name="bluetooth_connected_no_headset_no_a2dp" msgid="9195757766755553810">"متصل شد (بدون تلفن یا رسانه)"</string>
+ <!-- no translation found for bluetooth_connected_battery_level (7049181126136692368) -->
+ <skip />
+ <!-- no translation found for bluetooth_connected_no_headset_battery_level (5504193961248406027) -->
+ <skip />
+ <!-- no translation found for bluetooth_connected_no_a2dp_battery_level (4751724026365870779) -->
+ <skip />
+ <!-- no translation found for bluetooth_connected_no_headset_no_a2dp_battery_level (1549265779323455261) -->
+ <skip />
<string name="bluetooth_profile_a2dp" msgid="2031475486179830674">"رسانه صوتی"</string>
<string name="bluetooth_profile_headset" msgid="7815495680863246034">"تماسهای تلفنی"</string>
<string name="bluetooth_profile_opp" msgid="9168139293654233697">"انتقال فایل"</string>
diff --git a/packages/SettingsLib/res/values-fi/strings.xml b/packages/SettingsLib/res/values-fi/strings.xml
index 3ec8e48..42a0127 100644
--- a/packages/SettingsLib/res/values-fi/strings.xml
+++ b/packages/SettingsLib/res/values-fi/strings.xml
@@ -55,6 +55,14 @@
<string name="bluetooth_connected_no_a2dp" msgid="4576188601581440337">"Yhdistetty (ei median ääntä)"</string>
<string name="bluetooth_connected_no_map" msgid="6504436917057479986">"Yhdistetty (ei MAP)"</string>
<string name="bluetooth_connected_no_headset_no_a2dp" msgid="9195757766755553810">"Yhdistetty (ei puhelimen/median ääntä)"</string>
+ <!-- no translation found for bluetooth_connected_battery_level (7049181126136692368) -->
+ <skip />
+ <!-- no translation found for bluetooth_connected_no_headset_battery_level (5504193961248406027) -->
+ <skip />
+ <!-- no translation found for bluetooth_connected_no_a2dp_battery_level (4751724026365870779) -->
+ <skip />
+ <!-- no translation found for bluetooth_connected_no_headset_no_a2dp_battery_level (1549265779323455261) -->
+ <skip />
<string name="bluetooth_profile_a2dp" msgid="2031475486179830674">"Median ääni"</string>
<string name="bluetooth_profile_headset" msgid="7815495680863246034">"Puhelut"</string>
<string name="bluetooth_profile_opp" msgid="9168139293654233697">"Tiedostonsiirto"</string>
diff --git a/packages/SettingsLib/res/values-fr-rCA/strings.xml b/packages/SettingsLib/res/values-fr-rCA/strings.xml
index bc4b781..88fd9cb 100644
--- a/packages/SettingsLib/res/values-fr-rCA/strings.xml
+++ b/packages/SettingsLib/res/values-fr-rCA/strings.xml
@@ -55,6 +55,14 @@
<string name="bluetooth_connected_no_a2dp" msgid="4576188601581440337">"Connecté (sans audio contenu mutimédia)"</string>
<string name="bluetooth_connected_no_map" msgid="6504436917057479986">"Connecté (sans accès aux messages)"</string>
<string name="bluetooth_connected_no_headset_no_a2dp" msgid="9195757766755553810">"Connecté (sans audio tel./multimédia)"</string>
+ <!-- no translation found for bluetooth_connected_battery_level (7049181126136692368) -->
+ <skip />
+ <!-- no translation found for bluetooth_connected_no_headset_battery_level (5504193961248406027) -->
+ <skip />
+ <!-- no translation found for bluetooth_connected_no_a2dp_battery_level (4751724026365870779) -->
+ <skip />
+ <!-- no translation found for bluetooth_connected_no_headset_no_a2dp_battery_level (1549265779323455261) -->
+ <skip />
<string name="bluetooth_profile_a2dp" msgid="2031475486179830674">"Paramètres audio du support"</string>
<string name="bluetooth_profile_headset" msgid="7815495680863246034">"Appels téléphoniques"</string>
<string name="bluetooth_profile_opp" msgid="9168139293654233697">"Transfert de fichier"</string>
diff --git a/packages/SettingsLib/res/values-fr/strings.xml b/packages/SettingsLib/res/values-fr/strings.xml
index 4853bc8..c5f951d 100644
--- a/packages/SettingsLib/res/values-fr/strings.xml
+++ b/packages/SettingsLib/res/values-fr/strings.xml
@@ -55,6 +55,14 @@
<string name="bluetooth_connected_no_a2dp" msgid="4576188601581440337">"Connecté (sans audio contenu mutimédia)"</string>
<string name="bluetooth_connected_no_map" msgid="6504436917057479986">"Connecté (sans accès aux messages)"</string>
<string name="bluetooth_connected_no_headset_no_a2dp" msgid="9195757766755553810">"Connecté (sans audio tel./multimédia)"</string>
+ <!-- no translation found for bluetooth_connected_battery_level (7049181126136692368) -->
+ <skip />
+ <!-- no translation found for bluetooth_connected_no_headset_battery_level (5504193961248406027) -->
+ <skip />
+ <!-- no translation found for bluetooth_connected_no_a2dp_battery_level (4751724026365870779) -->
+ <skip />
+ <!-- no translation found for bluetooth_connected_no_headset_no_a2dp_battery_level (1549265779323455261) -->
+ <skip />
<string name="bluetooth_profile_a2dp" msgid="2031475486179830674">"Multimédia"</string>
<string name="bluetooth_profile_headset" msgid="7815495680863246034">"Appels téléphoniques"</string>
<string name="bluetooth_profile_opp" msgid="9168139293654233697">"Transfert de fichier"</string>
@@ -352,7 +360,7 @@
<string name="disabled" msgid="9206776641295849915">"Désactivée"</string>
<string name="external_source_trusted" msgid="2707996266575928037">"Autorisé"</string>
<string name="external_source_untrusted" msgid="2677442511837596726">"Non autorisé"</string>
- <string name="install_other_apps" msgid="6986686991775883017">"Installation d\'applications inconnues"</string>
+ <string name="install_other_apps" msgid="6986686991775883017">"Installation d\'applis inconnues"</string>
<string name="home" msgid="3256884684164448244">"Paramètres"</string>
<string-array name="battery_labels">
<item msgid="8494684293649631252">"0 %"</item>
diff --git a/packages/SettingsLib/res/values-gl/strings.xml b/packages/SettingsLib/res/values-gl/strings.xml
index 9043712..d60d072 100644
--- a/packages/SettingsLib/res/values-gl/strings.xml
+++ b/packages/SettingsLib/res/values-gl/strings.xml
@@ -55,6 +55,14 @@
<string name="bluetooth_connected_no_a2dp" msgid="4576188601581440337">"Conectado (sen ficheiros multimedia)"</string>
<string name="bluetooth_connected_no_map" msgid="6504436917057479986">"Conectado (sen acceso ás mensaxes)"</string>
<string name="bluetooth_connected_no_headset_no_a2dp" msgid="9195757766755553810">"Conectado (ningún teléfono nin soporte)"</string>
+ <!-- no translation found for bluetooth_connected_battery_level (7049181126136692368) -->
+ <skip />
+ <!-- no translation found for bluetooth_connected_no_headset_battery_level (5504193961248406027) -->
+ <skip />
+ <!-- no translation found for bluetooth_connected_no_a2dp_battery_level (4751724026365870779) -->
+ <skip />
+ <!-- no translation found for bluetooth_connected_no_headset_no_a2dp_battery_level (1549265779323455261) -->
+ <skip />
<string name="bluetooth_profile_a2dp" msgid="2031475486179830674">"Audio multimedia"</string>
<string name="bluetooth_profile_headset" msgid="7815495680863246034">"Chamadas telefónicas"</string>
<string name="bluetooth_profile_opp" msgid="9168139293654233697">"Transferencia de ficheiros"</string>
diff --git a/packages/SettingsLib/res/values-gu/strings.xml b/packages/SettingsLib/res/values-gu/strings.xml
index 9ec0c33..20d92f2 100644
--- a/packages/SettingsLib/res/values-gu/strings.xml
+++ b/packages/SettingsLib/res/values-gu/strings.xml
@@ -55,6 +55,14 @@
<string name="bluetooth_connected_no_a2dp" msgid="4576188601581440337">"કનેક્ટ કર્યું (મીડિયા નથી)"</string>
<string name="bluetooth_connected_no_map" msgid="6504436917057479986">"કનેક્ટ કર્યું (કોઇ સંદેશ ઍક્સેસ નથી)"</string>
<string name="bluetooth_connected_no_headset_no_a2dp" msgid="9195757766755553810">"કનેક્ટ કરેલ (કોઈ ફોન અથવા મીડિયા નથી)"</string>
+ <!-- no translation found for bluetooth_connected_battery_level (7049181126136692368) -->
+ <skip />
+ <!-- no translation found for bluetooth_connected_no_headset_battery_level (5504193961248406027) -->
+ <skip />
+ <!-- no translation found for bluetooth_connected_no_a2dp_battery_level (4751724026365870779) -->
+ <skip />
+ <!-- no translation found for bluetooth_connected_no_headset_no_a2dp_battery_level (1549265779323455261) -->
+ <skip />
<string name="bluetooth_profile_a2dp" msgid="2031475486179830674">"મીડિયા ઑડિઓ"</string>
<string name="bluetooth_profile_headset" msgid="7815495680863246034">"ફોન કૉલ"</string>
<string name="bluetooth_profile_opp" msgid="9168139293654233697">"ફાઇલ સ્થાનાંતરણ"</string>
diff --git a/packages/SettingsLib/res/values-hi/strings.xml b/packages/SettingsLib/res/values-hi/strings.xml
index 9078817..217099d 100644
--- a/packages/SettingsLib/res/values-hi/strings.xml
+++ b/packages/SettingsLib/res/values-hi/strings.xml
@@ -55,6 +55,14 @@
<string name="bluetooth_connected_no_a2dp" msgid="4576188601581440337">"कनेक्ट है (मीडिया नहीं)"</string>
<string name="bluetooth_connected_no_map" msgid="6504436917057479986">"कनेक्ट किया गया (कोई संदेश एक्सेस नहीं)"</string>
<string name="bluetooth_connected_no_headset_no_a2dp" msgid="9195757766755553810">"कनेक्ट है (फ़ोन या मीडिया नहीं)"</string>
+ <!-- no translation found for bluetooth_connected_battery_level (7049181126136692368) -->
+ <skip />
+ <!-- no translation found for bluetooth_connected_no_headset_battery_level (5504193961248406027) -->
+ <skip />
+ <!-- no translation found for bluetooth_connected_no_a2dp_battery_level (4751724026365870779) -->
+ <skip />
+ <!-- no translation found for bluetooth_connected_no_headset_no_a2dp_battery_level (1549265779323455261) -->
+ <skip />
<string name="bluetooth_profile_a2dp" msgid="2031475486179830674">"मीडिया ऑडियो"</string>
<string name="bluetooth_profile_headset" msgid="7815495680863246034">"फ़ोन कॉल"</string>
<string name="bluetooth_profile_opp" msgid="9168139293654233697">"फ़ाइल स्थानांतरण"</string>
diff --git a/packages/SettingsLib/res/values-hr/strings.xml b/packages/SettingsLib/res/values-hr/strings.xml
index ed6f06e5..6c4f293 100644
--- a/packages/SettingsLib/res/values-hr/strings.xml
+++ b/packages/SettingsLib/res/values-hr/strings.xml
@@ -55,6 +55,14 @@
<string name="bluetooth_connected_no_a2dp" msgid="4576188601581440337">"Povezano (bez medija)"</string>
<string name="bluetooth_connected_no_map" msgid="6504436917057479986">"Povezano (bez pristupa porukama)"</string>
<string name="bluetooth_connected_no_headset_no_a2dp" msgid="9195757766755553810">"Povezano (bez telefona ili medija)"</string>
+ <!-- no translation found for bluetooth_connected_battery_level (7049181126136692368) -->
+ <skip />
+ <!-- no translation found for bluetooth_connected_no_headset_battery_level (5504193961248406027) -->
+ <skip />
+ <!-- no translation found for bluetooth_connected_no_a2dp_battery_level (4751724026365870779) -->
+ <skip />
+ <!-- no translation found for bluetooth_connected_no_headset_no_a2dp_battery_level (1549265779323455261) -->
+ <skip />
<string name="bluetooth_profile_a2dp" msgid="2031475486179830674">"Medijski zvuk"</string>
<string name="bluetooth_profile_headset" msgid="7815495680863246034">"Telefonski pozivi"</string>
<string name="bluetooth_profile_opp" msgid="9168139293654233697">"Prijenos datoteke"</string>
diff --git a/packages/SettingsLib/res/values-hu/strings.xml b/packages/SettingsLib/res/values-hu/strings.xml
index 822ff0b..479290f 100644
--- a/packages/SettingsLib/res/values-hu/strings.xml
+++ b/packages/SettingsLib/res/values-hu/strings.xml
@@ -55,6 +55,14 @@
<string name="bluetooth_connected_no_a2dp" msgid="4576188601581440337">"Csatlakoztatva (nincs hordozó)"</string>
<string name="bluetooth_connected_no_map" msgid="6504436917057479986">"Csatlakoztatva (nincs üzenet-hozzáférés)"</string>
<string name="bluetooth_connected_no_headset_no_a2dp" msgid="9195757766755553810">"Csatlakoztatva (nincs telefon vagy hordozó)"</string>
+ <!-- no translation found for bluetooth_connected_battery_level (7049181126136692368) -->
+ <skip />
+ <!-- no translation found for bluetooth_connected_no_headset_battery_level (5504193961248406027) -->
+ <skip />
+ <!-- no translation found for bluetooth_connected_no_a2dp_battery_level (4751724026365870779) -->
+ <skip />
+ <!-- no translation found for bluetooth_connected_no_headset_no_a2dp_battery_level (1549265779323455261) -->
+ <skip />
<string name="bluetooth_profile_a2dp" msgid="2031475486179830674">"Média audió"</string>
<string name="bluetooth_profile_headset" msgid="7815495680863246034">"Telefonhívások"</string>
<string name="bluetooth_profile_opp" msgid="9168139293654233697">"Fájlátvitel"</string>
diff --git a/packages/SettingsLib/res/values-hy/strings.xml b/packages/SettingsLib/res/values-hy/strings.xml
index 1b7615b..ec6c1a2 100644
--- a/packages/SettingsLib/res/values-hy/strings.xml
+++ b/packages/SettingsLib/res/values-hy/strings.xml
@@ -55,6 +55,14 @@
<string name="bluetooth_connected_no_a2dp" msgid="4576188601581440337">"Միացված է (առանց մեդիա)"</string>
<string name="bluetooth_connected_no_map" msgid="6504436917057479986">"Միացված է (հաղորդագրությանը մուտք չկա)"</string>
<string name="bluetooth_connected_no_headset_no_a2dp" msgid="9195757766755553810">"Միացված է (առանց հեռախոսի և մեդիայի)"</string>
+ <!-- no translation found for bluetooth_connected_battery_level (7049181126136692368) -->
+ <skip />
+ <!-- no translation found for bluetooth_connected_no_headset_battery_level (5504193961248406027) -->
+ <skip />
+ <!-- no translation found for bluetooth_connected_no_a2dp_battery_level (4751724026365870779) -->
+ <skip />
+ <!-- no translation found for bluetooth_connected_no_headset_no_a2dp_battery_level (1549265779323455261) -->
+ <skip />
<string name="bluetooth_profile_a2dp" msgid="2031475486179830674">"Մեդիա աուդիո"</string>
<string name="bluetooth_profile_headset" msgid="7815495680863246034">"Հեռախոսազանգեր"</string>
<string name="bluetooth_profile_opp" msgid="9168139293654233697">"Ֆայլերի փոխանցում"</string>
diff --git a/packages/SettingsLib/res/values-in/strings.xml b/packages/SettingsLib/res/values-in/strings.xml
index 6e862b4..6027821 100644
--- a/packages/SettingsLib/res/values-in/strings.xml
+++ b/packages/SettingsLib/res/values-in/strings.xml
@@ -55,6 +55,14 @@
<string name="bluetooth_connected_no_a2dp" msgid="4576188601581440337">"Terhubung (kecuali media)"</string>
<string name="bluetooth_connected_no_map" msgid="6504436917057479986">"Tersambung (tidak ada akses pesan)"</string>
<string name="bluetooth_connected_no_headset_no_a2dp" msgid="9195757766755553810">"Terhubung (bukan telepon atau media)"</string>
+ <!-- no translation found for bluetooth_connected_battery_level (7049181126136692368) -->
+ <skip />
+ <!-- no translation found for bluetooth_connected_no_headset_battery_level (5504193961248406027) -->
+ <skip />
+ <!-- no translation found for bluetooth_connected_no_a2dp_battery_level (4751724026365870779) -->
+ <skip />
+ <!-- no translation found for bluetooth_connected_no_headset_no_a2dp_battery_level (1549265779323455261) -->
+ <skip />
<string name="bluetooth_profile_a2dp" msgid="2031475486179830674">"Audio media"</string>
<string name="bluetooth_profile_headset" msgid="7815495680863246034">"Panggilan telepon"</string>
<string name="bluetooth_profile_opp" msgid="9168139293654233697">"Transfer file"</string>
@@ -352,7 +360,7 @@
<string name="disabled" msgid="9206776641295849915">"Dinonaktifkan"</string>
<string name="external_source_trusted" msgid="2707996266575928037">"Diizinkan"</string>
<string name="external_source_untrusted" msgid="2677442511837596726">"Tidak diizinkan"</string>
- <string name="install_other_apps" msgid="6986686991775883017">"Instal aplikasi yang tidak dikenal"</string>
+ <string name="install_other_apps" msgid="6986686991775883017">"Menginstal aplikasi yang tidak dikenal"</string>
<string name="home" msgid="3256884684164448244">"Layar Utama Setelan"</string>
<string-array name="battery_labels">
<item msgid="8494684293649631252">"0%"</item>
diff --git a/packages/SettingsLib/res/values-is/strings.xml b/packages/SettingsLib/res/values-is/strings.xml
index 6b55685..4db2d5e 100644
--- a/packages/SettingsLib/res/values-is/strings.xml
+++ b/packages/SettingsLib/res/values-is/strings.xml
@@ -55,6 +55,14 @@
<string name="bluetooth_connected_no_a2dp" msgid="4576188601581440337">"Tengt (ekki efnisspilun)"</string>
<string name="bluetooth_connected_no_map" msgid="6504436917057479986">"Tengt (enginn skilaboðaaðgangur)"</string>
<string name="bluetooth_connected_no_headset_no_a2dp" msgid="9195757766755553810">"Tengt (ekki sími eða efnisspilun)"</string>
+ <!-- no translation found for bluetooth_connected_battery_level (7049181126136692368) -->
+ <skip />
+ <!-- no translation found for bluetooth_connected_no_headset_battery_level (5504193961248406027) -->
+ <skip />
+ <!-- no translation found for bluetooth_connected_no_a2dp_battery_level (4751724026365870779) -->
+ <skip />
+ <!-- no translation found for bluetooth_connected_no_headset_no_a2dp_battery_level (1549265779323455261) -->
+ <skip />
<string name="bluetooth_profile_a2dp" msgid="2031475486179830674">"Hljóð efnis"</string>
<string name="bluetooth_profile_headset" msgid="7815495680863246034">"Símtöl"</string>
<string name="bluetooth_profile_opp" msgid="9168139293654233697">"Skráaflutningur"</string>
diff --git a/packages/SettingsLib/res/values-it/strings.xml b/packages/SettingsLib/res/values-it/strings.xml
index 7f2d85a..2ab2f7e 100644
--- a/packages/SettingsLib/res/values-it/strings.xml
+++ b/packages/SettingsLib/res/values-it/strings.xml
@@ -55,6 +55,14 @@
<string name="bluetooth_connected_no_a2dp" msgid="4576188601581440337">"Collegato (contenuti multimed. esclusi)"</string>
<string name="bluetooth_connected_no_map" msgid="6504436917057479986">"Connesso (nessun accesso ai messaggi)"</string>
<string name="bluetooth_connected_no_headset_no_a2dp" msgid="9195757766755553810">"Collegato (telef. o conten. mult. esclusi)"</string>
+ <!-- no translation found for bluetooth_connected_battery_level (7049181126136692368) -->
+ <skip />
+ <!-- no translation found for bluetooth_connected_no_headset_battery_level (5504193961248406027) -->
+ <skip />
+ <!-- no translation found for bluetooth_connected_no_a2dp_battery_level (4751724026365870779) -->
+ <skip />
+ <!-- no translation found for bluetooth_connected_no_headset_no_a2dp_battery_level (1549265779323455261) -->
+ <skip />
<string name="bluetooth_profile_a2dp" msgid="2031475486179830674">"Audio multimediale"</string>
<string name="bluetooth_profile_headset" msgid="7815495680863246034">"Telefonate"</string>
<string name="bluetooth_profile_opp" msgid="9168139293654233697">"Trasferimento file"</string>
diff --git a/packages/SettingsLib/res/values-iw/strings.xml b/packages/SettingsLib/res/values-iw/strings.xml
index 36117ed..5c9ef23 100644
--- a/packages/SettingsLib/res/values-iw/strings.xml
+++ b/packages/SettingsLib/res/values-iw/strings.xml
@@ -55,6 +55,14 @@
<string name="bluetooth_connected_no_a2dp" msgid="4576188601581440337">"מחובר (ללא מדיה)"</string>
<string name="bluetooth_connected_no_map" msgid="6504436917057479986">"מחובר (אין גישה להודעות)"</string>
<string name="bluetooth_connected_no_headset_no_a2dp" msgid="9195757766755553810">"מחובר (ללא טלפון או מדיה)"</string>
+ <!-- no translation found for bluetooth_connected_battery_level (7049181126136692368) -->
+ <skip />
+ <!-- no translation found for bluetooth_connected_no_headset_battery_level (5504193961248406027) -->
+ <skip />
+ <!-- no translation found for bluetooth_connected_no_a2dp_battery_level (4751724026365870779) -->
+ <skip />
+ <!-- no translation found for bluetooth_connected_no_headset_no_a2dp_battery_level (1549265779323455261) -->
+ <skip />
<string name="bluetooth_profile_a2dp" msgid="2031475486179830674">"אודיו של מדיה"</string>
<string name="bluetooth_profile_headset" msgid="7815495680863246034">"שיחות טלפון"</string>
<string name="bluetooth_profile_opp" msgid="9168139293654233697">"העברת קבצים"</string>
diff --git a/packages/SettingsLib/res/values-ja/strings.xml b/packages/SettingsLib/res/values-ja/strings.xml
index 1e82d3a..0d6334d 100644
--- a/packages/SettingsLib/res/values-ja/strings.xml
+++ b/packages/SettingsLib/res/values-ja/strings.xml
@@ -55,6 +55,14 @@
<string name="bluetooth_connected_no_a2dp" msgid="4576188601581440337">"接続済み(メディアを除く)"</string>
<string name="bluetooth_connected_no_map" msgid="6504436917057479986">"接続済み(メッセージへのアクセスなし)"</string>
<string name="bluetooth_connected_no_headset_no_a2dp" msgid="9195757766755553810">"接続済み(電話/メディアを除く)"</string>
+ <!-- no translation found for bluetooth_connected_battery_level (7049181126136692368) -->
+ <skip />
+ <!-- no translation found for bluetooth_connected_no_headset_battery_level (5504193961248406027) -->
+ <skip />
+ <!-- no translation found for bluetooth_connected_no_a2dp_battery_level (4751724026365870779) -->
+ <skip />
+ <!-- no translation found for bluetooth_connected_no_headset_no_a2dp_battery_level (1549265779323455261) -->
+ <skip />
<string name="bluetooth_profile_a2dp" msgid="2031475486179830674">"メディアの音声"</string>
<string name="bluetooth_profile_headset" msgid="7815495680863246034">"電話"</string>
<string name="bluetooth_profile_opp" msgid="9168139293654233697">"ファイル転送"</string>
@@ -110,7 +118,7 @@
<string name="unknown" msgid="1592123443519355854">"不明"</string>
<string name="running_process_item_user_label" msgid="3129887865552025943">"ユーザー: <xliff:g id="USER_NAME">%1$s</xliff:g>"</string>
<string name="launch_defaults_some" msgid="313159469856372621">"一部デフォルトを設定"</string>
- <string name="launch_defaults_none" msgid="4241129108140034876">"既定の設定なし"</string>
+ <string name="launch_defaults_none" msgid="4241129108140034876">"デフォルトの設定なし"</string>
<string name="tts_settings" msgid="8186971894801348327">"テキスト読み上げの設定"</string>
<string name="tts_settings_title" msgid="1237820681016639683">"テキスト読み上げの出力"</string>
<string name="tts_default_rate_title" msgid="6030550998379310088">"音声の速度"</string>
diff --git a/packages/SettingsLib/res/values-ka/strings.xml b/packages/SettingsLib/res/values-ka/strings.xml
index a63c7a1..c48018d 100644
--- a/packages/SettingsLib/res/values-ka/strings.xml
+++ b/packages/SettingsLib/res/values-ka/strings.xml
@@ -55,6 +55,14 @@
<string name="bluetooth_connected_no_a2dp" msgid="4576188601581440337">"მიერთებულია (მედიის გარდა)"</string>
<string name="bluetooth_connected_no_map" msgid="6504436917057479986">"დაკავშირებულია (შეტყობინებაზე წვდომა არ არის)"</string>
<string name="bluetooth_connected_no_headset_no_a2dp" msgid="9195757766755553810">"დაკავშირება (გარდა ტელეფონისა და მედიისა)"</string>
+ <!-- no translation found for bluetooth_connected_battery_level (7049181126136692368) -->
+ <skip />
+ <!-- no translation found for bluetooth_connected_no_headset_battery_level (5504193961248406027) -->
+ <skip />
+ <!-- no translation found for bluetooth_connected_no_a2dp_battery_level (4751724026365870779) -->
+ <skip />
+ <!-- no translation found for bluetooth_connected_no_headset_no_a2dp_battery_level (1549265779323455261) -->
+ <skip />
<string name="bluetooth_profile_a2dp" msgid="2031475486179830674">"მედია აუდიო"</string>
<string name="bluetooth_profile_headset" msgid="7815495680863246034">"სატელეფონო ზარები"</string>
<string name="bluetooth_profile_opp" msgid="9168139293654233697">"ფაილების გადაცემა"</string>
diff --git a/packages/SettingsLib/res/values-kk/strings.xml b/packages/SettingsLib/res/values-kk/strings.xml
index b2de421..be03821 100644
--- a/packages/SettingsLib/res/values-kk/strings.xml
+++ b/packages/SettingsLib/res/values-kk/strings.xml
@@ -55,6 +55,14 @@
<string name="bluetooth_connected_no_a2dp" msgid="4576188601581440337">"Жалғанған (медиа жоқ)"</string>
<string name="bluetooth_connected_no_map" msgid="6504436917057479986">"Жалғанған (хабарлар қол жетімсіз)"</string>
<string name="bluetooth_connected_no_headset_no_a2dp" msgid="9195757766755553810">"Жалғанған (телефон және медиа жоқ)"</string>
+ <!-- no translation found for bluetooth_connected_battery_level (7049181126136692368) -->
+ <skip />
+ <!-- no translation found for bluetooth_connected_no_headset_battery_level (5504193961248406027) -->
+ <skip />
+ <!-- no translation found for bluetooth_connected_no_a2dp_battery_level (4751724026365870779) -->
+ <skip />
+ <!-- no translation found for bluetooth_connected_no_headset_no_a2dp_battery_level (1549265779323455261) -->
+ <skip />
<string name="bluetooth_profile_a2dp" msgid="2031475486179830674">"Meдиа аудиосы"</string>
<string name="bluetooth_profile_headset" msgid="7815495680863246034">"Телефон қоңыраулары"</string>
<string name="bluetooth_profile_opp" msgid="9168139293654233697">"Файл жіберу"</string>
diff --git a/packages/SettingsLib/res/values-km/strings.xml b/packages/SettingsLib/res/values-km/strings.xml
index 8f9066f..d8fac16 100644
--- a/packages/SettingsLib/res/values-km/strings.xml
+++ b/packages/SettingsLib/res/values-km/strings.xml
@@ -55,6 +55,14 @@
<string name="bluetooth_connected_no_a2dp" msgid="4576188601581440337">"បានតភ្ជាប់ (គ្មានមេឌៀ)"</string>
<string name="bluetooth_connected_no_map" msgid="6504436917057479986">"បានភ្ជាប់ (គ្មានការចូលដំណើរការសារ)"</string>
<string name="bluetooth_connected_no_headset_no_a2dp" msgid="9195757766755553810">"បានតភ្ជាប់ (គ្មានទូរស័ព្ទ ឬមេឌៀ)"</string>
+ <!-- no translation found for bluetooth_connected_battery_level (7049181126136692368) -->
+ <skip />
+ <!-- no translation found for bluetooth_connected_no_headset_battery_level (5504193961248406027) -->
+ <skip />
+ <!-- no translation found for bluetooth_connected_no_a2dp_battery_level (4751724026365870779) -->
+ <skip />
+ <!-- no translation found for bluetooth_connected_no_headset_no_a2dp_battery_level (1549265779323455261) -->
+ <skip />
<string name="bluetooth_profile_a2dp" msgid="2031475486179830674">"សំឡេងមេឌៀ"</string>
<string name="bluetooth_profile_headset" msgid="7815495680863246034">"ការហៅទូរសព្ទ"</string>
<string name="bluetooth_profile_opp" msgid="9168139293654233697">"ផ្ទេរឯកសារ"</string>
diff --git a/packages/SettingsLib/res/values-kn/strings.xml b/packages/SettingsLib/res/values-kn/strings.xml
index 0c7ebff..3989e98 100644
--- a/packages/SettingsLib/res/values-kn/strings.xml
+++ b/packages/SettingsLib/res/values-kn/strings.xml
@@ -55,6 +55,14 @@
<string name="bluetooth_connected_no_a2dp" msgid="4576188601581440337">"ಸಂಪರ್ಕಗೊಂಡಿದೆ (ಮಾಧ್ಯಮವಿಲ್ಲ)"</string>
<string name="bluetooth_connected_no_map" msgid="6504436917057479986">"ಸಂಪರ್ಕಪಡಿಸಲಾಗಿದೆ (ಯಾವುದೇ ಸಂದೇಶ ಪ್ರವೇಶವಿಲ್ಲ)"</string>
<string name="bluetooth_connected_no_headset_no_a2dp" msgid="9195757766755553810">"ಸಂಪರ್ಕಗೊಂಡಿದೆ (ಫೋನ್ ಅಥವಾ ಮಾಧ್ಯಮವಿಲ್ಲ)"</string>
+ <!-- no translation found for bluetooth_connected_battery_level (7049181126136692368) -->
+ <skip />
+ <!-- no translation found for bluetooth_connected_no_headset_battery_level (5504193961248406027) -->
+ <skip />
+ <!-- no translation found for bluetooth_connected_no_a2dp_battery_level (4751724026365870779) -->
+ <skip />
+ <!-- no translation found for bluetooth_connected_no_headset_no_a2dp_battery_level (1549265779323455261) -->
+ <skip />
<string name="bluetooth_profile_a2dp" msgid="2031475486179830674">"ಮಾಧ್ಯಮ ಆಡಿಯೋ"</string>
<string name="bluetooth_profile_headset" msgid="7815495680863246034">"ಫೋನ್ ಕರೆಗಳು"</string>
<string name="bluetooth_profile_opp" msgid="9168139293654233697">"ಫೈಲ್ ವರ್ಗಾವಣೆ"</string>
diff --git a/packages/SettingsLib/res/values-ko/strings.xml b/packages/SettingsLib/res/values-ko/strings.xml
index eb20fdc..385172d 100644
--- a/packages/SettingsLib/res/values-ko/strings.xml
+++ b/packages/SettingsLib/res/values-ko/strings.xml
@@ -55,6 +55,14 @@
<string name="bluetooth_connected_no_a2dp" msgid="4576188601581440337">"연결됨(미디어 없음)"</string>
<string name="bluetooth_connected_no_map" msgid="6504436917057479986">"연결됨(메시지 액세스 없음)"</string>
<string name="bluetooth_connected_no_headset_no_a2dp" msgid="9195757766755553810">"연결됨(전화 또는 미디어 없음)"</string>
+ <!-- no translation found for bluetooth_connected_battery_level (7049181126136692368) -->
+ <skip />
+ <!-- no translation found for bluetooth_connected_no_headset_battery_level (5504193961248406027) -->
+ <skip />
+ <!-- no translation found for bluetooth_connected_no_a2dp_battery_level (4751724026365870779) -->
+ <skip />
+ <!-- no translation found for bluetooth_connected_no_headset_no_a2dp_battery_level (1549265779323455261) -->
+ <skip />
<string name="bluetooth_profile_a2dp" msgid="2031475486179830674">"미디어 오디오"</string>
<string name="bluetooth_profile_headset" msgid="7815495680863246034">"전화 통화"</string>
<string name="bluetooth_profile_opp" msgid="9168139293654233697">"파일 전송"</string>
diff --git a/packages/SettingsLib/res/values-ky/strings.xml b/packages/SettingsLib/res/values-ky/strings.xml
index 64bea17..a5cee81 100644
--- a/packages/SettingsLib/res/values-ky/strings.xml
+++ b/packages/SettingsLib/res/values-ky/strings.xml
@@ -55,6 +55,14 @@
<string name="bluetooth_connected_no_a2dp" msgid="4576188601581440337">"Туташып турат (медиасыз)"</string>
<string name="bluetooth_connected_no_map" msgid="6504436917057479986">"Байланышта (билдирүү алмашуу жок)"</string>
<string name="bluetooth_connected_no_headset_no_a2dp" msgid="9195757766755553810">"Туташып турат (телефониясыз же медиасыз)"</string>
+ <!-- no translation found for bluetooth_connected_battery_level (7049181126136692368) -->
+ <skip />
+ <!-- no translation found for bluetooth_connected_no_headset_battery_level (5504193961248406027) -->
+ <skip />
+ <!-- no translation found for bluetooth_connected_no_a2dp_battery_level (4751724026365870779) -->
+ <skip />
+ <!-- no translation found for bluetooth_connected_no_headset_no_a2dp_battery_level (1549265779323455261) -->
+ <skip />
<string name="bluetooth_profile_a2dp" msgid="2031475486179830674">"Аудио"</string>
<string name="bluetooth_profile_headset" msgid="7815495680863246034">"Телефон чалуулар"</string>
<string name="bluetooth_profile_opp" msgid="9168139293654233697">"Файл алмашуу"</string>
diff --git a/packages/SettingsLib/res/values-lo/strings.xml b/packages/SettingsLib/res/values-lo/strings.xml
index e02e6ff..ddacdf2 100644
--- a/packages/SettingsLib/res/values-lo/strings.xml
+++ b/packages/SettingsLib/res/values-lo/strings.xml
@@ -55,6 +55,14 @@
<string name="bluetooth_connected_no_a2dp" msgid="4576188601581440337">"ເຊື່ອມຕໍ່ແລ້ວ (ບໍ່ມີສື່)"</string>
<string name="bluetooth_connected_no_map" msgid="6504436917057479986">"ເຊື່ອມຕໍ່ (ບໍ່ມີການເຂົ້າເຖິງຂໍ້ຄວາມ)"</string>
<string name="bluetooth_connected_no_headset_no_a2dp" msgid="9195757766755553810">"ເຊື່ອມຕໍ່ແລ້ວ (ບໍ່ມີໂທລະສັບ ຫຼືສື່)"</string>
+ <!-- no translation found for bluetooth_connected_battery_level (7049181126136692368) -->
+ <skip />
+ <!-- no translation found for bluetooth_connected_no_headset_battery_level (5504193961248406027) -->
+ <skip />
+ <!-- no translation found for bluetooth_connected_no_a2dp_battery_level (4751724026365870779) -->
+ <skip />
+ <!-- no translation found for bluetooth_connected_no_headset_no_a2dp_battery_level (1549265779323455261) -->
+ <skip />
<string name="bluetooth_profile_a2dp" msgid="2031475486179830674">"ສຽງ"</string>
<string name="bluetooth_profile_headset" msgid="7815495680863246034">"ການໂທ"</string>
<string name="bluetooth_profile_opp" msgid="9168139293654233697">"ການໂອນຍ້າຍໄຟລ໌"</string>
diff --git a/packages/SettingsLib/res/values-lt/strings.xml b/packages/SettingsLib/res/values-lt/strings.xml
index ff5b79b..99d2875 100644
--- a/packages/SettingsLib/res/values-lt/strings.xml
+++ b/packages/SettingsLib/res/values-lt/strings.xml
@@ -55,6 +55,14 @@
<string name="bluetooth_connected_no_a2dp" msgid="4576188601581440337">"Prijungta (be laikmenos)"</string>
<string name="bluetooth_connected_no_map" msgid="6504436917057479986">"Prisijungta (be prieigos prie pranešimų)"</string>
<string name="bluetooth_connected_no_headset_no_a2dp" msgid="9195757766755553810">"Prijungta (be telefono ar laikmenos)"</string>
+ <!-- no translation found for bluetooth_connected_battery_level (7049181126136692368) -->
+ <skip />
+ <!-- no translation found for bluetooth_connected_no_headset_battery_level (5504193961248406027) -->
+ <skip />
+ <!-- no translation found for bluetooth_connected_no_a2dp_battery_level (4751724026365870779) -->
+ <skip />
+ <!-- no translation found for bluetooth_connected_no_headset_no_a2dp_battery_level (1549265779323455261) -->
+ <skip />
<string name="bluetooth_profile_a2dp" msgid="2031475486179830674">"Laikmenos garsas"</string>
<string name="bluetooth_profile_headset" msgid="7815495680863246034">"Telefono skambučiai"</string>
<string name="bluetooth_profile_opp" msgid="9168139293654233697">"Failo perkėlimas"</string>
diff --git a/packages/SettingsLib/res/values-lv/strings.xml b/packages/SettingsLib/res/values-lv/strings.xml
index 3784768..8ade7d4 100644
--- a/packages/SettingsLib/res/values-lv/strings.xml
+++ b/packages/SettingsLib/res/values-lv/strings.xml
@@ -55,6 +55,14 @@
<string name="bluetooth_connected_no_a2dp" msgid="4576188601581440337">"Sav. ir izveidots (nav multivides)"</string>
<string name="bluetooth_connected_no_map" msgid="6504436917057479986">"Savienots (nav piekļuves ziņojumam)"</string>
<string name="bluetooth_connected_no_headset_no_a2dp" msgid="9195757766755553810">"Sav. ir izveidots (nav tel. vai multiv.)"</string>
+ <!-- no translation found for bluetooth_connected_battery_level (7049181126136692368) -->
+ <skip />
+ <!-- no translation found for bluetooth_connected_no_headset_battery_level (5504193961248406027) -->
+ <skip />
+ <!-- no translation found for bluetooth_connected_no_a2dp_battery_level (4751724026365870779) -->
+ <skip />
+ <!-- no translation found for bluetooth_connected_no_headset_no_a2dp_battery_level (1549265779323455261) -->
+ <skip />
<string name="bluetooth_profile_a2dp" msgid="2031475486179830674">"Multivides audio"</string>
<string name="bluetooth_profile_headset" msgid="7815495680863246034">"Tālruņa zvani"</string>
<string name="bluetooth_profile_opp" msgid="9168139293654233697">"Failu pārsūtīšana"</string>
diff --git a/packages/SettingsLib/res/values-mk/strings.xml b/packages/SettingsLib/res/values-mk/strings.xml
index 694a9c8..666cc12 100644
--- a/packages/SettingsLib/res/values-mk/strings.xml
+++ b/packages/SettingsLib/res/values-mk/strings.xml
@@ -55,6 +55,14 @@
<string name="bluetooth_connected_no_a2dp" msgid="4576188601581440337">"Поврзани (без медиуми)"</string>
<string name="bluetooth_connected_no_map" msgid="6504436917057479986">"Поврзано (без порака за пристап)"</string>
<string name="bluetooth_connected_no_headset_no_a2dp" msgid="9195757766755553810">"Поврзан (без телефон или медиуми)"</string>
+ <!-- no translation found for bluetooth_connected_battery_level (7049181126136692368) -->
+ <skip />
+ <!-- no translation found for bluetooth_connected_no_headset_battery_level (5504193961248406027) -->
+ <skip />
+ <!-- no translation found for bluetooth_connected_no_a2dp_battery_level (4751724026365870779) -->
+ <skip />
+ <!-- no translation found for bluetooth_connected_no_headset_no_a2dp_battery_level (1549265779323455261) -->
+ <skip />
<string name="bluetooth_profile_a2dp" msgid="2031475486179830674">"Аудио на медиуми"</string>
<string name="bluetooth_profile_headset" msgid="7815495680863246034">"Телефонски повици"</string>
<string name="bluetooth_profile_opp" msgid="9168139293654233697">"Пренос на датотека"</string>
diff --git a/packages/SettingsLib/res/values-ml/strings.xml b/packages/SettingsLib/res/values-ml/strings.xml
index 7de21c4..f657b43 100644
--- a/packages/SettingsLib/res/values-ml/strings.xml
+++ b/packages/SettingsLib/res/values-ml/strings.xml
@@ -55,6 +55,14 @@
<string name="bluetooth_connected_no_a2dp" msgid="4576188601581440337">"കണക്റ്റുചെയ്തു (മീഡിയ ഇല്ല)"</string>
<string name="bluetooth_connected_no_map" msgid="6504436917057479986">"കണക്റ്റുചെയ്തു (സന്ദേശ ആക്സസ്സില്ല)"</string>
<string name="bluetooth_connected_no_headset_no_a2dp" msgid="9195757766755553810">"കണക്റ്റുചെയ്തു (ഫോണോ മീഡിയയോ അല്ല)"</string>
+ <!-- no translation found for bluetooth_connected_battery_level (7049181126136692368) -->
+ <skip />
+ <!-- no translation found for bluetooth_connected_no_headset_battery_level (5504193961248406027) -->
+ <skip />
+ <!-- no translation found for bluetooth_connected_no_a2dp_battery_level (4751724026365870779) -->
+ <skip />
+ <!-- no translation found for bluetooth_connected_no_headset_no_a2dp_battery_level (1549265779323455261) -->
+ <skip />
<string name="bluetooth_profile_a2dp" msgid="2031475486179830674">"മീഡിയ ഓഡിയോ"</string>
<string name="bluetooth_profile_headset" msgid="7815495680863246034">"ഫോണ് കോളുകൾ"</string>
<string name="bluetooth_profile_opp" msgid="9168139293654233697">"ഫയൽ കൈമാറൽ"</string>
diff --git a/packages/SettingsLib/res/values-mn/strings.xml b/packages/SettingsLib/res/values-mn/strings.xml
index 5a0a722..a0f3cee 100644
--- a/packages/SettingsLib/res/values-mn/strings.xml
+++ b/packages/SettingsLib/res/values-mn/strings.xml
@@ -55,6 +55,14 @@
<string name="bluetooth_connected_no_a2dp" msgid="4576188601581440337">"Холбогдсон (медиа байхгүй)"</string>
<string name="bluetooth_connected_no_map" msgid="6504436917057479986">"Холбогдсон (зурвас хандалт байхгүй)"</string>
<string name="bluetooth_connected_no_headset_no_a2dp" msgid="9195757766755553810">"Холбогдсон (утас буюу медиа байхгүй)"</string>
+ <!-- no translation found for bluetooth_connected_battery_level (7049181126136692368) -->
+ <skip />
+ <!-- no translation found for bluetooth_connected_no_headset_battery_level (5504193961248406027) -->
+ <skip />
+ <!-- no translation found for bluetooth_connected_no_a2dp_battery_level (4751724026365870779) -->
+ <skip />
+ <!-- no translation found for bluetooth_connected_no_headset_no_a2dp_battery_level (1549265779323455261) -->
+ <skip />
<string name="bluetooth_profile_a2dp" msgid="2031475486179830674">"Медиа аудио"</string>
<string name="bluetooth_profile_headset" msgid="7815495680863246034">"Утасны дуудлага"</string>
<string name="bluetooth_profile_opp" msgid="9168139293654233697">"Файл дамжуулалт"</string>
diff --git a/packages/SettingsLib/res/values-mr/strings.xml b/packages/SettingsLib/res/values-mr/strings.xml
index 8032392..0a90722 100644
--- a/packages/SettingsLib/res/values-mr/strings.xml
+++ b/packages/SettingsLib/res/values-mr/strings.xml
@@ -55,6 +55,14 @@
<string name="bluetooth_connected_no_a2dp" msgid="4576188601581440337">"कनेक्ट केले (मीडिया नाही)"</string>
<string name="bluetooth_connected_no_map" msgid="6504436917057479986">"कनेक्ट केलेले आहे (कोणत्याही संदेशामध्ये प्रवेश नाही)"</string>
<string name="bluetooth_connected_no_headset_no_a2dp" msgid="9195757766755553810">"कनेक्ट केले (फोन किंवा मीडिया नाही)"</string>
+ <!-- no translation found for bluetooth_connected_battery_level (7049181126136692368) -->
+ <skip />
+ <!-- no translation found for bluetooth_connected_no_headset_battery_level (5504193961248406027) -->
+ <skip />
+ <!-- no translation found for bluetooth_connected_no_a2dp_battery_level (4751724026365870779) -->
+ <skip />
+ <!-- no translation found for bluetooth_connected_no_headset_no_a2dp_battery_level (1549265779323455261) -->
+ <skip />
<string name="bluetooth_profile_a2dp" msgid="2031475486179830674">"मीडिया ऑडिओ"</string>
<string name="bluetooth_profile_headset" msgid="7815495680863246034">"फोन कॉल"</string>
<string name="bluetooth_profile_opp" msgid="9168139293654233697">"फाइल स्थानांतरण"</string>
diff --git a/packages/SettingsLib/res/values-ms/strings.xml b/packages/SettingsLib/res/values-ms/strings.xml
index eedc1a0..8aadf7c 100644
--- a/packages/SettingsLib/res/values-ms/strings.xml
+++ b/packages/SettingsLib/res/values-ms/strings.xml
@@ -55,6 +55,14 @@
<string name="bluetooth_connected_no_a2dp" msgid="4576188601581440337">"Disambungkan (tiada media)"</string>
<string name="bluetooth_connected_no_map" msgid="6504436917057479986">"Disambungkan (tiada akses mesej)"</string>
<string name="bluetooth_connected_no_headset_no_a2dp" msgid="9195757766755553810">"Disambungkan (tiada telefon atau media)"</string>
+ <!-- no translation found for bluetooth_connected_battery_level (7049181126136692368) -->
+ <skip />
+ <!-- no translation found for bluetooth_connected_no_headset_battery_level (5504193961248406027) -->
+ <skip />
+ <!-- no translation found for bluetooth_connected_no_a2dp_battery_level (4751724026365870779) -->
+ <skip />
+ <!-- no translation found for bluetooth_connected_no_headset_no_a2dp_battery_level (1549265779323455261) -->
+ <skip />
<string name="bluetooth_profile_a2dp" msgid="2031475486179830674">"Audio media"</string>
<string name="bluetooth_profile_headset" msgid="7815495680863246034">"Panggilan telefon"</string>
<string name="bluetooth_profile_opp" msgid="9168139293654233697">"Pemindahan fail"</string>
diff --git a/packages/SettingsLib/res/values-my/strings.xml b/packages/SettingsLib/res/values-my/strings.xml
index 4e5873e..85f89a1 100644
--- a/packages/SettingsLib/res/values-my/strings.xml
+++ b/packages/SettingsLib/res/values-my/strings.xml
@@ -55,6 +55,14 @@
<string name="bluetooth_connected_no_a2dp" msgid="4576188601581440337">"ချိတ်ဆက်ထားပြီး (မီဒီယာမရှိ)"</string>
<string name="bluetooth_connected_no_map" msgid="6504436917057479986">"ချိတ်ဆက်မိသည် (သတင်းရယူမှုမရှိ)"</string>
<string name="bluetooth_connected_no_headset_no_a2dp" msgid="9195757766755553810">"ချိတ်ဆက်ပြီး (ဖုန်း သို့ မီဒီယာမဟုတ်ပါ)"</string>
+ <!-- no translation found for bluetooth_connected_battery_level (7049181126136692368) -->
+ <skip />
+ <!-- no translation found for bluetooth_connected_no_headset_battery_level (5504193961248406027) -->
+ <skip />
+ <!-- no translation found for bluetooth_connected_no_a2dp_battery_level (4751724026365870779) -->
+ <skip />
+ <!-- no translation found for bluetooth_connected_no_headset_no_a2dp_battery_level (1549265779323455261) -->
+ <skip />
<string name="bluetooth_profile_a2dp" msgid="2031475486179830674">"မီဒီယာ အသံ"</string>
<string name="bluetooth_profile_headset" msgid="7815495680863246034">"ဖုန်းခေါ်ဆိုမှုများ"</string>
<string name="bluetooth_profile_opp" msgid="9168139293654233697">"ဖိုင်လွဲပြောင်းခြင်း"</string>
diff --git a/packages/SettingsLib/res/values-nb/strings.xml b/packages/SettingsLib/res/values-nb/strings.xml
index 81a1eb5..7cb6816 100644
--- a/packages/SettingsLib/res/values-nb/strings.xml
+++ b/packages/SettingsLib/res/values-nb/strings.xml
@@ -55,6 +55,14 @@
<string name="bluetooth_connected_no_a2dp" msgid="4576188601581440337">"Tilkoblet (ingen medier)"</string>
<string name="bluetooth_connected_no_map" msgid="6504436917057479986">"Tilkoblet (ingen meldingstilgang)"</string>
<string name="bluetooth_connected_no_headset_no_a2dp" msgid="9195757766755553810">"Tilkoblet (ingen telefon eller media)"</string>
+ <!-- no translation found for bluetooth_connected_battery_level (7049181126136692368) -->
+ <skip />
+ <!-- no translation found for bluetooth_connected_no_headset_battery_level (5504193961248406027) -->
+ <skip />
+ <!-- no translation found for bluetooth_connected_no_a2dp_battery_level (4751724026365870779) -->
+ <skip />
+ <!-- no translation found for bluetooth_connected_no_headset_no_a2dp_battery_level (1549265779323455261) -->
+ <skip />
<string name="bluetooth_profile_a2dp" msgid="2031475486179830674">"Medielyd"</string>
<string name="bluetooth_profile_headset" msgid="7815495680863246034">"Telefonsamtaler"</string>
<string name="bluetooth_profile_opp" msgid="9168139293654233697">"Filoverføring"</string>
diff --git a/packages/SettingsLib/res/values-ne/strings.xml b/packages/SettingsLib/res/values-ne/strings.xml
index dbb1977..5abcf19 100644
--- a/packages/SettingsLib/res/values-ne/strings.xml
+++ b/packages/SettingsLib/res/values-ne/strings.xml
@@ -55,6 +55,14 @@
<string name="bluetooth_connected_no_a2dp" msgid="4576188601581440337">"जडित (कुनै पनि मिडिया छैन)"</string>
<string name="bluetooth_connected_no_map" msgid="6504436917057479986">"जडित छ (सन्देशमा पहुँच छैन)"</string>
<string name="bluetooth_connected_no_headset_no_a2dp" msgid="9195757766755553810">"जडित (फोन वा मिडिया छैन)"</string>
+ <!-- no translation found for bluetooth_connected_battery_level (7049181126136692368) -->
+ <skip />
+ <!-- no translation found for bluetooth_connected_no_headset_battery_level (5504193961248406027) -->
+ <skip />
+ <!-- no translation found for bluetooth_connected_no_a2dp_battery_level (4751724026365870779) -->
+ <skip />
+ <!-- no translation found for bluetooth_connected_no_headset_no_a2dp_battery_level (1549265779323455261) -->
+ <skip />
<string name="bluetooth_profile_a2dp" msgid="2031475486179830674">"मिडिया अडियो"</string>
<string name="bluetooth_profile_headset" msgid="7815495680863246034">"फोन कलहरू"</string>
<string name="bluetooth_profile_opp" msgid="9168139293654233697">"फाइल स्थानान्तरण"</string>
diff --git a/packages/SettingsLib/res/values-nl/strings.xml b/packages/SettingsLib/res/values-nl/strings.xml
index b94f2c7..2649a4f 100644
--- a/packages/SettingsLib/res/values-nl/strings.xml
+++ b/packages/SettingsLib/res/values-nl/strings.xml
@@ -55,6 +55,14 @@
<string name="bluetooth_connected_no_a2dp" msgid="4576188601581440337">"Gekoppeld (geen media)"</string>
<string name="bluetooth_connected_no_map" msgid="6504436917057479986">"Verbonden (geen toegang tot berichten)"</string>
<string name="bluetooth_connected_no_headset_no_a2dp" msgid="9195757766755553810">"Gekoppeld (geen telefoon of media)"</string>
+ <!-- no translation found for bluetooth_connected_battery_level (7049181126136692368) -->
+ <skip />
+ <!-- no translation found for bluetooth_connected_no_headset_battery_level (5504193961248406027) -->
+ <skip />
+ <!-- no translation found for bluetooth_connected_no_a2dp_battery_level (4751724026365870779) -->
+ <skip />
+ <!-- no translation found for bluetooth_connected_no_headset_no_a2dp_battery_level (1549265779323455261) -->
+ <skip />
<string name="bluetooth_profile_a2dp" msgid="2031475486179830674">"Media-audio"</string>
<string name="bluetooth_profile_headset" msgid="7815495680863246034">"Telefoongesprekken"</string>
<string name="bluetooth_profile_opp" msgid="9168139293654233697">"Bestandsoverdracht"</string>
diff --git a/packages/SettingsLib/res/values-pa/strings.xml b/packages/SettingsLib/res/values-pa/strings.xml
index fa5c3b7..77ba3f8 100644
--- a/packages/SettingsLib/res/values-pa/strings.xml
+++ b/packages/SettingsLib/res/values-pa/strings.xml
@@ -55,6 +55,14 @@
<string name="bluetooth_connected_no_a2dp" msgid="4576188601581440337">"ਕਨੈਕਟ ਕੀਤਾ (ਕੋਈ ਮੀਡੀਆ ਨਹੀਂ)"</string>
<string name="bluetooth_connected_no_map" msgid="6504436917057479986">"ਕਨੈਕਟ ਕੀਤਾ (ਕੋਈ ਸੁਨੇਹਾ ਪਹੁੰਚ ਨਹੀਂ)"</string>
<string name="bluetooth_connected_no_headset_no_a2dp" msgid="9195757766755553810">"ਕਨੈਕਟ ਕੀਤਾ (ਕੋਈ ਫੋਨ ਜਾਂ ਮੀਡੀਆ ਨਹੀਂ)"</string>
+ <!-- no translation found for bluetooth_connected_battery_level (7049181126136692368) -->
+ <skip />
+ <!-- no translation found for bluetooth_connected_no_headset_battery_level (5504193961248406027) -->
+ <skip />
+ <!-- no translation found for bluetooth_connected_no_a2dp_battery_level (4751724026365870779) -->
+ <skip />
+ <!-- no translation found for bluetooth_connected_no_headset_no_a2dp_battery_level (1549265779323455261) -->
+ <skip />
<string name="bluetooth_profile_a2dp" msgid="2031475486179830674">"ਮੀਡੀਆ ਔਡੀਓ"</string>
<string name="bluetooth_profile_headset" msgid="7815495680863246034">"ਫ਼ੋਨ ਕਾਲਾਂ"</string>
<string name="bluetooth_profile_opp" msgid="9168139293654233697">"ਫਾਈਲ ਟ੍ਰਾਂਸਫਰ"</string>
diff --git a/packages/SettingsLib/res/values-pl/strings.xml b/packages/SettingsLib/res/values-pl/strings.xml
index ee1ba4d..b216ff1 100644
--- a/packages/SettingsLib/res/values-pl/strings.xml
+++ b/packages/SettingsLib/res/values-pl/strings.xml
@@ -55,6 +55,14 @@
<string name="bluetooth_connected_no_a2dp" msgid="4576188601581440337">"Połączono (bez multimediów)"</string>
<string name="bluetooth_connected_no_map" msgid="6504436917057479986">"Połączono (brak dostępu do wiadomości)"</string>
<string name="bluetooth_connected_no_headset_no_a2dp" msgid="9195757766755553810">"Połączono (bez telefonu ani multimediów)"</string>
+ <!-- no translation found for bluetooth_connected_battery_level (7049181126136692368) -->
+ <skip />
+ <!-- no translation found for bluetooth_connected_no_headset_battery_level (5504193961248406027) -->
+ <skip />
+ <!-- no translation found for bluetooth_connected_no_a2dp_battery_level (4751724026365870779) -->
+ <skip />
+ <!-- no translation found for bluetooth_connected_no_headset_no_a2dp_battery_level (1549265779323455261) -->
+ <skip />
<string name="bluetooth_profile_a2dp" msgid="2031475486179830674">"Dźwięk multimediów"</string>
<string name="bluetooth_profile_headset" msgid="7815495680863246034">"Połączenia telefoniczne"</string>
<string name="bluetooth_profile_opp" msgid="9168139293654233697">"Przesyłanie pliku"</string>
diff --git a/packages/SettingsLib/res/values-pt-rBR/strings.xml b/packages/SettingsLib/res/values-pt-rBR/strings.xml
index 675a6d09..d98570f 100644
--- a/packages/SettingsLib/res/values-pt-rBR/strings.xml
+++ b/packages/SettingsLib/res/values-pt-rBR/strings.xml
@@ -55,6 +55,14 @@
<string name="bluetooth_connected_no_a2dp" msgid="4576188601581440337">"Conectado (sem mídia)"</string>
<string name="bluetooth_connected_no_map" msgid="6504436917057479986">"Conectado (sem acesso a mensagens)"</string>
<string name="bluetooth_connected_no_headset_no_a2dp" msgid="9195757766755553810">"Conectado (sem telefone ou mídia)"</string>
+ <!-- no translation found for bluetooth_connected_battery_level (7049181126136692368) -->
+ <skip />
+ <!-- no translation found for bluetooth_connected_no_headset_battery_level (5504193961248406027) -->
+ <skip />
+ <!-- no translation found for bluetooth_connected_no_a2dp_battery_level (4751724026365870779) -->
+ <skip />
+ <!-- no translation found for bluetooth_connected_no_headset_no_a2dp_battery_level (1549265779323455261) -->
+ <skip />
<string name="bluetooth_profile_a2dp" msgid="2031475486179830674">"Áudio da mídia"</string>
<string name="bluetooth_profile_headset" msgid="7815495680863246034">"Chamadas telefônicas"</string>
<string name="bluetooth_profile_opp" msgid="9168139293654233697">"Transferência de arquivo"</string>
diff --git a/packages/SettingsLib/res/values-pt-rPT/strings.xml b/packages/SettingsLib/res/values-pt-rPT/strings.xml
index 736579f..dc1aeac 100644
--- a/packages/SettingsLib/res/values-pt-rPT/strings.xml
+++ b/packages/SettingsLib/res/values-pt-rPT/strings.xml
@@ -55,6 +55,14 @@
<string name="bluetooth_connected_no_a2dp" msgid="4576188601581440337">"Ligado (sem multimédia)"</string>
<string name="bluetooth_connected_no_map" msgid="6504436917057479986">"Ligado (sem acesso a mensagens)"</string>
<string name="bluetooth_connected_no_headset_no_a2dp" msgid="9195757766755553810">"Ligado (sem telefone ou multimédia)"</string>
+ <!-- no translation found for bluetooth_connected_battery_level (7049181126136692368) -->
+ <skip />
+ <!-- no translation found for bluetooth_connected_no_headset_battery_level (5504193961248406027) -->
+ <skip />
+ <!-- no translation found for bluetooth_connected_no_a2dp_battery_level (4751724026365870779) -->
+ <skip />
+ <!-- no translation found for bluetooth_connected_no_headset_no_a2dp_battery_level (1549265779323455261) -->
+ <skip />
<string name="bluetooth_profile_a2dp" msgid="2031475486179830674">"Áudio de multimédia"</string>
<string name="bluetooth_profile_headset" msgid="7815495680863246034">"Chamadas telefónicas"</string>
<string name="bluetooth_profile_opp" msgid="9168139293654233697">"Transferência do ficheiro"</string>
diff --git a/packages/SettingsLib/res/values-pt/strings.xml b/packages/SettingsLib/res/values-pt/strings.xml
index 675a6d09..d98570f 100644
--- a/packages/SettingsLib/res/values-pt/strings.xml
+++ b/packages/SettingsLib/res/values-pt/strings.xml
@@ -55,6 +55,14 @@
<string name="bluetooth_connected_no_a2dp" msgid="4576188601581440337">"Conectado (sem mídia)"</string>
<string name="bluetooth_connected_no_map" msgid="6504436917057479986">"Conectado (sem acesso a mensagens)"</string>
<string name="bluetooth_connected_no_headset_no_a2dp" msgid="9195757766755553810">"Conectado (sem telefone ou mídia)"</string>
+ <!-- no translation found for bluetooth_connected_battery_level (7049181126136692368) -->
+ <skip />
+ <!-- no translation found for bluetooth_connected_no_headset_battery_level (5504193961248406027) -->
+ <skip />
+ <!-- no translation found for bluetooth_connected_no_a2dp_battery_level (4751724026365870779) -->
+ <skip />
+ <!-- no translation found for bluetooth_connected_no_headset_no_a2dp_battery_level (1549265779323455261) -->
+ <skip />
<string name="bluetooth_profile_a2dp" msgid="2031475486179830674">"Áudio da mídia"</string>
<string name="bluetooth_profile_headset" msgid="7815495680863246034">"Chamadas telefônicas"</string>
<string name="bluetooth_profile_opp" msgid="9168139293654233697">"Transferência de arquivo"</string>
diff --git a/packages/SettingsLib/res/values-ro/strings.xml b/packages/SettingsLib/res/values-ro/strings.xml
index f14aed0..23bc4f7 100644
--- a/packages/SettingsLib/res/values-ro/strings.xml
+++ b/packages/SettingsLib/res/values-ro/strings.xml
@@ -55,6 +55,14 @@
<string name="bluetooth_connected_no_a2dp" msgid="4576188601581440337">"Conectat (fără conținut media)"</string>
<string name="bluetooth_connected_no_map" msgid="6504436917057479986">"Conectat (fără acces la mesaje)"</string>
<string name="bluetooth_connected_no_headset_no_a2dp" msgid="9195757766755553810">"Conectat (fără telefon sau conț. media)"</string>
+ <!-- no translation found for bluetooth_connected_battery_level (7049181126136692368) -->
+ <skip />
+ <!-- no translation found for bluetooth_connected_no_headset_battery_level (5504193961248406027) -->
+ <skip />
+ <!-- no translation found for bluetooth_connected_no_a2dp_battery_level (4751724026365870779) -->
+ <skip />
+ <!-- no translation found for bluetooth_connected_no_headset_no_a2dp_battery_level (1549265779323455261) -->
+ <skip />
<string name="bluetooth_profile_a2dp" msgid="2031475486179830674">"Conținut media audio"</string>
<string name="bluetooth_profile_headset" msgid="7815495680863246034">"Apeluri telefonice"</string>
<string name="bluetooth_profile_opp" msgid="9168139293654233697">"Transfer de fișiere"</string>
diff --git a/packages/SettingsLib/res/values-ru/strings.xml b/packages/SettingsLib/res/values-ru/strings.xml
index ff6c838..e5fe5f7 100644
--- a/packages/SettingsLib/res/values-ru/strings.xml
+++ b/packages/SettingsLib/res/values-ru/strings.xml
@@ -55,6 +55,14 @@
<string name="bluetooth_connected_no_a2dp" msgid="4576188601581440337">"Подключено (кроме A2DP)"</string>
<string name="bluetooth_connected_no_map" msgid="6504436917057479986">"Подключено (нет доступа к сообщениям)"</string>
<string name="bluetooth_connected_no_headset_no_a2dp" msgid="9195757766755553810">"Подключено (кроме HSP/HFP/A2DP)"</string>
+ <!-- no translation found for bluetooth_connected_battery_level (7049181126136692368) -->
+ <skip />
+ <!-- no translation found for bluetooth_connected_no_headset_battery_level (5504193961248406027) -->
+ <skip />
+ <!-- no translation found for bluetooth_connected_no_a2dp_battery_level (4751724026365870779) -->
+ <skip />
+ <!-- no translation found for bluetooth_connected_no_headset_no_a2dp_battery_level (1549265779323455261) -->
+ <skip />
<string name="bluetooth_profile_a2dp" msgid="2031475486179830674">"Профиль A2DP"</string>
<string name="bluetooth_profile_headset" msgid="7815495680863246034">"Звонки"</string>
<string name="bluetooth_profile_opp" msgid="9168139293654233697">"Профиль OPP"</string>
@@ -213,7 +221,7 @@
<string name="allow_mock_location_summary" msgid="317615105156345626">"Разрешить использование фиктивных местоположений"</string>
<string name="debug_view_attributes" msgid="6485448367803310384">"Включить проверку атрибутов"</string>
<string name="mobile_data_always_on_summary" msgid="8149773901431697910">"Не отключать передачу данных по мобильной сети даже при активном Wi-Fi-подключении (для быстрого переключения между сетями)."</string>
- <string name="adb_warning_title" msgid="6234463310896563253">"Разрешить отладку USB?"</string>
+ <string name="adb_warning_title" msgid="6234463310896563253">"Разрешить отладку по USB?"</string>
<string name="adb_warning_message" msgid="7316799925425402244">"Отладка по USB – это режим, который позволяет использовать ваше устройство как внешний накопитель: перемещать файлы (с компьютера и на компьютер), напрямую устанавливать приложения, а также просматривать системные журналы."</string>
<string name="adb_keys_warning_message" msgid="5659849457135841625">"Запретить доступ к USB-отладке для всех компьютеров, которым он был разрешен?"</string>
<string name="dev_settings_warning_title" msgid="7244607768088540165">"Изменение настроек"</string>
diff --git a/packages/SettingsLib/res/values-si/strings.xml b/packages/SettingsLib/res/values-si/strings.xml
index 5486aa601..9fc96d5 100644
--- a/packages/SettingsLib/res/values-si/strings.xml
+++ b/packages/SettingsLib/res/values-si/strings.xml
@@ -55,6 +55,14 @@
<string name="bluetooth_connected_no_a2dp" msgid="4576188601581440337">"සම්බන්ධිතයි (මාධ්යයක් නොමැත)"</string>
<string name="bluetooth_connected_no_map" msgid="6504436917057479986">"සම්බන්ධිතයි (පණිවිඩ ප්රවේශ නොමැත)"</string>
<string name="bluetooth_connected_no_headset_no_a2dp" msgid="9195757766755553810">"සම්බන්ධිතයි (දුරකතනයක් හෝ මාධ්යයක් නැත)"</string>
+ <!-- no translation found for bluetooth_connected_battery_level (7049181126136692368) -->
+ <skip />
+ <!-- no translation found for bluetooth_connected_no_headset_battery_level (5504193961248406027) -->
+ <skip />
+ <!-- no translation found for bluetooth_connected_no_a2dp_battery_level (4751724026365870779) -->
+ <skip />
+ <!-- no translation found for bluetooth_connected_no_headset_no_a2dp_battery_level (1549265779323455261) -->
+ <skip />
<string name="bluetooth_profile_a2dp" msgid="2031475486179830674">"මාධ්ය ශ්රව්ය"</string>
<string name="bluetooth_profile_headset" msgid="7815495680863246034">"දුරකථන ඇමතුම්"</string>
<string name="bluetooth_profile_opp" msgid="9168139293654233697">"ගොනු හුවමාරුව"</string>
diff --git a/packages/SettingsLib/res/values-sk/strings.xml b/packages/SettingsLib/res/values-sk/strings.xml
index db3c5c37..fba2edc 100644
--- a/packages/SettingsLib/res/values-sk/strings.xml
+++ b/packages/SettingsLib/res/values-sk/strings.xml
@@ -55,6 +55,14 @@
<string name="bluetooth_connected_no_a2dp" msgid="4576188601581440337">"Pripojené (bez média)"</string>
<string name="bluetooth_connected_no_map" msgid="6504436917057479986">"Pripojené (bez prístupu ku správam)"</string>
<string name="bluetooth_connected_no_headset_no_a2dp" msgid="9195757766755553810">"Pripojené (bez telefónu alebo média)"</string>
+ <!-- no translation found for bluetooth_connected_battery_level (7049181126136692368) -->
+ <skip />
+ <!-- no translation found for bluetooth_connected_no_headset_battery_level (5504193961248406027) -->
+ <skip />
+ <!-- no translation found for bluetooth_connected_no_a2dp_battery_level (4751724026365870779) -->
+ <skip />
+ <!-- no translation found for bluetooth_connected_no_headset_no_a2dp_battery_level (1549265779323455261) -->
+ <skip />
<string name="bluetooth_profile_a2dp" msgid="2031475486179830674">"Zvuk medií"</string>
<string name="bluetooth_profile_headset" msgid="7815495680863246034">"Telefonické hovory"</string>
<string name="bluetooth_profile_opp" msgid="9168139293654233697">"Prenos súborov"</string>
@@ -65,8 +73,8 @@
<string name="bluetooth_profile_pan_nap" msgid="8429049285027482959">"Zdieľanie pripojenia na Internet"</string>
<string name="bluetooth_profile_map" msgid="1019763341565580450">"Textové správy"</string>
<string name="bluetooth_profile_sap" msgid="5764222021851283125">"Prístup k SIM karte"</string>
- <string name="bluetooth_profile_a2dp_high_quality" msgid="5444517801472820055">"Zvuk v HD: <xliff:g id="CODEC_NAME">%1$s</xliff:g>"</string>
- <string name="bluetooth_profile_a2dp_high_quality_unknown_codec" msgid="8510588052415438887">"Zvuk v HD"</string>
+ <string name="bluetooth_profile_a2dp_high_quality" msgid="5444517801472820055">"HD zvuk: <xliff:g id="CODEC_NAME">%1$s</xliff:g>"</string>
+ <string name="bluetooth_profile_a2dp_high_quality_unknown_codec" msgid="8510588052415438887">"HD zvuk"</string>
<string name="bluetooth_a2dp_profile_summary_connected" msgid="963376081347721598">"Pripojené ku zvukovému médiu"</string>
<string name="bluetooth_headset_profile_summary_connected" msgid="7661070206715520671">"Pripojené ku zvuku telefónu"</string>
<string name="bluetooth_opp_profile_summary_connected" msgid="2611913495968309066">"Pripojené na server pre prenos údajov"</string>
diff --git a/packages/SettingsLib/res/values-sl/strings.xml b/packages/SettingsLib/res/values-sl/strings.xml
index 9c20947..a206c30 100644
--- a/packages/SettingsLib/res/values-sl/strings.xml
+++ b/packages/SettingsLib/res/values-sl/strings.xml
@@ -55,6 +55,14 @@
<string name="bluetooth_connected_no_a2dp" msgid="4576188601581440337">"Povezava vzpostavljena (brez predstavnosti)"</string>
<string name="bluetooth_connected_no_map" msgid="6504436917057479986">"Povezava vzp. (ni dostopa do sporočil)"</string>
<string name="bluetooth_connected_no_headset_no_a2dp" msgid="9195757766755553810">"Povezava vzpostavljena (brez telefona ali predstavnosti)"</string>
+ <!-- no translation found for bluetooth_connected_battery_level (7049181126136692368) -->
+ <skip />
+ <!-- no translation found for bluetooth_connected_no_headset_battery_level (5504193961248406027) -->
+ <skip />
+ <!-- no translation found for bluetooth_connected_no_a2dp_battery_level (4751724026365870779) -->
+ <skip />
+ <!-- no translation found for bluetooth_connected_no_headset_no_a2dp_battery_level (1549265779323455261) -->
+ <skip />
<string name="bluetooth_profile_a2dp" msgid="2031475486179830674">"Zvok predstavnosti"</string>
<string name="bluetooth_profile_headset" msgid="7815495680863246034">"Telefonski klici"</string>
<string name="bluetooth_profile_opp" msgid="9168139293654233697">"Prenos datoteke"</string>
diff --git a/packages/SettingsLib/res/values-sq/strings.xml b/packages/SettingsLib/res/values-sq/strings.xml
index 9dddf73..c3ad1f2 100644
--- a/packages/SettingsLib/res/values-sq/strings.xml
+++ b/packages/SettingsLib/res/values-sq/strings.xml
@@ -55,6 +55,14 @@
<string name="bluetooth_connected_no_a2dp" msgid="4576188601581440337">"U lidh (nuk ka media)"</string>
<string name="bluetooth_connected_no_map" msgid="6504436917057479986">"U lidh (pa qasje te mesazhet)"</string>
<string name="bluetooth_connected_no_headset_no_a2dp" msgid="9195757766755553810">"I lidhur (pa telefon apo media)"</string>
+ <!-- no translation found for bluetooth_connected_battery_level (7049181126136692368) -->
+ <skip />
+ <!-- no translation found for bluetooth_connected_no_headset_battery_level (5504193961248406027) -->
+ <skip />
+ <!-- no translation found for bluetooth_connected_no_a2dp_battery_level (4751724026365870779) -->
+ <skip />
+ <!-- no translation found for bluetooth_connected_no_headset_no_a2dp_battery_level (1549265779323455261) -->
+ <skip />
<string name="bluetooth_profile_a2dp" msgid="2031475486179830674">"Audioja e klipit \"media\""</string>
<string name="bluetooth_profile_headset" msgid="7815495680863246034">"Telefonatat"</string>
<string name="bluetooth_profile_opp" msgid="9168139293654233697">"Transferimi i skedarëve"</string>
diff --git a/packages/SettingsLib/res/values-sr/strings.xml b/packages/SettingsLib/res/values-sr/strings.xml
index 1cda307..aa8387b 100644
--- a/packages/SettingsLib/res/values-sr/strings.xml
+++ b/packages/SettingsLib/res/values-sr/strings.xml
@@ -55,6 +55,14 @@
<string name="bluetooth_connected_no_a2dp" msgid="4576188601581440337">"Повезано (без медија)"</string>
<string name="bluetooth_connected_no_map" msgid="6504436917057479986">"Повезано је (нема приступа порукама)"</string>
<string name="bluetooth_connected_no_headset_no_a2dp" msgid="9195757766755553810">"Повезано (без телефона или медија)"</string>
+ <!-- no translation found for bluetooth_connected_battery_level (7049181126136692368) -->
+ <skip />
+ <!-- no translation found for bluetooth_connected_no_headset_battery_level (5504193961248406027) -->
+ <skip />
+ <!-- no translation found for bluetooth_connected_no_a2dp_battery_level (4751724026365870779) -->
+ <skip />
+ <!-- no translation found for bluetooth_connected_no_headset_no_a2dp_battery_level (1549265779323455261) -->
+ <skip />
<string name="bluetooth_profile_a2dp" msgid="2031475486179830674">"Звук медија"</string>
<string name="bluetooth_profile_headset" msgid="7815495680863246034">"Телефонски позиви"</string>
<string name="bluetooth_profile_opp" msgid="9168139293654233697">"Пренос датотеке"</string>
@@ -352,7 +360,7 @@
<string name="disabled" msgid="9206776641295849915">"Онемогућено"</string>
<string name="external_source_trusted" msgid="2707996266575928037">"Дозвољено"</string>
<string name="external_source_untrusted" msgid="2677442511837596726">"Није дозвољено"</string>
- <string name="install_other_apps" msgid="6986686991775883017">"Инсталирајте непозн. апл."</string>
+ <string name="install_other_apps" msgid="6986686991775883017">"Инсталирање непознатих апликација"</string>
<string name="home" msgid="3256884684164448244">"Почетна за Подешавања"</string>
<string-array name="battery_labels">
<item msgid="8494684293649631252">"0%"</item>
diff --git a/packages/SettingsLib/res/values-sv/strings.xml b/packages/SettingsLib/res/values-sv/strings.xml
index 260554f..deaa6ae 100644
--- a/packages/SettingsLib/res/values-sv/strings.xml
+++ b/packages/SettingsLib/res/values-sv/strings.xml
@@ -55,6 +55,14 @@
<string name="bluetooth_connected_no_a2dp" msgid="4576188601581440337">"Ansluten (inga media)"</string>
<string name="bluetooth_connected_no_map" msgid="6504436917057479986">"Ansluten (ingen meddelandeåtkomst)"</string>
<string name="bluetooth_connected_no_headset_no_a2dp" msgid="9195757766755553810">"Ansluten (ingen telefon och inga media)"</string>
+ <!-- no translation found for bluetooth_connected_battery_level (7049181126136692368) -->
+ <skip />
+ <!-- no translation found for bluetooth_connected_no_headset_battery_level (5504193961248406027) -->
+ <skip />
+ <!-- no translation found for bluetooth_connected_no_a2dp_battery_level (4751724026365870779) -->
+ <skip />
+ <!-- no translation found for bluetooth_connected_no_headset_no_a2dp_battery_level (1549265779323455261) -->
+ <skip />
<string name="bluetooth_profile_a2dp" msgid="2031475486179830674">"Medialjud"</string>
<string name="bluetooth_profile_headset" msgid="7815495680863246034">"Telefonsamtal"</string>
<string name="bluetooth_profile_opp" msgid="9168139293654233697">"Filöverföring"</string>
diff --git a/packages/SettingsLib/res/values-sw/strings.xml b/packages/SettingsLib/res/values-sw/strings.xml
index 04f80a9..3582f50 100644
--- a/packages/SettingsLib/res/values-sw/strings.xml
+++ b/packages/SettingsLib/res/values-sw/strings.xml
@@ -55,6 +55,14 @@
<string name="bluetooth_connected_no_a2dp" msgid="4576188601581440337">"Imeunganishwa(hakuna vyombo vya habari)"</string>
<string name="bluetooth_connected_no_map" msgid="6504436917057479986">"Imeunganishwa (hakuna ufikiaji kwa ujumbe)"</string>
<string name="bluetooth_connected_no_headset_no_a2dp" msgid="9195757766755553810">"Imeunganishwa(hakuna simu au vyombo vya habari)"</string>
+ <!-- no translation found for bluetooth_connected_battery_level (7049181126136692368) -->
+ <skip />
+ <!-- no translation found for bluetooth_connected_no_headset_battery_level (5504193961248406027) -->
+ <skip />
+ <!-- no translation found for bluetooth_connected_no_a2dp_battery_level (4751724026365870779) -->
+ <skip />
+ <!-- no translation found for bluetooth_connected_no_headset_no_a2dp_battery_level (1549265779323455261) -->
+ <skip />
<string name="bluetooth_profile_a2dp" msgid="2031475486179830674">"Media ya sauti"</string>
<string name="bluetooth_profile_headset" msgid="7815495680863246034">"Simu"</string>
<string name="bluetooth_profile_opp" msgid="9168139293654233697">"Uhamishaji wa faili"</string>
diff --git a/packages/SettingsLib/res/values-ta/strings.xml b/packages/SettingsLib/res/values-ta/strings.xml
index 74f88d2..2eca4d7 100644
--- a/packages/SettingsLib/res/values-ta/strings.xml
+++ b/packages/SettingsLib/res/values-ta/strings.xml
@@ -55,6 +55,14 @@
<string name="bluetooth_connected_no_a2dp" msgid="4576188601581440337">"இணைக்கப்பட்டது (மீடியா இல்லை)"</string>
<string name="bluetooth_connected_no_map" msgid="6504436917057479986">"இணைக்கப்பட்டது (செய்திக்கான அணுகல் இல்லை)"</string>
<string name="bluetooth_connected_no_headset_no_a2dp" msgid="9195757766755553810">"இணைக்கப்பட்டது (மொபைல் அல்லது மீடியாவுடன் அல்ல)"</string>
+ <!-- no translation found for bluetooth_connected_battery_level (7049181126136692368) -->
+ <skip />
+ <!-- no translation found for bluetooth_connected_no_headset_battery_level (5504193961248406027) -->
+ <skip />
+ <!-- no translation found for bluetooth_connected_no_a2dp_battery_level (4751724026365870779) -->
+ <skip />
+ <!-- no translation found for bluetooth_connected_no_headset_no_a2dp_battery_level (1549265779323455261) -->
+ <skip />
<string name="bluetooth_profile_a2dp" msgid="2031475486179830674">"மீடியா ஆடியோ"</string>
<string name="bluetooth_profile_headset" msgid="7815495680863246034">"ஃபோன் அழைப்புகள்"</string>
<string name="bluetooth_profile_opp" msgid="9168139293654233697">"கோப்பு இடமாற்றம்"</string>
diff --git a/packages/SettingsLib/res/values-te/strings.xml b/packages/SettingsLib/res/values-te/strings.xml
index 6f432d0..b7936fc 100644
--- a/packages/SettingsLib/res/values-te/strings.xml
+++ b/packages/SettingsLib/res/values-te/strings.xml
@@ -55,6 +55,14 @@
<string name="bluetooth_connected_no_a2dp" msgid="4576188601581440337">"కనెక్ట్ చేయబడింది (మీడియా కాదు)"</string>
<string name="bluetooth_connected_no_map" msgid="6504436917057479986">"కనెక్ట్ చేయబడింది (సందేశ ప్రాప్యత లేదు)"</string>
<string name="bluetooth_connected_no_headset_no_a2dp" msgid="9195757766755553810">"కనెక్ట్ చేయబడింది (ఫోన్ లేదా మీడియా కాకుండా)"</string>
+ <!-- no translation found for bluetooth_connected_battery_level (7049181126136692368) -->
+ <skip />
+ <!-- no translation found for bluetooth_connected_no_headset_battery_level (5504193961248406027) -->
+ <skip />
+ <!-- no translation found for bluetooth_connected_no_a2dp_battery_level (4751724026365870779) -->
+ <skip />
+ <!-- no translation found for bluetooth_connected_no_headset_no_a2dp_battery_level (1549265779323455261) -->
+ <skip />
<string name="bluetooth_profile_a2dp" msgid="2031475486179830674">"మీడియా ఆడియో"</string>
<string name="bluetooth_profile_headset" msgid="7815495680863246034">"ఫోన్ కాల్లు"</string>
<string name="bluetooth_profile_opp" msgid="9168139293654233697">"ఫైల్ బదిలీ"</string>
diff --git a/packages/SettingsLib/res/values-th/strings.xml b/packages/SettingsLib/res/values-th/strings.xml
index d8950b8..4631e85 100644
--- a/packages/SettingsLib/res/values-th/strings.xml
+++ b/packages/SettingsLib/res/values-th/strings.xml
@@ -55,6 +55,14 @@
<string name="bluetooth_connected_no_a2dp" msgid="4576188601581440337">"เชื่อมต่อแล้ว (ยกเว้นเสียงสื่อ)"</string>
<string name="bluetooth_connected_no_map" msgid="6504436917057479986">"เชื่อมต่อแล้ว (ไม่มีการเข้าถึงข้อความ)"</string>
<string name="bluetooth_connected_no_headset_no_a2dp" msgid="9195757766755553810">"เชื่อมต่อ (ยกเว้นเสียงโทรศัพท์หรือสื่อ)"</string>
+ <!-- no translation found for bluetooth_connected_battery_level (7049181126136692368) -->
+ <skip />
+ <!-- no translation found for bluetooth_connected_no_headset_battery_level (5504193961248406027) -->
+ <skip />
+ <!-- no translation found for bluetooth_connected_no_a2dp_battery_level (4751724026365870779) -->
+ <skip />
+ <!-- no translation found for bluetooth_connected_no_headset_no_a2dp_battery_level (1549265779323455261) -->
+ <skip />
<string name="bluetooth_profile_a2dp" msgid="2031475486179830674">"เสียงสื่อ"</string>
<string name="bluetooth_profile_headset" msgid="7815495680863246034">"การโทรศัพท์"</string>
<string name="bluetooth_profile_opp" msgid="9168139293654233697">"การถ่ายโอนไฟล์"</string>
diff --git a/packages/SettingsLib/res/values-tl/strings.xml b/packages/SettingsLib/res/values-tl/strings.xml
index 7b10c85..88b9232 100644
--- a/packages/SettingsLib/res/values-tl/strings.xml
+++ b/packages/SettingsLib/res/values-tl/strings.xml
@@ -55,6 +55,14 @@
<string name="bluetooth_connected_no_a2dp" msgid="4576188601581440337">"Nakakonekta (walang media)"</string>
<string name="bluetooth_connected_no_map" msgid="6504436917057479986">"Nakakonekta (walang access sa mensahe)"</string>
<string name="bluetooth_connected_no_headset_no_a2dp" msgid="9195757766755553810">"Nakakonekta (walang telepono o media)"</string>
+ <!-- no translation found for bluetooth_connected_battery_level (7049181126136692368) -->
+ <skip />
+ <!-- no translation found for bluetooth_connected_no_headset_battery_level (5504193961248406027) -->
+ <skip />
+ <!-- no translation found for bluetooth_connected_no_a2dp_battery_level (4751724026365870779) -->
+ <skip />
+ <!-- no translation found for bluetooth_connected_no_headset_no_a2dp_battery_level (1549265779323455261) -->
+ <skip />
<string name="bluetooth_profile_a2dp" msgid="2031475486179830674">"Audio ng media"</string>
<string name="bluetooth_profile_headset" msgid="7815495680863246034">"Mga tawag sa telepono"</string>
<string name="bluetooth_profile_opp" msgid="9168139293654233697">"Paglilipat ng file"</string>
diff --git a/packages/SettingsLib/res/values-tr/strings.xml b/packages/SettingsLib/res/values-tr/strings.xml
index 8ceb1d8..2c8e1ec 100644
--- a/packages/SettingsLib/res/values-tr/strings.xml
+++ b/packages/SettingsLib/res/values-tr/strings.xml
@@ -55,6 +55,14 @@
<string name="bluetooth_connected_no_a2dp" msgid="4576188601581440337">"Bağlandı (medya yok)"</string>
<string name="bluetooth_connected_no_map" msgid="6504436917057479986">"Bağlı (mesaj erişimi yok)"</string>
<string name="bluetooth_connected_no_headset_no_a2dp" msgid="9195757766755553810">"Bağlandı (telefon veya medya yok)"</string>
+ <!-- no translation found for bluetooth_connected_battery_level (7049181126136692368) -->
+ <skip />
+ <!-- no translation found for bluetooth_connected_no_headset_battery_level (5504193961248406027) -->
+ <skip />
+ <!-- no translation found for bluetooth_connected_no_a2dp_battery_level (4751724026365870779) -->
+ <skip />
+ <!-- no translation found for bluetooth_connected_no_headset_no_a2dp_battery_level (1549265779323455261) -->
+ <skip />
<string name="bluetooth_profile_a2dp" msgid="2031475486179830674">"Medya sesi"</string>
<string name="bluetooth_profile_headset" msgid="7815495680863246034">"Telefon çağrıları"</string>
<string name="bluetooth_profile_opp" msgid="9168139293654233697">"Dosya aktarımı"</string>
diff --git a/packages/SettingsLib/res/values-uk/strings.xml b/packages/SettingsLib/res/values-uk/strings.xml
index ad32222..e7bd0c8 100644
--- a/packages/SettingsLib/res/values-uk/strings.xml
+++ b/packages/SettingsLib/res/values-uk/strings.xml
@@ -55,6 +55,14 @@
<string name="bluetooth_connected_no_a2dp" msgid="4576188601581440337">"Під’єднано (без медіа-файлів)"</string>
<string name="bluetooth_connected_no_map" msgid="6504436917057479986">"Під’єднано (без доступу до повідомлень)"</string>
<string name="bluetooth_connected_no_headset_no_a2dp" msgid="9195757766755553810">"Під’єднано (без телефону чи медіа)"</string>
+ <!-- no translation found for bluetooth_connected_battery_level (7049181126136692368) -->
+ <skip />
+ <!-- no translation found for bluetooth_connected_no_headset_battery_level (5504193961248406027) -->
+ <skip />
+ <!-- no translation found for bluetooth_connected_no_a2dp_battery_level (4751724026365870779) -->
+ <skip />
+ <!-- no translation found for bluetooth_connected_no_headset_no_a2dp_battery_level (1549265779323455261) -->
+ <skip />
<string name="bluetooth_profile_a2dp" msgid="2031475486179830674">"Звук медіа-файлів"</string>
<string name="bluetooth_profile_headset" msgid="7815495680863246034">"Телефонні дзвінки"</string>
<string name="bluetooth_profile_opp" msgid="9168139293654233697">"Передавання файлів"</string>
diff --git a/packages/SettingsLib/res/values-ur/strings.xml b/packages/SettingsLib/res/values-ur/strings.xml
index 6e9cdde..7e3723c 100644
--- a/packages/SettingsLib/res/values-ur/strings.xml
+++ b/packages/SettingsLib/res/values-ur/strings.xml
@@ -55,6 +55,14 @@
<string name="bluetooth_connected_no_a2dp" msgid="4576188601581440337">"مربوط (کوئی میڈیا نہیں ہے)"</string>
<string name="bluetooth_connected_no_map" msgid="6504436917057479986">"مربوط (کسی پیغام تک رسائی نہیں ہے)"</string>
<string name="bluetooth_connected_no_headset_no_a2dp" msgid="9195757766755553810">"مربوط (کوئی فون یا میڈیا نہیں ہے)"</string>
+ <!-- no translation found for bluetooth_connected_battery_level (7049181126136692368) -->
+ <skip />
+ <!-- no translation found for bluetooth_connected_no_headset_battery_level (5504193961248406027) -->
+ <skip />
+ <!-- no translation found for bluetooth_connected_no_a2dp_battery_level (4751724026365870779) -->
+ <skip />
+ <!-- no translation found for bluetooth_connected_no_headset_no_a2dp_battery_level (1549265779323455261) -->
+ <skip />
<string name="bluetooth_profile_a2dp" msgid="2031475486179830674">"میڈيا آڈیو"</string>
<string name="bluetooth_profile_headset" msgid="7815495680863246034">"فون کالز"</string>
<string name="bluetooth_profile_opp" msgid="9168139293654233697">"فائل کی منتقلی"</string>
diff --git a/packages/SettingsLib/res/values-uz/strings.xml b/packages/SettingsLib/res/values-uz/strings.xml
index 70cc95a..0d9bc50 100644
--- a/packages/SettingsLib/res/values-uz/strings.xml
+++ b/packages/SettingsLib/res/values-uz/strings.xml
@@ -55,6 +55,14 @@
<string name="bluetooth_connected_no_a2dp" msgid="4576188601581440337">"Ulanildi (mediadan tashqari)"</string>
<string name="bluetooth_connected_no_map" msgid="6504436917057479986">"Ulangan (xabarlarga kirib bo‘lmaydi)"</string>
<string name="bluetooth_connected_no_headset_no_a2dp" msgid="9195757766755553810">"Ulangan (telefon yoki media qurilma emas)"</string>
+ <!-- no translation found for bluetooth_connected_battery_level (7049181126136692368) -->
+ <skip />
+ <!-- no translation found for bluetooth_connected_no_headset_battery_level (5504193961248406027) -->
+ <skip />
+ <!-- no translation found for bluetooth_connected_no_a2dp_battery_level (4751724026365870779) -->
+ <skip />
+ <!-- no translation found for bluetooth_connected_no_headset_no_a2dp_battery_level (1549265779323455261) -->
+ <skip />
<string name="bluetooth_profile_a2dp" msgid="2031475486179830674">"Media audio"</string>
<string name="bluetooth_profile_headset" msgid="7815495680863246034">"Telefon chaqiruvlari"</string>
<string name="bluetooth_profile_opp" msgid="9168139293654233697">"Fayl o‘tkazish"</string>
diff --git a/packages/SettingsLib/res/values-vi/strings.xml b/packages/SettingsLib/res/values-vi/strings.xml
index 9ba6457..4bf4ec4 100644
--- a/packages/SettingsLib/res/values-vi/strings.xml
+++ b/packages/SettingsLib/res/values-vi/strings.xml
@@ -55,6 +55,14 @@
<string name="bluetooth_connected_no_a2dp" msgid="4576188601581440337">"Đã kết nối (không có phương tiện)"</string>
<string name="bluetooth_connected_no_map" msgid="6504436917057479986">"Đã kết nối (không truy cập tin nhắn)"</string>
<string name="bluetooth_connected_no_headset_no_a2dp" msgid="9195757766755553810">"Đã k.nối (kg có ĐT hoặc p.tiện nào)"</string>
+ <!-- no translation found for bluetooth_connected_battery_level (7049181126136692368) -->
+ <skip />
+ <!-- no translation found for bluetooth_connected_no_headset_battery_level (5504193961248406027) -->
+ <skip />
+ <!-- no translation found for bluetooth_connected_no_a2dp_battery_level (4751724026365870779) -->
+ <skip />
+ <!-- no translation found for bluetooth_connected_no_headset_no_a2dp_battery_level (1549265779323455261) -->
+ <skip />
<string name="bluetooth_profile_a2dp" msgid="2031475486179830674">"Âm thanh của phương tiện"</string>
<string name="bluetooth_profile_headset" msgid="7815495680863246034">"Cuộc gọi điện thoại"</string>
<string name="bluetooth_profile_opp" msgid="9168139293654233697">"Chuyển tệp"</string>
diff --git a/packages/SettingsLib/res/values-zh-rCN/strings.xml b/packages/SettingsLib/res/values-zh-rCN/strings.xml
index 43fa66e..addd04d5 100644
--- a/packages/SettingsLib/res/values-zh-rCN/strings.xml
+++ b/packages/SettingsLib/res/values-zh-rCN/strings.xml
@@ -55,6 +55,14 @@
<string name="bluetooth_connected_no_a2dp" msgid="4576188601581440337">"已连接(无媒体)"</string>
<string name="bluetooth_connected_no_map" msgid="6504436917057479986">"已连接(无消息权限)"</string>
<string name="bluetooth_connected_no_headset_no_a2dp" msgid="9195757766755553810">"已连接(没有手机或媒体信号)"</string>
+ <!-- no translation found for bluetooth_connected_battery_level (7049181126136692368) -->
+ <skip />
+ <!-- no translation found for bluetooth_connected_no_headset_battery_level (5504193961248406027) -->
+ <skip />
+ <!-- no translation found for bluetooth_connected_no_a2dp_battery_level (4751724026365870779) -->
+ <skip />
+ <!-- no translation found for bluetooth_connected_no_headset_no_a2dp_battery_level (1549265779323455261) -->
+ <skip />
<string name="bluetooth_profile_a2dp" msgid="2031475486179830674">"媒体音频"</string>
<string name="bluetooth_profile_headset" msgid="7815495680863246034">"通话"</string>
<string name="bluetooth_profile_opp" msgid="9168139293654233697">"文件传输"</string>
@@ -110,7 +118,7 @@
<string name="unknown" msgid="1592123443519355854">"未知"</string>
<string name="running_process_item_user_label" msgid="3129887865552025943">"用户:<xliff:g id="USER_NAME">%1$s</xliff:g>"</string>
<string name="launch_defaults_some" msgid="313159469856372621">"已设置部分默认选项"</string>
- <string name="launch_defaults_none" msgid="4241129108140034876">"未设置任何默认选项"</string>
+ <string name="launch_defaults_none" msgid="4241129108140034876">"没有默认操作"</string>
<string name="tts_settings" msgid="8186971894801348327">"文字转语音设置"</string>
<string name="tts_settings_title" msgid="1237820681016639683">"文字转语音 (TTS) 输出"</string>
<string name="tts_default_rate_title" msgid="6030550998379310088">"语速"</string>
@@ -160,9 +168,9 @@
<string name="vpn_settings_not_available" msgid="956841430176985598">"此用户无权修改VPN设置"</string>
<string name="tethering_settings_not_available" msgid="6765770438438291012">"此用户无权修改网络共享设置"</string>
<string name="apn_settings_not_available" msgid="7873729032165324000">"此用户无权修改接入点名称设置"</string>
- <string name="enable_adb" msgid="7982306934419797485">"USB调试"</string>
+ <string name="enable_adb" msgid="7982306934419797485">"USB 调试"</string>
<string name="enable_adb_summary" msgid="4881186971746056635">"连接USB后启用调试模式"</string>
- <string name="clear_adb_keys" msgid="4038889221503122743">"撤消USB调试授权"</string>
+ <string name="clear_adb_keys" msgid="4038889221503122743">"撤消 USB 调试授权"</string>
<string name="bugreport_in_power" msgid="7923901846375587241">"错误报告快捷方式"</string>
<string name="bugreport_in_power_summary" msgid="1778455732762984579">"在电源菜单中显示用于提交错误报告的按钮"</string>
<string name="keep_screen_on" msgid="1146389631208760344">"不锁定屏幕"</string>
@@ -213,9 +221,9 @@
<string name="allow_mock_location_summary" msgid="317615105156345626">"允许模拟位置"</string>
<string name="debug_view_attributes" msgid="6485448367803310384">"启用视图属性检查功能"</string>
<string name="mobile_data_always_on_summary" msgid="8149773901431697910">"始终开启移动数据网络,即使 WLAN 网络已开启(便于快速切换网络)。"</string>
- <string name="adb_warning_title" msgid="6234463310896563253">"是否允许USB调试?"</string>
+ <string name="adb_warning_title" msgid="6234463310896563253">"是否允许 USB 调试?"</string>
<string name="adb_warning_message" msgid="7316799925425402244">"USB 调试仅用于开发目的。该功能可用于在您的计算机和设备之间复制数据、在您的设备上安装应用(事先不发通知)以及读取日志数据。"</string>
- <string name="adb_keys_warning_message" msgid="5659849457135841625">"是否针对您之前授权的所有计算机撤消USB调试的访问权限?"</string>
+ <string name="adb_keys_warning_message" msgid="5659849457135841625">"是否针对您之前授权的所有计算机撤消 USB 调试的访问权限?"</string>
<string name="dev_settings_warning_title" msgid="7244607768088540165">"允许开发设置?"</string>
<string name="dev_settings_warning_message" msgid="2298337781139097964">"这些设置仅适用于开发工作。一旦启用,会导致您的设备以及设备上的应用崩溃或出现异常。"</string>
<string name="verify_apps_over_usb_title" msgid="4177086489869041953">"通过USB验证应用"</string>
@@ -232,7 +240,7 @@
<string name="debug_app_set" msgid="2063077997870280017">"调试应用:<xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
<string name="select_application" msgid="5156029161289091703">"选择应用"</string>
<string name="no_application" msgid="2813387563129153880">"无"</string>
- <string name="wait_for_debugger" msgid="1202370874528893091">"等待调试器"</string>
+ <string name="wait_for_debugger" msgid="1202370874528893091">"等待调试程序"</string>
<string name="wait_for_debugger_summary" msgid="1766918303462746804">"调试应用会在执行前等待附加调试器"</string>
<string name="telephony_monitor_switch" msgid="1764958220062121194">"电话监控器"</string>
<string name="telephony_monitor_switch_summary" msgid="7695552966547975635">"电话监控器会在检测到电话/调制解调器功能存在问题时收集相关日志,并向用户发出通知,提醒用户提交错误报告"</string>
diff --git a/packages/SettingsLib/res/values-zh-rHK/strings.xml b/packages/SettingsLib/res/values-zh-rHK/strings.xml
index 41eb94f..ee4ff6b 100644
--- a/packages/SettingsLib/res/values-zh-rHK/strings.xml
+++ b/packages/SettingsLib/res/values-zh-rHK/strings.xml
@@ -55,13 +55,21 @@
<string name="bluetooth_connected_no_a2dp" msgid="4576188601581440337">"已連線 (無媒體)"</string>
<string name="bluetooth_connected_no_map" msgid="6504436917057479986">"已連結 (無訊息存取權)"</string>
<string name="bluetooth_connected_no_headset_no_a2dp" msgid="9195757766755553810">"已連線 (無手機或媒體)"</string>
+ <!-- no translation found for bluetooth_connected_battery_level (7049181126136692368) -->
+ <skip />
+ <!-- no translation found for bluetooth_connected_no_headset_battery_level (5504193961248406027) -->
+ <skip />
+ <!-- no translation found for bluetooth_connected_no_a2dp_battery_level (4751724026365870779) -->
+ <skip />
+ <!-- no translation found for bluetooth_connected_no_headset_no_a2dp_battery_level (1549265779323455261) -->
+ <skip />
<string name="bluetooth_profile_a2dp" msgid="2031475486179830674">"媒體音效"</string>
<string name="bluetooth_profile_headset" msgid="7815495680863246034">"通話"</string>
<string name="bluetooth_profile_opp" msgid="9168139293654233697">"檔案傳輸"</string>
<string name="bluetooth_profile_hid" msgid="3680729023366986480">"輸入裝置"</string>
<string name="bluetooth_profile_pan" msgid="3391606497945147673">"互聯網連線"</string>
- <string name="bluetooth_profile_pbap" msgid="5372051906968576809">"聯絡人共用"</string>
- <string name="bluetooth_profile_pbap_summary" msgid="6605229608108852198">"用於聯絡人共用"</string>
+ <string name="bluetooth_profile_pbap" msgid="5372051906968576809">"共用聯絡人"</string>
+ <string name="bluetooth_profile_pbap_summary" msgid="6605229608108852198">"用於共用聯絡人"</string>
<string name="bluetooth_profile_pan_nap" msgid="8429049285027482959">"互聯網連線分享"</string>
<string name="bluetooth_profile_map" msgid="1019763341565580450">"短訊"</string>
<string name="bluetooth_profile_sap" msgid="5764222021851283125">"SIM 卡存取"</string>
diff --git a/packages/SettingsLib/res/values-zh-rTW/strings.xml b/packages/SettingsLib/res/values-zh-rTW/strings.xml
index edd02c9..0a4e483 100644
--- a/packages/SettingsLib/res/values-zh-rTW/strings.xml
+++ b/packages/SettingsLib/res/values-zh-rTW/strings.xml
@@ -55,6 +55,14 @@
<string name="bluetooth_connected_no_a2dp" msgid="4576188601581440337">"已連線 (無媒體音訊)"</string>
<string name="bluetooth_connected_no_map" msgid="6504436917057479986">"已連線 (無訊息存取權)"</string>
<string name="bluetooth_connected_no_headset_no_a2dp" msgid="9195757766755553810">"已連線 (無手機或媒體音訊)"</string>
+ <!-- no translation found for bluetooth_connected_battery_level (7049181126136692368) -->
+ <skip />
+ <!-- no translation found for bluetooth_connected_no_headset_battery_level (5504193961248406027) -->
+ <skip />
+ <!-- no translation found for bluetooth_connected_no_a2dp_battery_level (4751724026365870779) -->
+ <skip />
+ <!-- no translation found for bluetooth_connected_no_headset_no_a2dp_battery_level (1549265779323455261) -->
+ <skip />
<string name="bluetooth_profile_a2dp" msgid="2031475486179830674">"媒體音訊"</string>
<string name="bluetooth_profile_headset" msgid="7815495680863246034">"通話"</string>
<string name="bluetooth_profile_opp" msgid="9168139293654233697">"檔案傳輸"</string>
@@ -65,8 +73,8 @@
<string name="bluetooth_profile_pan_nap" msgid="8429049285027482959">"網際網路連線分享"</string>
<string name="bluetooth_profile_map" msgid="1019763341565580450">"簡訊"</string>
<string name="bluetooth_profile_sap" msgid="5764222021851283125">"SIM 卡存取權"</string>
- <string name="bluetooth_profile_a2dp_high_quality" msgid="5444517801472820055">"HD 高解析度音訊:<xliff:g id="CODEC_NAME">%1$s</xliff:g>"</string>
- <string name="bluetooth_profile_a2dp_high_quality_unknown_codec" msgid="8510588052415438887">"HD 高解析度音訊"</string>
+ <string name="bluetooth_profile_a2dp_high_quality" msgid="5444517801472820055">"HD 高解析音訊:<xliff:g id="CODEC_NAME">%1$s</xliff:g>"</string>
+ <string name="bluetooth_profile_a2dp_high_quality_unknown_codec" msgid="8510588052415438887">"HD 高解析音訊"</string>
<string name="bluetooth_a2dp_profile_summary_connected" msgid="963376081347721598">"連接至媒體音訊"</string>
<string name="bluetooth_headset_profile_summary_connected" msgid="7661070206715520671">"連接至電話音訊"</string>
<string name="bluetooth_opp_profile_summary_connected" msgid="2611913495968309066">"已連線到檔案傳輸伺服器"</string>
diff --git a/packages/SettingsLib/res/values-zu/strings.xml b/packages/SettingsLib/res/values-zu/strings.xml
index b2e5ae3..a142c32 100644
--- a/packages/SettingsLib/res/values-zu/strings.xml
+++ b/packages/SettingsLib/res/values-zu/strings.xml
@@ -55,6 +55,14 @@
<string name="bluetooth_connected_no_a2dp" msgid="4576188601581440337">"Ixhunyiwe (ayikho imidiya)"</string>
<string name="bluetooth_connected_no_map" msgid="6504436917057479986">"Kuxhunyiwe (akukho ukufinyelela umlayezo)"</string>
<string name="bluetooth_connected_no_headset_no_a2dp" msgid="9195757766755553810">"Ixhunyiwe (ayikho ifoni noma imidiya)"</string>
+ <!-- no translation found for bluetooth_connected_battery_level (7049181126136692368) -->
+ <skip />
+ <!-- no translation found for bluetooth_connected_no_headset_battery_level (5504193961248406027) -->
+ <skip />
+ <!-- no translation found for bluetooth_connected_no_a2dp_battery_level (4751724026365870779) -->
+ <skip />
+ <!-- no translation found for bluetooth_connected_no_headset_no_a2dp_battery_level (1549265779323455261) -->
+ <skip />
<string name="bluetooth_profile_a2dp" msgid="2031475486179830674">"Umsindo wemidiya"</string>
<string name="bluetooth_profile_headset" msgid="7815495680863246034">"Amakholi efoni"</string>
<string name="bluetooth_profile_opp" msgid="9168139293654233697">"Dlulisa ifayela"</string>
diff --git a/packages/SettingsLib/res/values/strings.xml b/packages/SettingsLib/res/values/strings.xml
index a430288..064cc84 100644
--- a/packages/SettingsLib/res/values/strings.xml
+++ b/packages/SettingsLib/res/values/strings.xml
@@ -465,6 +465,8 @@
<string name="wifi_allow_scan_with_traffic">Always allow Wi\u2011Fi Roam Scans</string>
<!-- Setting Checkbox title whether to always keep mobile data active. [CHAR LIMIT=80] -->
<string name="mobile_data_always_on">Mobile data always active</string>
+ <!-- Setting Checkbox title whether to enable hardware acceleration for tethering. [CHAR LIMIT=80] -->
+ <string name="tethering_hardware_offload">Tethering hardware acceleration</string>
<!-- Setting Checkbox title for disabling Bluetooth absolute volume -->
<string name="bluetooth_disable_absolute_volume">Disable absolute volume</string>
<!-- Setting Checkbox title for enabling Bluetooth inband ringing -->
@@ -534,6 +536,7 @@
<!-- Setting Checkbox title whether to enable view attribute inspection -->
<string name="debug_view_attributes">Enable view attribute inspection</string>
<string name="mobile_data_always_on_summary">Always keep mobile data active, even when Wi\u2011Fi is active (for fast network switching).</string>
+ <string name="tethering_hardware_offload_summary">Use tethering hardware acceleration if available</string>
<!-- Title of warning dialog about the implications of enabling USB debugging -->
<string name="adb_warning_title">Allow USB debugging?</string>
<!-- Warning text to user about the implications of enabling USB debugging -->
diff --git a/packages/SettingsLib/src/com/android/settingslib/applications/InterestingConfigChanges.java b/packages/SettingsLib/src/com/android/settingslib/applications/InterestingConfigChanges.java
index e4e0f7f..c4cbc2b 100644
--- a/packages/SettingsLib/src/com/android/settingslib/applications/InterestingConfigChanges.java
+++ b/packages/SettingsLib/src/com/android/settingslib/applications/InterestingConfigChanges.java
@@ -36,7 +36,8 @@
}
public boolean applyNewConfig(Resources res) {
- int configChanges = mLastConfiguration.updateFrom(res.getConfiguration());
+ int configChanges = mLastConfiguration.updateFrom(
+ Configuration.generateDelta(mLastConfiguration, res.getConfiguration()));
boolean densityChanged = mLastDensity != res.getDisplayMetrics().densityDpi;
if (densityChanged || (configChanges & (mFlags)) != 0) {
mLastDensity = res.getDisplayMetrics().densityDpi;
diff --git a/packages/SettingsLib/src/com/android/settingslib/bluetooth/BluetoothEventManager.java b/packages/SettingsLib/src/com/android/settingslib/bluetooth/BluetoothEventManager.java
index 80b943c..d07da93 100755
--- a/packages/SettingsLib/src/com/android/settingslib/bluetooth/BluetoothEventManager.java
+++ b/packages/SettingsLib/src/com/android/settingslib/bluetooth/BluetoothEventManager.java
@@ -102,6 +102,7 @@
// Fine-grained state broadcasts
addHandler(BluetoothDevice.ACTION_CLASS_CHANGED, new ClassChangedHandler());
addHandler(BluetoothDevice.ACTION_UUID, new UuidChangedHandler());
+ addHandler(BluetoothDevice.ACTION_BATTERY_LEVEL_CHANGED, new BatteryLevelChangedHandler());
// Dock event broadcasts
addHandler(Intent.ACTION_DOCK_EVENT, new DockEventHandler());
@@ -376,6 +377,17 @@
}
}
}
+
+ private class BatteryLevelChangedHandler implements Handler {
+ public void onReceive(Context context, Intent intent,
+ BluetoothDevice device) {
+ CachedBluetoothDevice cachedDevice = mDeviceManager.findDevice(device);
+ if (cachedDevice != null) {
+ cachedDevice.refresh();
+ }
+ }
+ }
+
boolean readPairedDevices() {
Set<BluetoothDevice> bondedDevices = mLocalAdapter.getBondedDevices();
if (bondedDevices == null) {
diff --git a/packages/SettingsLib/src/com/android/settingslib/bluetooth/CachedBluetoothDevice.java b/packages/SettingsLib/src/com/android/settingslib/bluetooth/CachedBluetoothDevice.java
index e279a09..4bb4b40 100644
--- a/packages/SettingsLib/src/com/android/settingslib/bluetooth/CachedBluetoothDevice.java
+++ b/packages/SettingsLib/src/com/android/settingslib/bluetooth/CachedBluetoothDevice.java
@@ -368,6 +368,15 @@
return mDevice;
}
+ /**
+ * Convenience method that can be mocked - it lets tests avoid having to call getDevice() which
+ * causes problems in tests since BluetoothDevice is final and cannot be mocked.
+ * @return the address of this device
+ */
+ public String getAddress() {
+ return mDevice.getAddress();
+ }
+
public String getName() {
return mName;
}
@@ -410,6 +419,14 @@
}
}
+ /**
+ * Get battery level from remote device
+ * @return battery level in percentage [0-100], or {@link BluetoothDevice#BATTERY_LEVEL_UNKNOWN}
+ */
+ public int getBatteryLevel() {
+ return mDevice.getBatteryLevel();
+ }
+
void refresh() {
dispatchAttributesChanged();
}
@@ -828,7 +845,7 @@
/**
* @return resource for string that discribes the connection state of this device.
*/
- public int getConnectionSummary() {
+ public String getConnectionSummary() {
boolean profileConnected = false; // at least one profile is connected
boolean a2dpNotConnected = false; // A2DP is preferred but not connected
boolean hfpNotConnected = false; // HFP is preferred but not connected
@@ -839,7 +856,7 @@
switch (connectionStatus) {
case BluetoothProfile.STATE_CONNECTING:
case BluetoothProfile.STATE_DISCONNECTING:
- return Utils.getConnectionStateSummary(connectionStatus);
+ return mContext.getString(Utils.getConnectionStateSummary(connectionStatus));
case BluetoothProfile.STATE_CONNECTED:
profileConnected = true;
@@ -859,18 +876,54 @@
}
}
+ String batteryLevelPercentageString = null;
+ // Android framework should only set mBatteryLevel to valid range [0-100] or
+ // BluetoothDevice.BATTERY_LEVEL_UNKNOWN, any other value should be a framework bug.
+ // Thus assume here that if value is not BluetoothDevice.BATTERY_LEVEL_UNKNOWN, it must
+ // be valid
+ final int batteryLevel = getBatteryLevel();
+ if (batteryLevel != BluetoothDevice.BATTERY_LEVEL_UNKNOWN) {
+ // TODO: name com.android.settingslib.bluetooth.Utils something different
+ batteryLevelPercentageString =
+ com.android.settingslib.Utils.formatPercentage(batteryLevel);
+ }
+
if (profileConnected) {
if (a2dpNotConnected && hfpNotConnected) {
- return R.string.bluetooth_connected_no_headset_no_a2dp;
+ if (batteryLevelPercentageString != null) {
+ return mContext.getString(
+ R.string.bluetooth_connected_no_headset_no_a2dp_battery_level,
+ batteryLevelPercentageString);
+ } else {
+ return mContext.getString(R.string.bluetooth_connected_no_headset_no_a2dp);
+ }
+
} else if (a2dpNotConnected) {
- return R.string.bluetooth_connected_no_a2dp;
+ if (batteryLevelPercentageString != null) {
+ return mContext.getString(R.string.bluetooth_connected_no_a2dp_battery_level,
+ batteryLevelPercentageString);
+ } else {
+ return mContext.getString(R.string.bluetooth_connected_no_a2dp);
+ }
+
} else if (hfpNotConnected) {
- return R.string.bluetooth_connected_no_headset;
+ if (batteryLevelPercentageString != null) {
+ return mContext.getString(R.string.bluetooth_connected_no_headset_battery_level,
+ batteryLevelPercentageString);
+ } else {
+ return mContext.getString(R.string.bluetooth_connected_no_headset);
+ }
} else {
- return R.string.bluetooth_connected;
+ if (batteryLevelPercentageString != null) {
+ return mContext.getString(R.string.bluetooth_connected_battery_level,
+ batteryLevelPercentageString);
+ } else {
+ return mContext.getString(R.string.bluetooth_connected);
+ }
}
}
- return getBondState() == BluetoothDevice.BOND_BONDING ? R.string.bluetooth_pairing : 0;
+ return getBondState() == BluetoothDevice.BOND_BONDING ?
+ mContext.getString(R.string.bluetooth_pairing) : null;
}
}
diff --git a/packages/SettingsLib/src/com/android/settingslib/bluetooth/HeadsetProfile.java b/packages/SettingsLib/src/com/android/settingslib/bluetooth/HeadsetProfile.java
index 5529866..d45fe1a 100755
--- a/packages/SettingsLib/src/com/android/settingslib/bluetooth/HeadsetProfile.java
+++ b/packages/SettingsLib/src/com/android/settingslib/bluetooth/HeadsetProfile.java
@@ -34,7 +34,7 @@
/**
* HeadsetProfile handles Bluetooth HFP and Headset profiles.
*/
-public final class HeadsetProfile implements LocalBluetoothProfile {
+public class HeadsetProfile implements LocalBluetoothProfile {
private static final String TAG = "HeadsetProfile";
private static boolean V = true;
diff --git a/packages/SettingsLib/src/com/android/settingslib/bluetooth/HidProfile.java b/packages/SettingsLib/src/com/android/settingslib/bluetooth/HidProfile.java
index a9e8db5..d1621da 100755
--- a/packages/SettingsLib/src/com/android/settingslib/bluetooth/HidProfile.java
+++ b/packages/SettingsLib/src/com/android/settingslib/bluetooth/HidProfile.java
@@ -31,7 +31,7 @@
/**
* HidProfile handles Bluetooth HID profile.
*/
-public final class HidProfile implements LocalBluetoothProfile {
+public class HidProfile implements LocalBluetoothProfile {
private static final String TAG = "HidProfile";
private static boolean V = true;
diff --git a/packages/SettingsLib/src/com/android/settingslib/wifi/AccessPoint.java b/packages/SettingsLib/src/com/android/settingslib/wifi/AccessPoint.java
index 4a54451..ec41415 100644
--- a/packages/SettingsLib/src/com/android/settingslib/wifi/AccessPoint.java
+++ b/packages/SettingsLib/src/com/android/settingslib/wifi/AccessPoint.java
@@ -1053,7 +1053,8 @@
}
/** Attempt to update the AccessPoint and return true if an update occurred. */
- public boolean update(WifiConfiguration config, WifiInfo info, NetworkInfo networkInfo) {
+ public boolean update(
+ @Nullable WifiConfiguration config, WifiInfo info, NetworkInfo networkInfo) {
boolean updated = false;
final int oldLevel = getLevel();
if (info != null && isInfoForThisAccessPoint(config, info)) {
@@ -1088,9 +1089,9 @@
return updated;
}
- void update(WifiConfiguration config) {
+ void update(@Nullable WifiConfiguration config) {
mConfig = config;
- networkId = config.networkId;
+ networkId = config != null ? config.networkId : WifiConfiguration.INVALID_NETWORK_ID;
if (mAccessPointListener != null) {
mAccessPointListener.onAccessPointChanged(this);
}
diff --git a/packages/SettingsLib/tests/integ/src/com/android/settingslib/wifi/AccessPointTest.java b/packages/SettingsLib/tests/integ/src/com/android/settingslib/wifi/AccessPointTest.java
index 5c64cff..c08dd6e 100644
--- a/packages/SettingsLib/tests/integ/src/com/android/settingslib/wifi/AccessPointTest.java
+++ b/packages/SettingsLib/tests/integ/src/com/android/settingslib/wifi/AccessPointTest.java
@@ -656,4 +656,28 @@
assertThat(ap.update(newConfig, wifiInfo, networkInfo)).isFalse();
verify(mockListener).onAccessPointChanged(ap);
}
+
+ @Test
+ public void testUpdateWithNullWifiConfiguration_doesNotThrowNPE() {
+ int networkId = 123;
+ int rssi = -55;
+ WifiConfiguration config = new WifiConfiguration();
+ config.networkId = networkId;
+ WifiInfo wifiInfo = new WifiInfo();
+ wifiInfo.setNetworkId(networkId);
+ wifiInfo.setRssi(rssi);
+
+ NetworkInfo networkInfo =
+ new NetworkInfo(ConnectivityManager.TYPE_WIFI, 0 /* subtype */, "WIFI", "");
+ networkInfo.setDetailedState(NetworkInfo.DetailedState.CONNECTING, "", "");
+
+ AccessPoint ap = new TestAccessPointBuilder(mContext)
+ .setNetworkInfo(networkInfo)
+ .setNetworkId(networkId)
+ .setRssi(rssi)
+ .setWifiInfo(wifiInfo)
+ .build();
+
+ ap.update(null, wifiInfo, networkInfo);
+ }
}
diff --git a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/bluetooth/CachedBluetoothDeviceTest.java b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/bluetooth/CachedBluetoothDeviceTest.java
new file mode 100644
index 0000000..e2ebbeb
--- /dev/null
+++ b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/bluetooth/CachedBluetoothDeviceTest.java
@@ -0,0 +1,155 @@
+/*
+ * 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.settingslib.bluetooth;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import static org.mockito.Mockito.doAnswer;
+import static org.mockito.Mockito.spy;
+import static org.mockito.Mockito.when;
+
+import android.bluetooth.BluetoothAdapter;
+import android.bluetooth.BluetoothDevice;
+import android.bluetooth.BluetoothProfile;
+import android.content.Context;
+
+import com.android.settingslib.R;
+import com.android.settingslib.TestConfig;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+import org.robolectric.RobolectricTestRunner;
+import org.robolectric.RuntimeEnvironment;
+import org.robolectric.annotation.Config;
+
+@RunWith(RobolectricTestRunner.class)
+@Config(manifest = TestConfig.MANIFEST_PATH, sdk = TestConfig.SDK_VERSION, resourceDir =
+ "../../res")
+public class CachedBluetoothDeviceTest {
+ @Mock
+ private LocalBluetoothAdapter mAdapter;
+ @Mock
+ private LocalBluetoothProfileManager mProfileManager;
+ @Mock
+ private HeadsetProfile mHfpProfile;
+ @Mock
+ private A2dpProfile mA2dpProfile;
+ @Mock
+ private HidProfile mHidProfile;
+ @Mock
+ private BluetoothDevice mDevice;
+ private CachedBluetoothDevice mCachedDevice;
+ private Context mContext;
+ private int mBatteryLevel = BluetoothDevice.BATTERY_LEVEL_UNKNOWN;
+
+ @Before
+ public void setUp() {
+ MockitoAnnotations.initMocks(this);
+ mContext = RuntimeEnvironment.application;
+ when(mAdapter.getBluetoothState()).thenReturn(BluetoothAdapter.STATE_ON);
+ when(mHfpProfile.isProfileReady()).thenReturn(true);
+ when(mA2dpProfile.isProfileReady()).thenReturn(true);
+ when(mHidProfile.isProfileReady()).thenReturn(true);
+ mCachedDevice = spy(
+ new CachedBluetoothDevice(mContext, mAdapter, mProfileManager, mDevice));
+ doAnswer((invocation) -> mBatteryLevel).when(mCachedDevice).getBatteryLevel();
+ }
+
+ /**
+ * Test to verify the current test context object works so that we are not checking null
+ * against null
+ */
+ @Test
+ public void testContextMock() {
+ assertThat(mContext.getString(R.string.bluetooth_connected)).isEqualTo("Connected");
+ }
+
+ @Test
+ public void testGetConnectionSummary_testSingleProfileConnectDisconnect() {
+ // Test without battery level
+ // Set HID profile to be connected and test connection state summary
+ mCachedDevice.onProfileStateChanged(mHidProfile, BluetoothProfile.STATE_CONNECTED);
+ assertThat(mCachedDevice.getConnectionSummary()).isEqualTo(mContext.getString(
+ R.string.bluetooth_connected));
+
+ // Set HID profile to be disconnected and test connection state summary
+ mCachedDevice.onProfileStateChanged(mHidProfile, BluetoothProfile.STATE_DISCONNECTED);
+ assertThat(mCachedDevice.getConnectionSummary()).isNull();
+
+ // Test with battery level
+ mBatteryLevel = 10;
+ // Set HID profile to be connected and test connection state summary
+ mCachedDevice.onProfileStateChanged(mHidProfile, BluetoothProfile.STATE_CONNECTED);
+ assertThat(mCachedDevice.getConnectionSummary()).isEqualTo(mContext.getString(
+ R.string.bluetooth_connected_battery_level,
+ com.android.settingslib.Utils.formatPercentage(mBatteryLevel)));
+
+ // Set HID profile to be disconnected and test connection state summary
+ mCachedDevice.onProfileStateChanged(mHidProfile, BluetoothProfile.STATE_DISCONNECTED);
+ assertThat(mCachedDevice.getConnectionSummary()).isNull();
+
+ // Test with BluetoothDevice.BATTERY_LEVEL_UNKNOWN battery level
+ mBatteryLevel = BluetoothDevice.BATTERY_LEVEL_UNKNOWN;
+
+ // Set HID profile to be connected and test connection state summary
+ mCachedDevice.onProfileStateChanged(mHidProfile, BluetoothProfile.STATE_CONNECTED);
+ assertThat(mCachedDevice.getConnectionSummary()).isEqualTo(mContext.getString(
+ R.string.bluetooth_connected));
+
+ // Set HID profile to be disconnected and test connection state summary
+ mCachedDevice.onProfileStateChanged(mHidProfile, BluetoothProfile.STATE_DISCONNECTED);
+ assertThat(mCachedDevice.getConnectionSummary()).isNull();
+ }
+
+ @Test
+ public void testGetConnectionSummary_testMultipleProfileConnectDisconnect() {
+ mBatteryLevel = 10;
+
+ // Set HFP, A2DP and HID profile to be connected and test connection state summary
+ mCachedDevice.onProfileStateChanged(mHfpProfile, BluetoothProfile.STATE_CONNECTED);
+ mCachedDevice.onProfileStateChanged(mA2dpProfile, BluetoothProfile.STATE_CONNECTED);
+ mCachedDevice.onProfileStateChanged(mHidProfile, BluetoothProfile.STATE_CONNECTED);
+ assertThat(mCachedDevice.getConnectionSummary()).isEqualTo(mContext.getString(
+ R.string.bluetooth_connected_battery_level,
+ com.android.settingslib.Utils.formatPercentage(mBatteryLevel)));
+
+ // Disconnect HFP only and test connection state summary
+ mCachedDevice.onProfileStateChanged(mHfpProfile, BluetoothProfile.STATE_DISCONNECTED);
+ assertThat(mCachedDevice.getConnectionSummary()).isEqualTo(mContext.getString(
+ R.string.bluetooth_connected_no_headset_battery_level,
+ com.android.settingslib.Utils.formatPercentage(mBatteryLevel)));
+
+ // Disconnect A2DP only and test connection state summary
+ mCachedDevice.onProfileStateChanged(mHfpProfile, BluetoothProfile.STATE_CONNECTED);
+ mCachedDevice.onProfileStateChanged(mA2dpProfile, BluetoothProfile.STATE_DISCONNECTED);
+ assertThat(mCachedDevice.getConnectionSummary()).isEqualTo(mContext.getString(
+ R.string.bluetooth_connected_no_a2dp_battery_level,
+ com.android.settingslib.Utils.formatPercentage(mBatteryLevel)));
+
+ // Disconnect both HFP and A2DP and test connection state summary
+ mCachedDevice.onProfileStateChanged(mHfpProfile, BluetoothProfile.STATE_DISCONNECTED);
+ assertThat(mCachedDevice.getConnectionSummary()).isEqualTo(mContext.getString(
+ R.string.bluetooth_connected_no_headset_no_a2dp_battery_level,
+ com.android.settingslib.Utils.formatPercentage(mBatteryLevel)));
+
+ // Disconnect all profiles and test connection state summary
+ mCachedDevice.onProfileStateChanged(mHidProfile, BluetoothProfile.STATE_DISCONNECTED);
+ assertThat(mCachedDevice.getConnectionSummary()).isNull();
+ }
+}
diff --git a/packages/SystemUI/res/anim/ic_landscape_from_auto_rotate_animation_arrow_bottom.xml b/packages/SystemUI/res/anim/ic_landscape_from_auto_rotate_animation_arrow_bottom.xml
deleted file mode 100644
index b003e92..0000000
--- a/packages/SystemUI/res/anim/ic_landscape_from_auto_rotate_animation_arrow_bottom.xml
+++ /dev/null
@@ -1,33 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
- 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.
--->
-<set xmlns:android="http://schemas.android.com/apk/res/android" >
- <set
- android:ordering="sequentially" >
- <objectAnimator
- android:duration="367"
- android:propertyName="fillAlpha"
- android:valueFrom="1"
- android:valueTo="1"
- android:interpolator="@android:interpolator/linear" />
- <objectAnimator
- android:duration="33"
- android:propertyName="fillAlpha"
- android:valueFrom="1"
- android:valueTo="0"
- android:interpolator="@android:interpolator/linear" />
- </set>
-</set>
diff --git a/packages/SystemUI/res/anim/ic_landscape_from_auto_rotate_animation_arrow_top.xml b/packages/SystemUI/res/anim/ic_landscape_from_auto_rotate_animation_arrow_top.xml
deleted file mode 100644
index b003e92..0000000
--- a/packages/SystemUI/res/anim/ic_landscape_from_auto_rotate_animation_arrow_top.xml
+++ /dev/null
@@ -1,33 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
- 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.
--->
-<set xmlns:android="http://schemas.android.com/apk/res/android" >
- <set
- android:ordering="sequentially" >
- <objectAnimator
- android:duration="367"
- android:propertyName="fillAlpha"
- android:valueFrom="1"
- android:valueTo="1"
- android:interpolator="@android:interpolator/linear" />
- <objectAnimator
- android:duration="33"
- android:propertyName="fillAlpha"
- android:valueFrom="1"
- android:valueTo="0"
- android:interpolator="@android:interpolator/linear" />
- </set>
-</set>
diff --git a/packages/SystemUI/res/anim/ic_landscape_from_auto_rotate_animation_body.xml b/packages/SystemUI/res/anim/ic_landscape_from_auto_rotate_animation_body.xml
deleted file mode 100644
index aa086c9..0000000
--- a/packages/SystemUI/res/anim/ic_landscape_from_auto_rotate_animation_body.xml
+++ /dev/null
@@ -1,35 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
- 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.
--->
-<set xmlns:android="http://schemas.android.com/apk/res/android" >
- <set
- android:ordering="sequentially" >
- <objectAnimator
- android:duration="67"
- android:propertyName="pathData"
- android:valueFrom="M -3.5,-20.5 c -1.19999694824,-1.19999694824 -3.10000610352,-1.19999694824 -4.19999694824,0.0 c 0.0,0.0 -12.8000030518,12.6999969482 -12.8000030518,12.6999969482 c -1.19999694824,1.19999694824 -1.19999694824,3.10000610352 0.0,4.19999694824 c 0.0,0.0 24.0,24.0000152588 24.0,24.0000152588 c 1.19999694824,1.19999694824 3.10000610352,1.19999694824 4.19999694824,0.0 c 0.0,0.0 12.6999969482,-12.700012207 12.6999969482,-12.700012207 c 1.20001220703,-1.19999694824 1.20001220703,-3.09999084473 0.0,-4.19999694824 c 0.0,0.0 -23.8999938965,-24.0 -23.8999938965,-24.0 Z M 2.84999084473,15.5500183105 c 0.0,0.0 -18.6000061035,-18.5000457764 -18.6000061035,-18.5000457764 c 0.0,0.0 12.5999908447,-12.8000030518 12.5999908447,-12.8000030518 c 0.0,0.0 18.6000213623,18.5000457764 18.6000213623,18.5000457764 c 0.0,0.0 -12.6000061035,12.8000030518 -12.6000061035,12.8000030518 Z"
- android:valueTo="M -3.5,-20.5 c -1.19999694824,-1.19999694824 -3.10000610352,-1.19999694824 -4.19999694824,0.0 c 0.0,0.0 -12.8000030518,12.6999969482 -12.8000030518,12.6999969482 c -1.19999694824,1.19999694824 -1.19999694824,3.10000610352 0.0,4.19999694824 c 0.0,0.0 24.0,24.0000152588 24.0,24.0000152588 c 1.19999694824,1.19999694824 3.10000610352,1.19999694824 4.19999694824,0.0 c 0.0,0.0 12.6999969482,-12.700012207 12.6999969482,-12.700012207 c 1.20001220703,-1.19999694824 1.20001220703,-3.09999084473 0.0,-4.19999694824 c 0.0,0.0 -23.8999938965,-24.0 -23.8999938965,-24.0 Z M 2.84999084473,15.5500183105 c 0.0,0.0 -18.6000061035,-18.5000457764 -18.6000061035,-18.5000457764 c 0.0,0.0 12.5999908447,-12.8000030518 12.5999908447,-12.8000030518 c 0.0,0.0 18.6000213623,18.5000457764 18.6000213623,18.5000457764 c 0.0,0.0 -12.6000061035,12.8000030518 -12.6000061035,12.8000030518 Z"
- android:valueType="pathType"
- android:interpolator="@android:interpolator/fast_out_slow_in" />
- <objectAnimator
- android:duration="217"
- android:propertyName="pathData"
- android:valueFrom="M -3.5,-20.5 c -1.19999694824,-1.19999694824 -3.10000610352,-1.19999694824 -4.19999694824,0.0 c 0.0,0.0 -12.8000030518,12.6999969482 -12.8000030518,12.6999969482 c -1.19999694824,1.19999694824 -1.19999694824,3.10000610352 0.0,4.19999694824 c 0.0,0.0 24.0,24.0000152588 24.0,24.0000152588 c 1.19999694824,1.19999694824 3.10000610352,1.19999694824 4.19999694824,0.0 c 0.0,0.0 12.6999969482,-12.700012207 12.6999969482,-12.700012207 c 1.20001220703,-1.19999694824 1.20001220703,-3.09999084473 0.0,-4.19999694824 c 0.0,0.0 -23.8999938965,-24.0 -23.8999938965,-24.0 Z M 2.84999084473,15.5500183105 c 0.0,0.0 -18.6000061035,-18.5000457764 -18.6000061035,-18.5000457764 c 0.0,0.0 12.5999908447,-12.8000030518 12.5999908447,-12.8000030518 c 0.0,0.0 18.6000213623,18.5000457764 18.6000213623,18.5000457764 c 0.0,0.0 -12.6000061035,12.8000030518 -12.6000061035,12.8000030518 Z"
- android:valueTo="M -3.34053039551,-22.9980926514 c -1.3207244873,-1.3207244873 -3.46876525879,-1.26383972168 -4.74829101563,0.125762939453 c 0.0,0.0 -14.8512420654,14.7411804199 -14.8512420654,14.7411804199 c -1.39259338379,1.392578125 -1.44947814941,3.54061889648 -0.125762939453,4.74827575684 c 0.0,0.0 26.4143981934,26.4144134521 26.4143981934,26.4144134521 c 1.3207244873,1.3207244873 3.46876525879,1.26382446289 4.74829101562,-0.125762939453 c 0.0,0.0 14.7381896973,-14.7381896973 14.7381896973,-14.7381896973 c 1.392578125,-1.39259338379 1.44947814941,-3.54061889648 0.125762939453,-4.74829101562 c 0.0,0.0 -26.3013458252,-26.417388916 -26.3013458252,-26.417388916 Z M 2.87156677246,16.9857940674 c 0.0,0.0 -19.7573547363,-19.7573699951 -19.7573547363,-19.7573699951 c 0.0,0.0 14.0142059326,-14.2142181396 14.0142059326,-14.2142181396 c 0.0,0.0 19.7573699951,19.7573699951 19.7573699951,19.7573699951 c 0.0,0.0 -14.0142211914,14.2142181396 -14.0142211914,14.2142181396 Z"
- android:valueType="pathType"
- android:interpolator="@android:interpolator/fast_out_slow_in" />
- </set>
-</set>
diff --git a/packages/SystemUI/res/anim/ic_landscape_to_auto_rotate_animation_arrow_top.xml b/packages/SystemUI/res/anim/ic_landscape_to_auto_rotate_animation_arrow_top.xml
deleted file mode 100644
index fa10b119..0000000
--- a/packages/SystemUI/res/anim/ic_landscape_to_auto_rotate_animation_arrow_top.xml
+++ /dev/null
@@ -1,33 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
- 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.
--->
-<set xmlns:android="http://schemas.android.com/apk/res/android" >
- <set
- android:ordering="sequentially" >
- <objectAnimator
- android:duration="50"
- android:propertyName="fillAlpha"
- android:valueFrom="0"
- android:valueTo="0"
- android:interpolator="@android:interpolator/linear" />
- <objectAnimator
- android:duration="33"
- android:propertyName="fillAlpha"
- android:valueFrom="0"
- android:valueTo="1"
- android:interpolator="@android:interpolator/linear" />
- </set>
-</set>
diff --git a/packages/SystemUI/res/anim/ic_landscape_to_auto_rotate_animation_arrows.xml b/packages/SystemUI/res/anim/ic_landscape_to_auto_rotate_animation_arrows.xml
deleted file mode 100644
index caae73a..0000000
--- a/packages/SystemUI/res/anim/ic_landscape_to_auto_rotate_animation_arrows.xml
+++ /dev/null
@@ -1,36 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
- 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.
--->
-<set xmlns:android="http://schemas.android.com/apk/res/android" >
- <objectAnimator
- android:duration="333"
- android:propertyName="scaleX"
- android:valueFrom="0.9"
- android:valueTo="1"
- android:interpolator="@android:interpolator/linear" />
- <objectAnimator
- android:duration="333"
- android:propertyName="scaleY"
- android:valueFrom="0.9"
- android:valueTo="1"
- android:interpolator="@android:interpolator/linear" />
- <objectAnimator
- android:duration="450"
- android:propertyName="rotation"
- android:valueFrom="-135"
- android:valueTo="0"
- android:interpolator="@interpolator/ic_landscape_to_auto_rotate_arrows_rotation_interpolator" />
-</set>
diff --git a/packages/SystemUI/res/anim/ic_landscape_to_auto_rotate_animation_body.xml b/packages/SystemUI/res/anim/ic_landscape_to_auto_rotate_animation_body.xml
deleted file mode 100644
index aa22c3b..0000000
--- a/packages/SystemUI/res/anim/ic_landscape_to_auto_rotate_animation_body.xml
+++ /dev/null
@@ -1,35 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
- 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.
--->
-<set xmlns:android="http://schemas.android.com/apk/res/android" >
- <set
- android:ordering="sequentially" >
- <objectAnimator
- android:duration="67"
- android:propertyName="pathData"
- android:valueFrom="M -3.34053039551,-22.9980926514 c -1.3207244873,-1.3207244873 -3.46876525879,-1.26383972168 -4.74829101563,0.125762939453 c 0.0,0.0 -14.8512420654,14.7411804199 -14.8512420654,14.7411804199 c -1.39259338379,1.392578125 -1.44947814941,3.54061889648 -0.125762939453,4.74827575684 c 0.0,0.0 26.4143981934,26.4144134521 26.4143981934,26.4144134521 c 1.3207244873,1.3207244873 3.46876525879,1.26382446289 4.74829101562,-0.125762939453 c 0.0,0.0 14.7381896973,-14.7381896973 14.7381896973,-14.7381896973 c 1.392578125,-1.39259338379 1.44947814941,-3.54061889648 0.125762939453,-4.74829101562 c 0.0,0.0 -26.3013458252,-26.417388916 -26.3013458252,-26.417388916 Z M 2.87156677246,16.9857940674 c 0.0,0.0 -19.7573547363,-19.7573699951 -19.7573547363,-19.7573699951 c 0.0,0.0 14.0142059326,-14.2142181396 14.0142059326,-14.2142181396 c 0.0,0.0 19.7573699951,19.7573699951 19.7573699951,19.7573699951 c 0.0,0.0 -14.0142211914,14.2142181396 -14.0142211914,14.2142181396 Z"
- android:valueTo="M -3.34053039551,-22.9980926514 c -1.3207244873,-1.3207244873 -3.46876525879,-1.26383972168 -4.74829101563,0.125762939453 c 0.0,0.0 -14.8512420654,14.7411804199 -14.8512420654,14.7411804199 c -1.39259338379,1.392578125 -1.44947814941,3.54061889648 -0.125762939453,4.74827575684 c 0.0,0.0 26.4143981934,26.4144134521 26.4143981934,26.4144134521 c 1.3207244873,1.3207244873 3.46876525879,1.26382446289 4.74829101562,-0.125762939453 c 0.0,0.0 14.7381896973,-14.7381896973 14.7381896973,-14.7381896973 c 1.392578125,-1.39259338379 1.44947814941,-3.54061889648 0.125762939453,-4.74829101562 c 0.0,0.0 -26.3013458252,-26.417388916 -26.3013458252,-26.417388916 Z M 2.87156677246,16.9857940674 c 0.0,0.0 -19.7573547363,-19.7573699951 -19.7573547363,-19.7573699951 c 0.0,0.0 14.0142059326,-14.2142181396 14.0142059326,-14.2142181396 c 0.0,0.0 19.7573699951,19.7573699951 19.7573699951,19.7573699951 c 0.0,0.0 -14.0142211914,14.2142181396 -14.0142211914,14.2142181396 Z"
- android:valueType="pathType"
- android:interpolator="@android:interpolator/fast_out_slow_in" />
- <objectAnimator
- android:duration="217"
- android:propertyName="pathData"
- android:valueFrom="M -3.34053039551,-22.9980926514 c -1.3207244873,-1.3207244873 -3.46876525879,-1.26383972168 -4.74829101563,0.125762939453 c 0.0,0.0 -14.8512420654,14.7411804199 -14.8512420654,14.7411804199 c -1.39259338379,1.392578125 -1.44947814941,3.54061889648 -0.125762939453,4.74827575684 c 0.0,0.0 26.4143981934,26.4144134521 26.4143981934,26.4144134521 c 1.3207244873,1.3207244873 3.46876525879,1.26382446289 4.74829101562,-0.125762939453 c 0.0,0.0 14.7381896973,-14.7381896973 14.7381896973,-14.7381896973 c 1.392578125,-1.39259338379 1.44947814941,-3.54061889648 0.125762939453,-4.74829101562 c 0.0,0.0 -26.3013458252,-26.417388916 -26.3013458252,-26.417388916 Z M 2.87156677246,16.9857940674 c 0.0,0.0 -19.7573547363,-19.7573699951 -19.7573547363,-19.7573699951 c 0.0,0.0 14.0142059326,-14.2142181396 14.0142059326,-14.2142181396 c 0.0,0.0 19.7573699951,19.7573699951 19.7573699951,19.7573699951 c 0.0,0.0 -14.0142211914,14.2142181396 -14.0142211914,14.2142181396 Z"
- android:valueTo="M -3.5,-20.5 c -1.19999694824,-1.19999694824 -3.10000610352,-1.19999694824 -4.19999694824,0.0 c 0.0,0.0 -12.8000030518,12.6999969482 -12.8000030518,12.6999969482 c -1.19999694824,1.19999694824 -1.19999694824,3.10000610352 0.0,4.19999694824 c 0.0,0.0 24.0,24.0000152588 24.0,24.0000152588 c 1.19999694824,1.19999694824 3.10000610352,1.19999694824 4.19999694824,0.0 c 0.0,0.0 12.6999969482,-12.700012207 12.6999969482,-12.700012207 c 1.20001220703,-1.19999694824 1.20001220703,-3.09999084473 0.0,-4.19999694824 c 0.0,0.0 -23.8999938965,-24.0 -23.8999938965,-24.0 Z M 2.84999084473,15.5500183105 c 0.0,0.0 -18.6000061035,-18.5000457764 -18.6000061035,-18.5000457764 c 0.0,0.0 12.5999908447,-12.8000030518 12.5999908447,-12.8000030518 c 0.0,0.0 18.6000213623,18.5000457764 18.6000213623,18.5000457764 c 0.0,0.0 -12.6000061035,12.8000030518 -12.6000061035,12.8000030518 Z"
- android:valueType="pathType"
- android:interpolator="@android:interpolator/fast_out_slow_in" />
- </set>
-</set>
diff --git a/packages/SystemUI/res/anim/ic_landscape_to_auto_rotate_animation_device.xml b/packages/SystemUI/res/anim/ic_landscape_to_auto_rotate_animation_device.xml
deleted file mode 100644
index 2530f08..0000000
--- a/packages/SystemUI/res/anim/ic_landscape_to_auto_rotate_animation_device.xml
+++ /dev/null
@@ -1,24 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
- 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.
--->
-<set xmlns:android="http://schemas.android.com/apk/res/android" >
- <objectAnimator
- android:duration="400"
- android:propertyName="rotation"
- android:valueFrom="-45"
- android:valueTo="0"
- android:interpolator="@android:interpolator/fast_out_slow_in" />
-</set>
diff --git a/packages/SystemUI/res/anim/ic_landscape_from_auto_rotate_animation_device.xml b/packages/SystemUI/res/anim/ic_landscape_to_rotate_arrows_animation.xml
similarity index 74%
rename from packages/SystemUI/res/anim/ic_landscape_from_auto_rotate_animation_device.xml
rename to packages/SystemUI/res/anim/ic_landscape_to_rotate_arrows_animation.xml
index 27fd653..8fdad80 100644
--- a/packages/SystemUI/res/anim/ic_landscape_from_auto_rotate_animation_device.xml
+++ b/packages/SystemUI/res/anim/ic_landscape_to_rotate_arrows_animation.xml
@@ -1,6 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
- Copyright (C) 2014 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,11 +14,13 @@
See the License for the specific language governing permissions and
limitations under the License.
-->
-<set xmlns:android="http://schemas.android.com/apk/res/android" >
+<set
+ xmlns:android="http://schemas.android.com/apk/res/android" >
<objectAnimator
- android:duration="400"
+ android:duration="616"
android:propertyName="rotation"
- android:valueFrom="0"
- android:valueTo="-45"
+ android:valueFrom="-90.0"
+ android:valueTo="0.0"
+ android:valueType="floatType"
android:interpolator="@android:interpolator/fast_out_slow_in" />
</set>
diff --git a/packages/SystemUI/res/anim/ic_landscape_to_auto_rotate_animation_arrow_bottom.xml b/packages/SystemUI/res/anim/ic_landscape_to_rotate_bottom_merged_animation.xml
similarity index 71%
rename from packages/SystemUI/res/anim/ic_landscape_to_auto_rotate_animation_arrow_bottom.xml
rename to packages/SystemUI/res/anim/ic_landscape_to_rotate_bottom_merged_animation.xml
index fa10b119..3c3c131 100644
--- a/packages/SystemUI/res/anim/ic_landscape_to_auto_rotate_animation_arrow_bottom.xml
+++ b/packages/SystemUI/res/anim/ic_landscape_to_rotate_bottom_merged_animation.xml
@@ -1,6 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
- Copyright (C) 2014 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,20 +14,23 @@
See the License for the specific language governing permissions and
limitations under the License.
-->
-<set xmlns:android="http://schemas.android.com/apk/res/android" >
+<set
+ xmlns:android="http://schemas.android.com/apk/res/android" >
<set
android:ordering="sequentially" >
<objectAnimator
android:duration="50"
android:propertyName="fillAlpha"
- android:valueFrom="0"
- android:valueTo="0"
+ android:valueFrom="0.0"
+ android:valueTo="0.0"
+ android:valueType="floatType"
android:interpolator="@android:interpolator/linear" />
<objectAnimator
- android:duration="33"
+ android:duration="83"
android:propertyName="fillAlpha"
- android:valueFrom="0"
- android:valueTo="1"
+ android:valueFrom="0.0"
+ android:valueTo="1.0"
+ android:valueType="floatType"
android:interpolator="@android:interpolator/linear" />
</set>
</set>
diff --git a/packages/SystemUI/res/anim/ic_landscape_to_rotate_landscape_animation.xml b/packages/SystemUI/res/anim/ic_landscape_to_rotate_landscape_animation.xml
new file mode 100644
index 0000000..57132e1
--- /dev/null
+++ b/packages/SystemUI/res/anim/ic_landscape_to_rotate_landscape_animation.xml
@@ -0,0 +1,50 @@
+<?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.
+-->
+<set
+ xmlns:android="http://schemas.android.com/apk/res/android" >
+ <objectAnimator
+ android:duration="466"
+ android:propertyName="scaleX"
+ android:valueFrom="1.0"
+ android:valueTo="0.909"
+ android:valueType="floatType"
+ android:interpolator="@interpolator/ic_landscape_to_rotate_animation_interpolator_0" />
+ <objectAnimator
+ android:duration="466"
+ android:propertyName="scaleY"
+ android:valueFrom="1.0"
+ android:valueTo="0.909"
+ android:valueType="floatType"
+ android:interpolator="@interpolator/ic_landscape_to_rotate_animation_interpolator_0" />
+ <set
+ android:ordering="sequentially" >
+ <objectAnimator
+ android:duration="50"
+ android:propertyName="rotation"
+ android:valueFrom="0.0"
+ android:valueTo="0.0"
+ android:valueType="floatType"
+ android:interpolator="@android:interpolator/linear" />
+ <objectAnimator
+ android:duration="400"
+ android:propertyName="rotation"
+ android:valueFrom="0.0"
+ android:valueTo="45.0"
+ android:valueType="floatType"
+ android:interpolator="@android:interpolator/fast_out_slow_in" />
+ </set>
+</set>
diff --git a/packages/SystemUI/res/anim/ic_landscape_from_auto_rotate_animation_arrows.xml b/packages/SystemUI/res/anim/ic_rotate_to_landscape_arrows_0_animation.xml
similarity index 68%
rename from packages/SystemUI/res/anim/ic_landscape_from_auto_rotate_animation_arrows.xml
rename to packages/SystemUI/res/anim/ic_rotate_to_landscape_arrows_0_animation.xml
index 5c37479..ad2a5fa 100644
--- a/packages/SystemUI/res/anim/ic_landscape_from_auto_rotate_animation_arrows.xml
+++ b/packages/SystemUI/res/anim/ic_rotate_to_landscape_arrows_0_animation.xml
@@ -1,6 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
- Copyright (C) 2014 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,41 +14,40 @@
See the License for the specific language governing permissions and
limitations under the License.
-->
-<set xmlns:android="http://schemas.android.com/apk/res/android" >
+<set
+ xmlns:android="http://schemas.android.com/apk/res/android" >
<set
android:ordering="sequentially" >
<objectAnimator
- android:duration="117"
+ android:duration="116"
android:propertyName="scaleX"
- android:valueFrom="1"
- android:valueTo="1"
+ android:valueFrom="1.0"
+ android:valueTo="1.0"
+ android:valueType="floatType"
android:interpolator="@android:interpolator/linear" />
<objectAnimator
android:duration="333"
android:propertyName="scaleX"
- android:valueFrom="1"
+ android:valueFrom="1.0"
android:valueTo="0.9"
+ android:valueType="floatType"
android:interpolator="@android:interpolator/linear" />
</set>
<set
android:ordering="sequentially" >
<objectAnimator
- android:duration="117"
+ android:duration="116"
android:propertyName="scaleY"
- android:valueFrom="1"
- android:valueTo="1"
+ android:valueFrom="1.0"
+ android:valueTo="1.0"
+ android:valueType="floatType"
android:interpolator="@android:interpolator/linear" />
<objectAnimator
android:duration="333"
android:propertyName="scaleY"
- android:valueFrom="1"
+ android:valueFrom="1.0"
android:valueTo="0.9"
+ android:valueType="floatType"
android:interpolator="@android:interpolator/linear" />
</set>
- <objectAnimator
- android:duration="450"
- android:propertyName="rotation"
- android:valueFrom="0"
- android:valueTo="-135"
- android:interpolator="@interpolator/ic_landscape_from_auto_rotate_arrows_rotation_interpolator" />
</set>
diff --git a/packages/SystemUI/res/anim/ic_landscape_from_auto_rotate_animation_device.xml b/packages/SystemUI/res/anim/ic_rotate_to_landscape_arrows_animation.xml
similarity index 74%
copy from packages/SystemUI/res/anim/ic_landscape_from_auto_rotate_animation_device.xml
copy to packages/SystemUI/res/anim/ic_rotate_to_landscape_arrows_animation.xml
index 27fd653..c152152 100644
--- a/packages/SystemUI/res/anim/ic_landscape_from_auto_rotate_animation_device.xml
+++ b/packages/SystemUI/res/anim/ic_rotate_to_landscape_arrows_animation.xml
@@ -1,6 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
- Copyright (C) 2014 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,11 +14,13 @@
See the License for the specific language governing permissions and
limitations under the License.
-->
-<set xmlns:android="http://schemas.android.com/apk/res/android" >
+<set
+ xmlns:android="http://schemas.android.com/apk/res/android" >
<objectAnimator
- android:duration="400"
+ android:duration="616"
android:propertyName="rotation"
- android:valueFrom="0"
- android:valueTo="-45"
+ android:valueFrom="0.0"
+ android:valueTo="-180.0"
+ android:valueType="floatType"
android:interpolator="@android:interpolator/fast_out_slow_in" />
</set>
diff --git a/packages/SystemUI/res/anim/ic_landscape_to_auto_rotate_animation_arrow_bottom.xml b/packages/SystemUI/res/anim/ic_rotate_to_landscape_bottom_merged_animation.xml
similarity index 69%
copy from packages/SystemUI/res/anim/ic_landscape_to_auto_rotate_animation_arrow_bottom.xml
copy to packages/SystemUI/res/anim/ic_rotate_to_landscape_bottom_merged_animation.xml
index fa10b119..b2c1eb8 100644
--- a/packages/SystemUI/res/anim/ic_landscape_to_auto_rotate_animation_arrow_bottom.xml
+++ b/packages/SystemUI/res/anim/ic_rotate_to_landscape_bottom_merged_animation.xml
@@ -1,6 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
- Copyright (C) 2014 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,20 +14,23 @@
See the License for the specific language governing permissions and
limitations under the License.
-->
-<set xmlns:android="http://schemas.android.com/apk/res/android" >
+<set
+ xmlns:android="http://schemas.android.com/apk/res/android" >
<set
android:ordering="sequentially" >
<objectAnimator
- android:duration="50"
+ android:duration="200"
android:propertyName="fillAlpha"
- android:valueFrom="0"
- android:valueTo="0"
+ android:valueFrom="1.0"
+ android:valueTo="1.0"
+ android:valueType="floatType"
android:interpolator="@android:interpolator/linear" />
<objectAnimator
- android:duration="33"
+ android:duration="83"
android:propertyName="fillAlpha"
- android:valueFrom="0"
- android:valueTo="1"
+ android:valueFrom="1.0"
+ android:valueTo="0.0"
+ android:valueType="floatType"
android:interpolator="@android:interpolator/linear" />
</set>
</set>
diff --git a/packages/SystemUI/res/anim/ic_rotate_to_landscape_landscape_animation.xml b/packages/SystemUI/res/anim/ic_rotate_to_landscape_landscape_animation.xml
new file mode 100644
index 0000000..2a9bbe3
--- /dev/null
+++ b/packages/SystemUI/res/anim/ic_rotate_to_landscape_landscape_animation.xml
@@ -0,0 +1,60 @@
+<?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.
+-->
+<set
+ xmlns:android="http://schemas.android.com/apk/res/android" >
+ <set
+ android:ordering="sequentially" >
+ <objectAnimator
+ android:duration="116"
+ android:propertyName="scaleX"
+ android:valueFrom="0.909"
+ android:valueTo="0.909"
+ android:valueType="floatType"
+ android:interpolator="@android:interpolator/linear" />
+ <objectAnimator
+ android:duration="166"
+ android:propertyName="scaleX"
+ android:valueFrom="0.909"
+ android:valueTo="1.0"
+ android:valueType="floatType"
+ android:interpolator="@interpolator/ic_rotate_to_landscape_animation_interpolator_0" />
+ </set>
+ <set
+ android:ordering="sequentially" >
+ <objectAnimator
+ android:duration="116"
+ android:propertyName="scaleY"
+ android:valueFrom="0.909"
+ android:valueTo="0.909"
+ android:valueType="floatType"
+ android:interpolator="@android:interpolator/linear" />
+ <objectAnimator
+ android:duration="166"
+ android:propertyName="scaleY"
+ android:valueFrom="0.909"
+ android:valueTo="1.0"
+ android:valueType="floatType"
+ android:interpolator="@interpolator/ic_rotate_to_landscape_animation_interpolator_0" />
+ </set>
+ <objectAnimator
+ android:duration="616"
+ android:propertyName="rotation"
+ android:valueFrom="45.0"
+ android:valueTo="0.0"
+ android:valueType="floatType"
+ android:interpolator="@android:interpolator/fast_out_slow_in" />
+</set>
diff --git a/packages/SystemUI/res/drawable/brightness_mirror_background.xml b/packages/SystemUI/res/drawable/brightness_mirror_background.xml
index 0c69d89..b3a0484 100644
--- a/packages/SystemUI/res/drawable/brightness_mirror_background.xml
+++ b/packages/SystemUI/res/drawable/brightness_mirror_background.xml
@@ -15,5 +15,5 @@
~ limitations under the License
-->
<shape xmlns:android="http://schemas.android.com/apk/res/android">
- <solid android:color="?android:attr/colorPrimary" />
+ <solid android:color="@color/qs_background_dark" />
</shape>
diff --git a/packages/SystemUI/res/drawable/ic_landscape_from_auto_rotate.xml b/packages/SystemUI/res/drawable/ic_landscape_from_auto_rotate.xml
index 8b2585b..061f9fe 100644
--- a/packages/SystemUI/res/drawable/ic_landscape_from_auto_rotate.xml
+++ b/packages/SystemUI/res/drawable/ic_landscape_from_auto_rotate.xml
@@ -1,6 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
- Copyright (C) 2014 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,49 +14,52 @@
See the License for the specific language governing permissions and
limitations under the License.
-->
-<vector xmlns:android="http://schemas.android.com/apk/res/android"
+<vector
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ android:name="ic_rotate_to_landscape"
android:height="48dp"
android:width="48dp"
android:viewportHeight="48"
android:viewportWidth="48"
android:tint="?android:attr/colorControlNormal" >
<group
- android:name="ic_screen_rotation_48px_outlines"
+ android:name="device"
android:translateX="24"
android:translateY="24" >
<group
- android:name="ic_screen_rotation_48px_outlines_pivot"
+ android:name="device_pivot"
android:translateX="-24.15"
android:translateY="-24.25" >
<group
- android:name="arrows"
- android:translateX="24.1"
- android:translateY="24.1" >
- <group
- android:name="arrows_pivot"
- android:translateX="-24.1"
- android:translateY="-24.1" >
- <path
- android:name="arrow_top"
- android:pathData="M 33.1499938965,5.25 c 6.5,3.10000610352 11.1999969482,9.40000915527 11.8999938965,17.0 c 0.0,0.0 3.00001525879,0.0 3.00001525879,0.0 c -1.00001525879,-12.3000030518 -11.3000030518,-22.0 -23.9000091553,-22.0 c -0.399993896484,0.0 -0.899993896484,0.0 -1.30000305176,0.100006103516 c 0.0,0.0 7.60000610352,7.59999084473 7.60000610352,7.59999084473 c 0.0,0.0 2.69999694824,-2.69999694824 2.69999694824,-2.69999694824 Z"
- android:fillColor="#FFFFFFFF"
- android:fillAlpha="1" />
- <path
- android:name="arrow_bottom"
- android:pathData="M 15.1499938965,43.25 c -6.5,-3.09999084473 -11.1999969482,-9.5 -11.8999938965,-17.0 c 0.0,0.0 -3.0,0.0 -3.0,0.0 c 1.0,12.3000030518 11.299987793,22.0 23.8999938965,22.0 c 0.399993896484,0.0 0.899993896484,0.0 1.30000305176,-0.0999908447266 c 0.0,0.0 -7.60000610352,-7.60000610352 -7.60000610352,-7.60000610352 c 0.0,0.0 -2.69999694824,2.69999694824 -2.69999694824,2.69999694824 Z"
- android:fillColor="#FFFFFFFF"
- android:fillAlpha="1" />
- </group>
- </group>
- <group
- android:name="device"
- android:translateX="24.14999"
- android:translateY="24.25" >
+ android:name="landscape"
+ android:translateX="24"
+ android:translateY="24"
+ android:scaleX="0.909"
+ android:scaleY="0.909"
+ android:rotation="45" >
<path
- android:name="body"
- android:pathData="M -3.5,-20.5 c -1.19999694824,-1.19999694824 -3.10000610352,-1.19999694824 -4.19999694824,0.0 c 0.0,0.0 -12.8000030518,12.6999969482 -12.8000030518,12.6999969482 c -1.19999694824,1.19999694824 -1.19999694824,3.10000610352 0.0,4.19999694824 c 0.0,0.0 24.0,24.0000152588 24.0,24.0000152588 c 1.19999694824,1.19999694824 3.10000610352,1.19999694824 4.19999694824,0.0 c 0.0,0.0 12.6999969482,-12.700012207 12.6999969482,-12.700012207 c 1.20001220703,-1.19999694824 1.20001220703,-3.09999084473 0.0,-4.19999694824 c 0.0,0.0 -23.8999938965,-24.0 -23.8999938965,-24.0 Z M 2.84999084473,15.5500183105 c 0.0,0.0 -18.6000061035,-18.5000457764 -18.6000061035,-18.5000457764 c 0.0,0.0 12.5999908447,-12.8000030518 12.5999908447,-12.8000030518 c 0.0,0.0 18.6000213623,18.5000457764 18.6000213623,18.5000457764 c 0.0,0.0 -12.6000061035,12.8000030518 -12.6000061035,12.8000030518 Z"
- android:fillColor="#FFFFFFFF"
- android:fillAlpha="1" />
+ android:name="device_merged"
+ android:pathData="M -21.9799957275,-10.0 c 0.0,0.0 -0.0200042724609,20.0 -0.0200042724609,20.0 c 0.0,2.19999694824 1.80000305176,4.0 4.0,4.0 c 0.0,0.0 36.0,0.0 36.0,0.0 c 2.19999694824,0.0 4.0,-1.80000305176 4.0,-4.0 c 0.0,0.0 0.0,-20.0 0.0,-20.0 c 0.0,-2.19999694824 -1.80000305176,-4.0 -4.0,-4.0 c 0.0,0.0 -36.0,0.0 -36.0,0.0 c -2.19999694824,0.0 -3.97999572754,1.80000305176 -3.97999572754,4.0 Z M 14.0,10.0 c 0.0,0.0 -28.0,0.0 -28.0,0.0 c 0.0,0.0 0.0,-20.0 0.0,-20.0 c 0.0,0.0 28.0,0.0 28.0,0.0 c 0.0,0.0 0.0,20.0 0.0,20.0 Z"
+ android:fillColor="#FFFFFFFF" />
+ </group>
+ </group>
+ </group>
+ <group
+ android:name="arrows"
+ android:translateX="24"
+ android:translateY="24" >
+ <group
+ android:name="arrows_pivot"
+ android:translateX="-24.0798"
+ android:translateY="-24.23" >
+ <group
+ android:name="arrows_0"
+ android:translateX="12.2505"
+ android:translateY="37.2145" >
+ <path
+ android:name="bottom_merged"
+ android:pathData="M 20.7395019531,-31.9844970703 c 6.23999023438,2.83999633789 10.6999969482,8.7200012207 11.8399963379,15.7799987793 c 0.119995117188,0.699996948242 0.740005493164,1.2200012207 1.46099853516,1.2200012207 c 0.919998168945,0.0 1.6190032959,-0.84001159668 1.47900390625,-1.74000549316 c -1.75900268555,-10.3800048828 -9.75900268555,-19.1199951172 -22.5800018311,-20.1600036621 c -0.919998168945,-0.0800018310547 -1.43899536133,1.04000854492 -0.800003051758,1.70001220703 c 0.0,0.0 5.12100219727,5.11999511719 5.12100219727,5.11999511719 c 0.378997802734,0.380004882812 0.97900390625,0.380004882812 1.37899780273,0.020004272461 c 0.0,0.0 2.10000610352,-1.94000244141 2.10000610352,-1.94000244141 Z M 2.73950195312,6.01550292969 c -6.26000976562,-2.83999633789 -10.7200012207,-8.76000976562 -11.8399963379,-15.8600006104 c -0.118011474609,-0.667007446289 -0.702011108398,-1.15100097656 -1.38000488281,-1.13999938965 c -0.860000610352,0.0 -1.52000427246,0.759994506836 -1.38000488281,1.61999511719 c 1.54000854492,10.4000091553 9.5,19.2200012207 22.4199981689,20.2799987793 c 0.920013427734,0.0800018310547 1.44100952148,-1.03999328613 0.800003051758,-1.69999694824 c 0.0,0.0 -5.11999511719,-5.11999511719 -5.11999511719,-5.11999511719 c -0.380004882812,-0.376007080078 -0.988998413086,-0.385009765625 -1.38000488281,-0.0200042724609 c 0.0,0.0 -2.11999511719,1.94000244141 -2.11999511719,1.94000244141 Z"
+ android:fillColor="#FFFFFFFF" />
</group>
</group>
</group>
diff --git a/packages/SystemUI/res/drawable/ic_landscape_from_auto_rotate_animation.xml b/packages/SystemUI/res/drawable/ic_landscape_from_auto_rotate_animation.xml
index 400a28b..00bcaf6 100644
--- a/packages/SystemUI/res/drawable/ic_landscape_from_auto_rotate_animation.xml
+++ b/packages/SystemUI/res/drawable/ic_landscape_from_auto_rotate_animation.xml
@@ -1,6 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
- Copyright (C) 2014 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,21 +14,19 @@
See the License for the specific language governing permissions and
limitations under the License.
-->
-<animated-vector xmlns:android="http://schemas.android.com/apk/res/android"
+<animated-vector
+ xmlns:android="http://schemas.android.com/apk/res/android"
android:drawable="@drawable/ic_landscape_from_auto_rotate" >
<target
+ android:name="landscape"
+ android:animation="@anim/ic_rotate_to_landscape_landscape_animation" />
+ <target
android:name="arrows"
- android:animation="@anim/ic_landscape_from_auto_rotate_animation_arrows" />
+ android:animation="@anim/ic_rotate_to_landscape_arrows_animation" />
<target
- android:name="arrow_top"
- android:animation="@anim/ic_landscape_from_auto_rotate_animation_arrow_top" />
+ android:name="arrows_0"
+ android:animation="@anim/ic_rotate_to_landscape_arrows_0_animation" />
<target
- android:name="arrow_bottom"
- android:animation="@anim/ic_landscape_from_auto_rotate_animation_arrow_bottom" />
- <target
- android:name="device"
- android:animation="@anim/ic_landscape_from_auto_rotate_animation_device" />
- <target
- android:name="body"
- android:animation="@anim/ic_landscape_from_auto_rotate_animation_body" />
+ android:name="bottom_merged"
+ android:animation="@anim/ic_rotate_to_landscape_bottom_merged_animation" />
</animated-vector>
diff --git a/packages/SystemUI/res/drawable/ic_landscape_to_auto_rotate.xml b/packages/SystemUI/res/drawable/ic_landscape_to_auto_rotate.xml
index 603d0bf..cde6797 100644
--- a/packages/SystemUI/res/drawable/ic_landscape_to_auto_rotate.xml
+++ b/packages/SystemUI/res/drawable/ic_landscape_to_auto_rotate.xml
@@ -1,6 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
- Copyright (C) 2014 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,53 +14,51 @@
See the License for the specific language governing permissions and
limitations under the License.
-->
-<vector xmlns:android="http://schemas.android.com/apk/res/android"
+<vector
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ android:name="ic_landscape_to_rotate"
android:height="48dp"
android:width="48dp"
android:viewportHeight="48"
android:viewportWidth="48"
android:tint="?android:attr/colorControlNormal" >
<group
- android:name="ic_screen_rotation_48px_outlines"
+ android:name="device"
android:translateX="24"
android:translateY="24" >
<group
- android:name="ic_screen_rotation_48px_outlines_pivot"
+ android:name="device_pivot"
android:translateX="-24.15"
android:translateY="-24.25" >
<group
- android:name="arrows"
- android:translateX="24.1"
- android:translateY="24.1"
- android:scaleX="0.9"
- android:scaleY="0.9"
- android:rotation="-135" >
- <group
- android:name="arrows_pivot"
- android:translateX="-24.1"
- android:translateY="-24.1" >
- <path
- android:name="arrow_top"
- android:pathData="M 33.1499938965,5.25 c 6.5,3.10000610352 11.1999969482,9.40000915527 11.8999938965,17.0 c 0.0,0.0 3.00001525879,0.0 3.00001525879,0.0 c -1.00001525879,-12.3000030518 -11.3000030518,-22.0 -23.9000091553,-22.0 c -0.399993896484,0.0 -0.899993896484,0.0 -1.30000305176,0.100006103516 c 0.0,0.0 7.60000610352,7.59999084473 7.60000610352,7.59999084473 c 0.0,0.0 2.69999694824,-2.69999694824 2.69999694824,-2.69999694824 Z"
- android:fillColor="#FFFFFFFF"
- android:fillAlpha="0" />
- <path
- android:name="arrow_bottom"
- android:pathData="M 15.1499938965,43.25 c -6.5,-3.09999084473 -11.1999969482,-9.5 -11.8999938965,-17.0 c 0.0,0.0 -3.0,0.0 -3.0,0.0 c 1.0,12.3000030518 11.299987793,22.0 23.8999938965,22.0 c 0.399993896484,0.0 0.899993896484,0.0 1.30000305176,-0.0999908447266 c 0.0,0.0 -7.60000610352,-7.60000610352 -7.60000610352,-7.60000610352 c 0.0,0.0 -2.69999694824,2.69999694824 -2.69999694824,2.69999694824 Z"
- android:fillColor="#FFFFFFFF"
- android:fillAlpha="0" />
- </group>
- </group>
- <group
- android:name="device"
- android:translateX="24.14999"
- android:translateY="24.25"
- android:rotation="-45" >
+ android:name="landscape"
+ android:translateX="24"
+ android:translateY="24" >
<path
- android:name="body"
- android:pathData="M -3.34053039551,-22.9980926514 c -1.3207244873,-1.3207244873 -3.46876525879,-1.26383972168 -4.74829101563,0.125762939453 c 0.0,0.0 -14.8512420654,14.7411804199 -14.8512420654,14.7411804199 c -1.39259338379,1.392578125 -1.44947814941,3.54061889648 -0.125762939453,4.74827575684 c 0.0,0.0 26.4143981934,26.4144134521 26.4143981934,26.4144134521 c 1.3207244873,1.3207244873 3.46876525879,1.26382446289 4.74829101562,-0.125762939453 c 0.0,0.0 14.7381896973,-14.7381896973 14.7381896973,-14.7381896973 c 1.392578125,-1.39259338379 1.44947814941,-3.54061889648 0.125762939453,-4.74829101562 c 0.0,0.0 -26.3013458252,-26.417388916 -26.3013458252,-26.417388916 Z M 2.87156677246,16.9857940674 c 0.0,0.0 -19.7573547363,-19.7573699951 -19.7573547363,-19.7573699951 c 0.0,0.0 14.0142059326,-14.2142181396 14.0142059326,-14.2142181396 c 0.0,0.0 19.7573699951,19.7573699951 19.7573699951,19.7573699951 c 0.0,0.0 -14.0142211914,14.2142181396 -14.0142211914,14.2142181396 Z"
+ android:name="device_merged"
+ android:pathData="M -21.9799957275,-10.0 c 0.0,0.0 -0.0200042724609,20.0 -0.0200042724609,20.0 c 0.0,2.19999694824 1.80000305176,4.0 4.0,4.0 c 0.0,0.0 36.0,0.0 36.0,0.0 c 2.19999694824,0.0 4.0,-1.80000305176 4.0,-4.0 c 0.0,0.0 0.0,-20.0 0.0,-20.0 c 0.0,-2.19999694824 -1.80000305176,-4.0 -4.0,-4.0 c 0.0,0.0 -36.0,0.0 -36.0,0.0 c -2.19999694824,0.0 -3.97999572754,1.80000305176 -3.97999572754,4.0 Z M 14.0,10.0 c 0.0,0.0 -28.0,0.0 -28.0,0.0 c 0.0,0.0 0.0,-20.0 0.0,-20.0 c 0.0,0.0 28.0,0.0 28.0,0.0 c 0.0,0.0 0.0,20.0 0.0,20.0 Z"
+ android:fillColor="#FFFFFFFF" />
+ </group>
+ </group>
+ </group>
+ <group
+ android:name="arrows"
+ android:translateX="24"
+ android:translateY="24"
+ android:rotation="-90" >
+ <group
+ android:name="arrows_pivot"
+ android:translateX="-24.0798"
+ android:translateY="-24.23" >
+ <group
+ android:name="arrows_0"
+ android:translateX="12.2505"
+ android:translateY="37.2145" >
+ <path
+ android:name="bottom_merged"
+ android:pathData="M 20.7395019531,-31.9844970703 c 6.23999023438,2.83999633789 10.6999969482,8.7200012207 11.8399963379,15.7799987793 c 0.119995117188,0.699996948242 0.740005493164,1.2200012207 1.46099853516,1.2200012207 c 0.919998168945,0.0 1.6190032959,-0.84001159668 1.47900390625,-1.74000549316 c -1.75900268555,-10.3800048828 -9.75900268555,-19.1199951172 -22.5800018311,-20.1600036621 c -0.919998168945,-0.0800018310547 -1.43899536133,1.04000854492 -0.800003051758,1.70001220703 c 0.0,0.0 5.12100219727,5.11999511719 5.12100219727,5.11999511719 c 0.378997802734,0.380004882812 0.97900390625,0.380004882812 1.37899780273,0.020004272461 c 0.0,0.0 2.10000610352,-1.94000244141 2.10000610352,-1.94000244141 Z M 2.73950195312,6.01550292969 c -6.26000976562,-2.83999633789 -10.7200012207,-8.76000976562 -11.8399963379,-15.8600006104 c -0.118011474609,-0.667007446289 -0.702011108398,-1.15100097656 -1.38000488281,-1.13999938965 c -0.860000610352,0.0 -1.52000427246,0.759994506836 -1.38000488281,1.61999511719 c 1.54000854492,10.4000091553 9.5,19.2200012207 22.4199981689,20.2799987793 c 0.920013427734,0.0800018310547 1.44100952148,-1.03999328613 0.800003051758,-1.69999694824 c 0.0,0.0 -5.11999511719,-5.11999511719 -5.11999511719,-5.11999511719 c -0.380004882812,-0.376007080078 -0.988998413086,-0.385009765625 -1.38000488281,-0.0200042724609 c 0.0,0.0 -2.11999511719,1.94000244141 -2.11999511719,1.94000244141 Z"
android:fillColor="#FFFFFFFF"
- android:fillAlpha="1" />
+ android:fillAlpha="0" />
</group>
</group>
</group>
diff --git a/packages/SystemUI/res/drawable/ic_landscape_to_auto_rotate_animation.xml b/packages/SystemUI/res/drawable/ic_landscape_to_auto_rotate_animation.xml
index 5263eb4..86dc6ce 100644
--- a/packages/SystemUI/res/drawable/ic_landscape_to_auto_rotate_animation.xml
+++ b/packages/SystemUI/res/drawable/ic_landscape_to_auto_rotate_animation.xml
@@ -1,6 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
- Copyright (C) 2014 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,21 +14,16 @@
See the License for the specific language governing permissions and
limitations under the License.
-->
-<animated-vector xmlns:android="http://schemas.android.com/apk/res/android"
+<animated-vector
+ xmlns:android="http://schemas.android.com/apk/res/android"
android:drawable="@drawable/ic_landscape_to_auto_rotate" >
<target
+ android:name="landscape"
+ android:animation="@anim/ic_landscape_to_rotate_landscape_animation" />
+ <target
android:name="arrows"
- android:animation="@anim/ic_landscape_to_auto_rotate_animation_arrows" />
+ android:animation="@anim/ic_landscape_to_rotate_arrows_animation" />
<target
- android:name="arrow_top"
- android:animation="@anim/ic_landscape_to_auto_rotate_animation_arrow_top" />
- <target
- android:name="arrow_bottom"
- android:animation="@anim/ic_landscape_to_auto_rotate_animation_arrow_bottom" />
- <target
- android:name="device"
- android:animation="@anim/ic_landscape_to_auto_rotate_animation_device" />
- <target
- android:name="body"
- android:animation="@anim/ic_landscape_to_auto_rotate_animation_body" />
+ android:name="bottom_merged"
+ android:animation="@anim/ic_landscape_to_rotate_bottom_merged_animation" />
</animated-vector>
diff --git a/packages/SystemUI/res/interpolator/ic_landscape_from_auto_rotate_arrows_rotation_interpolator.xml b/packages/SystemUI/res/interpolator/ic_landscape_from_auto_rotate_arrows_rotation_interpolator.xml
deleted file mode 100644
index 76f5667..0000000
--- a/packages/SystemUI/res/interpolator/ic_landscape_from_auto_rotate_arrows_rotation_interpolator.xml
+++ /dev/null
@@ -1,18 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
- 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.
--->
-<pathInterpolator xmlns:android="http://schemas.android.com/apk/res/android"
- android:pathData="M 0,0 c 0.458031162,0 0.299442342,0.748308635 1,1" />
diff --git a/packages/SystemUI/res/interpolator/ic_landscape_to_auto_rotate_arrows_rotation_interpolator.xml b/packages/SystemUI/res/interpolator/ic_landscape_to_rotate_animation_interpolator_0.xml
similarity index 75%
rename from packages/SystemUI/res/interpolator/ic_landscape_to_auto_rotate_arrows_rotation_interpolator.xml
rename to packages/SystemUI/res/interpolator/ic_landscape_to_rotate_animation_interpolator_0.xml
index ac27e4d..793e7ff 100644
--- a/packages/SystemUI/res/interpolator/ic_landscape_to_auto_rotate_arrows_rotation_interpolator.xml
+++ b/packages/SystemUI/res/interpolator/ic_landscape_to_rotate_animation_interpolator_0.xml
@@ -1,6 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
- Copyright (C) 2014 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,5 +14,6 @@
See the License for the specific language governing permissions and
limitations under the License.
-->
-<pathInterpolator xmlns:android="http://schemas.android.com/apk/res/android"
- android:pathData="M 0,0 c 0.4,0.143709151 0.2,1 1,1" />
+<pathInterpolator
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ android:pathData="M 0.0,0.0 c 0.4,0.0 0.6,1.0 1.0,1.0" />
diff --git a/packages/SystemUI/res/interpolator/ic_landscape_to_auto_rotate_arrows_rotation_interpolator.xml b/packages/SystemUI/res/interpolator/ic_rotate_to_landscape_animation_interpolator_0.xml
similarity index 75%
copy from packages/SystemUI/res/interpolator/ic_landscape_to_auto_rotate_arrows_rotation_interpolator.xml
copy to packages/SystemUI/res/interpolator/ic_rotate_to_landscape_animation_interpolator_0.xml
index ac27e4d..793e7ff 100644
--- a/packages/SystemUI/res/interpolator/ic_landscape_to_auto_rotate_arrows_rotation_interpolator.xml
+++ b/packages/SystemUI/res/interpolator/ic_rotate_to_landscape_animation_interpolator_0.xml
@@ -1,6 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
- Copyright (C) 2014 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,5 +14,6 @@
See the License for the specific language governing permissions and
limitations under the License.
-->
-<pathInterpolator xmlns:android="http://schemas.android.com/apk/res/android"
- android:pathData="M 0,0 c 0.4,0.143709151 0.2,1 1,1" />
+<pathInterpolator
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ android:pathData="M 0.0,0.0 c 0.4,0.0 0.6,1.0 1.0,1.0" />
diff --git a/packages/SystemUI/res/layout/quick_status_bar_header_system_icons.xml b/packages/SystemUI/res/layout/quick_status_bar_header_system_icons.xml
index c6dbd18..849bea4 100644
--- a/packages/SystemUI/res/layout/quick_status_bar_header_system_icons.xml
+++ b/packages/SystemUI/res/layout/quick_status_bar_header_system_icons.xml
@@ -23,8 +23,8 @@
android:clipChildren="false"
android:clipToPadding="false"
android:gravity="center"
- android:paddingStart="16dp"
- android:paddingEnd="16dp"
+ android:paddingStart="8dp"
+ android:paddingEnd="8dp"
android:orientation="horizontal">
diff --git a/packages/SystemUI/res/layout/recents_empty.xml b/packages/SystemUI/res/layout/recents_empty.xml
index 53d9cc5..8048c68 100644
--- a/packages/SystemUI/res/layout/recents_empty.xml
+++ b/packages/SystemUI/res/layout/recents_empty.xml
@@ -23,7 +23,8 @@
android:drawableTop="@drawable/recents_empty"
android:drawablePadding="25dp"
android:textSize="16sp"
- android:textColor="#ffffffff"
+ android:drawableTint="?attr/bgProtectTextColor"
+ android:textColor="?attr/bgProtectTextColor"
android:text="@string/recents_empty_message"
android:fontFamily="sans-serif"
android:visibility="gone" />
\ No newline at end of file
diff --git a/packages/SystemUI/res/layout/recents_stack_action_button.xml b/packages/SystemUI/res/layout/recents_stack_action_button.xml
index 34b4e17..10b4316 100644
--- a/packages/SystemUI/res/layout/recents_stack_action_button.xml
+++ b/packages/SystemUI/res/layout/recents_stack_action_button.xml
@@ -24,7 +24,7 @@
android:paddingBottom="12dp"
android:text="@string/recents_stack_action_button_label"
android:textSize="14sp"
- android:textColor="#FFFFFF"
+ android:textColor="?attr/bgProtectTextColor"
android:textAllCaps="true"
android:shadowColor="#99000000"
android:shadowDx="0"
diff --git a/packages/SystemUI/res/layout/rounded_corners.xml b/packages/SystemUI/res/layout/rounded_corners.xml
index 8d391e0..d1ef5d6 100644
--- a/packages/SystemUI/res/layout/rounded_corners.xml
+++ b/packages/SystemUI/res/layout/rounded_corners.xml
@@ -22,6 +22,7 @@
android:id="@+id/left"
android:layout_width="12dp"
android:layout_height="12dp"
+ android:layout_gravity="left"
android:tint="#ff000000"
android:src="@drawable/rounded" />
<ImageView
@@ -29,6 +30,6 @@
android:layout_width="12dp"
android:layout_height="12dp"
android:tint="#ff000000"
- android:layout_gravity="end"
+ android:layout_gravity="right"
android:src="@drawable/rounded" />
</FrameLayout>
diff --git a/packages/SystemUI/res/values-af/strings.xml b/packages/SystemUI/res/values-af/strings.xml
index c593655..62ceada 100644
--- a/packages/SystemUI/res/values-af/strings.xml
+++ b/packages/SystemUI/res/values-af/strings.xml
@@ -310,6 +310,8 @@
<string name="quick_settings_more_settings" msgid="326112621462813682">"Meer instellings"</string>
<string name="quick_settings_done" msgid="3402999958839153376">"Klaar"</string>
<string name="quick_settings_connected" msgid="1722253542984847487">"Gekoppel"</string>
+ <!-- no translation found for quick_settings_connected_battery_level (4136051440381328892) -->
+ <skip />
<string name="quick_settings_connecting" msgid="47623027419264404">"Koppel tans …"</string>
<string name="quick_settings_tethering_label" msgid="7153452060448575549">"USB-verbinding"</string>
<string name="quick_settings_hotspot_label" msgid="6046917934974004879">"Warmkol"</string>
diff --git a/packages/SystemUI/res/values-am/strings.xml b/packages/SystemUI/res/values-am/strings.xml
index 6689907..17964d8 100644
--- a/packages/SystemUI/res/values-am/strings.xml
+++ b/packages/SystemUI/res/values-am/strings.xml
@@ -310,6 +310,8 @@
<string name="quick_settings_more_settings" msgid="326112621462813682">"ተጨማሪ ቅንብሮች"</string>
<string name="quick_settings_done" msgid="3402999958839153376">"ተከናውኗል"</string>
<string name="quick_settings_connected" msgid="1722253542984847487">"ተገናኝቷል"</string>
+ <!-- no translation found for quick_settings_connected_battery_level (4136051440381328892) -->
+ <skip />
<string name="quick_settings_connecting" msgid="47623027419264404">"በማገናኘት ላይ..."</string>
<string name="quick_settings_tethering_label" msgid="7153452060448575549">"በማገናኘት ላይ"</string>
<string name="quick_settings_hotspot_label" msgid="6046917934974004879">"መገናኛ ነጥብ"</string>
diff --git a/packages/SystemUI/res/values-am/strings_tv.xml b/packages/SystemUI/res/values-am/strings_tv.xml
index 89fd692..7a375a9 100644
--- a/packages/SystemUI/res/values-am/strings_tv.xml
+++ b/packages/SystemUI/res/values-am/strings_tv.xml
@@ -19,7 +19,7 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="notification_channel_tv_pip" msgid="134047986446577723">"ፎቶ በፎቶ"</string>
+ <string name="notification_channel_tv_pip" msgid="134047986446577723">"ስዕል-ላይ-ስዕል"</string>
<string name="pip_notification_unknown_title" msgid="6289156118095849438">"(ርዕስ የሌለው ፕሮግራም)"</string>
<string name="pip_close" msgid="3480680679023423574">"PIPን ዝጋ"</string>
<string name="pip_fullscreen" msgid="8604643018538487816">"ሙሉ ማያ ገጽ"</string>
diff --git a/packages/SystemUI/res/values-ar/strings.xml b/packages/SystemUI/res/values-ar/strings.xml
index bc6104f..aabc9d7 100644
--- a/packages/SystemUI/res/values-ar/strings.xml
+++ b/packages/SystemUI/res/values-ar/strings.xml
@@ -74,8 +74,8 @@
<string name="screenshot_saving_ticker" msgid="7403652894056693515">"جارٍ حفظ لقطة الشاشة..."</string>
<string name="screenshot_saving_title" msgid="8242282144535555697">"جارٍ حفظ لقطة الشاشة..."</string>
<string name="screenshot_saving_text" msgid="2419718443411738818">"يتم حفظ لقطة."</string>
- <string name="screenshot_saved_title" msgid="6461865960961414961">"تم التقاط لقطة الشاشة."</string>
- <string name="screenshot_saved_text" msgid="2685605830386712477">"انقر لعرض لقطة الشاشة."</string>
+ <string name="screenshot_saved_title" msgid="6461865960961414961">"تم التقاط لقطة الشاشة"</string>
+ <string name="screenshot_saved_text" msgid="2685605830386712477">"انقر لعرض لقطة الشاشة"</string>
<string name="screenshot_failed_title" msgid="705781116746922771">"تعذر التقاط لقطة الشاشة."</string>
<string name="screenshot_failed_to_save_unknown_text" msgid="7887826345701753830">"حدثت مشكلة أثناء حفظ لقطة الشاشة."</string>
<string name="screenshot_failed_to_save_text" msgid="2592658083866306296">"يتعذر حفظ لقطة الشاشة نظرًا لأن مساحة التخزين المتاحة محدودة."</string>
@@ -161,7 +161,7 @@
<string name="accessibility_cell_data_off" msgid="443267573897409704">"إيقاف بيانات الجوال"</string>
<string name="accessibility_bluetooth_tether" msgid="4102784498140271969">"ربط البلوتوث."</string>
<string name="accessibility_airplane_mode" msgid="834748999790763092">"وضع الطائرة."</string>
- <string name="accessibility_vpn_on" msgid="5993385083262856059">"الشبكة الظاهرية الخاصة (VPN) قيد التشغيل."</string>
+ <string name="accessibility_vpn_on" msgid="5993385083262856059">"الشبكة الافتراضية الخاصة (VPN) قيد التشغيل."</string>
<string name="accessibility_no_sims" msgid="3957997018324995781">"ليس هناك شريحة SIM."</string>
<string name="accessibility_carrier_network_change_mode" msgid="4017301580441304305">"جارٍ تغيير شبكة مشغِّل شبكة الجوّال."</string>
<string name="accessibility_battery_details" msgid="7645516654955025422">"فتح تفاصيل البطارية"</string>
@@ -318,6 +318,8 @@
<string name="quick_settings_more_settings" msgid="326112621462813682">"المزيد من الإعدادات"</string>
<string name="quick_settings_done" msgid="3402999958839153376">"تم"</string>
<string name="quick_settings_connected" msgid="1722253542984847487">"متصل"</string>
+ <!-- no translation found for quick_settings_connected_battery_level (4136051440381328892) -->
+ <skip />
<string name="quick_settings_connecting" msgid="47623027419264404">"جارٍ الاتصال..."</string>
<string name="quick_settings_tethering_label" msgid="7153452060448575549">"النطاق"</string>
<string name="quick_settings_hotspot_label" msgid="6046917934974004879">"نقطة اتصال"</string>
@@ -428,22 +430,22 @@
<string name="quick_settings_disclosure_named_management_named_vpn" msgid="6290456493852584017">"يخضع الجهاز لإدارة <xliff:g id="ORGANIZATION_NAME">%1$s</xliff:g> وتم ربطه بـ <xliff:g id="VPN_APP">%2$s</xliff:g>"</string>
<string name="quick_settings_disclosure_management" msgid="3294967280853150271">"يخضع الجهاز لإدارة مؤسستك"</string>
<string name="quick_settings_disclosure_named_management" msgid="1059403025094542908">"تتم إدارة هذا الجهاز بواسطة <xliff:g id="ORGANIZATION_NAME">%1$s</xliff:g>"</string>
- <string name="quick_settings_disclosure_management_vpns" msgid="3698767349925266482">"يخضع الجهاز لإدارة مؤسستك وتم ربطه بالشبكات الظاهرية الخاصة"</string>
- <string name="quick_settings_disclosure_named_management_vpns" msgid="7777821385318891527">"يخضع الجهاز لإدارة <xliff:g id="ORGANIZATION_NAME">%1$s</xliff:g> وتم ربطه بالشبكات الظاهرية الخاصة"</string>
+ <string name="quick_settings_disclosure_management_vpns" msgid="3698767349925266482">"يخضع الجهاز لإدارة مؤسستك وتم ربطه بالشبكات الافتراضية الخاصة"</string>
+ <string name="quick_settings_disclosure_named_management_vpns" msgid="7777821385318891527">"يخضع الجهاز لإدارة <xliff:g id="ORGANIZATION_NAME">%1$s</xliff:g> وتم ربطه بالشبكات الافتراضية الخاصة"</string>
<string name="quick_settings_disclosure_managed_profile_monitoring" msgid="5125463987558278215">"يمكن لمؤسستك مراقبة حركة بيانات الشبكة في الملف الشخصي للعمل"</string>
<string name="quick_settings_disclosure_named_managed_profile_monitoring" msgid="8973606847896650284">"يمكن لـ <xliff:g id="ORGANIZATION_NAME">%1$s</xliff:g> مراقبة حركة بيانات الشبكة في ملفك الشخصي للعمل"</string>
<string name="quick_settings_disclosure_monitoring" msgid="679658227269205728">"قد تكون الشبكة خاضعة للمراقبة"</string>
- <string name="quick_settings_disclosure_vpns" msgid="8170318392053156330">"تم ربط الجهاز بالشبكات الظاهرية الخاصة"</string>
+ <string name="quick_settings_disclosure_vpns" msgid="8170318392053156330">"تم ربط الجهاز بالشبكات الافتراضية الخاصة"</string>
<string name="quick_settings_disclosure_managed_profile_named_vpn" msgid="3494535754792751741">"تم ربط الملف الشخصي للعمل بـ <xliff:g id="VPN_APP">%1$s</xliff:g>"</string>
<string name="quick_settings_disclosure_personal_profile_named_vpn" msgid="4467456202486569906">"تم ربط الملف الشخصي بـ <xliff:g id="VPN_APP">%1$s</xliff:g>"</string>
<string name="quick_settings_disclosure_named_vpn" msgid="6943724064780847080">"تم ربط الجهاز بـ <xliff:g id="VPN_APP">%1$s</xliff:g>"</string>
<string name="monitoring_title_device_owned" msgid="1652495295941959815">"إدارة الأجهزة"</string>
<string name="monitoring_title_profile_owned" msgid="6790109874733501487">"مراقبة الملف الشخصي"</string>
<string name="monitoring_title" msgid="169206259253048106">"مراقبة الشبكات"</string>
- <string name="monitoring_subtitle_vpn" msgid="876537538087857300">"شبكة ظاهرية خاصة (VPN)"</string>
+ <string name="monitoring_subtitle_vpn" msgid="876537538087857300">"شبكة افتراضية خاصة (VPN)"</string>
<string name="monitoring_subtitle_network_logging" msgid="3341264304793193386">"تسجيل بيانات الشبكة"</string>
<string name="monitoring_subtitle_ca_certificate" msgid="3874151893894355988">"شهادات CA"</string>
- <string name="disable_vpn" msgid="4435534311510272506">"تعطيل الشبكة الظاهرية الخاصة"</string>
+ <string name="disable_vpn" msgid="4435534311510272506">"تعطيل الشبكة الافتراضية الخاصة"</string>
<string name="disconnect_vpn" msgid="1324915059568548655">"قطع الاتصال بشبكة VPN"</string>
<string name="monitoring_button_view_policies" msgid="100913612638514424">"عرض السياسات"</string>
<string name="monitoring_description_named_management" msgid="5281789135578986303">"تتم إدارة جهازك بواسطة <xliff:g id="ORGANIZATION_NAME">%1$s</xliff:g>.\n\nيمكن للمشرف مراقبة وإدارة الإعدادات والدخول إلى المؤسسة والتطبيقات والبيانات المرتبطة بجهازك ومعلومات الموقع الجغرافي للجهاز.\n\nللحصول على المزيد من المعلومات، اتصل بالمشرف."</string>
@@ -463,13 +465,13 @@
<string name="monitoring_description_do_learn_more" msgid="1849514470437907421">"مزيد من المعلومات"</string>
<string name="monitoring_description_do_body_vpn" msgid="8255218762488901796">"لقد اتصلت بتطبيق <xliff:g id="VPN_APP">%1$s</xliff:g>، الذي يمكن أن يراقب نشاط الشبكة، بما في ذلك رسائل البريد الإلكتروني والتطبيقات والمواقع الإلكترونية."</string>
<string name="monitoring_description_vpn_settings_separator" msgid="1933186756733474388">" "</string>
- <string name="monitoring_description_vpn_settings" msgid="8869300202410505143">"فتح إعدادات الشبكة الظاهرية الخاصة (VPN)"</string>
+ <string name="monitoring_description_vpn_settings" msgid="8869300202410505143">"فتح إعدادات الشبكة الافتراضية الخاصة (VPN)"</string>
<string name="monitoring_description_ca_cert_settings_separator" msgid="4987350385906393626">" "</string>
<string name="monitoring_description_ca_cert_settings" msgid="5489969458872997092">"فتح بيانات الاعتماد الموثوق بها"</string>
<string name="monitoring_description_network_logging" msgid="7223505523384076027">"شغَّل المشرف ميزة تسجيل بيانات الشبكة، والتي يتم من خلالها مراقبة حركة البيانات على جهازك.\n\nللحصول على المزيد من المعلومات، اتصل بالمشرف."</string>
- <string name="monitoring_description_vpn" msgid="4445150119515393526">"لقد منحت تطبيقًا الإذن لإعداد اتصال شبكة ظاهرية خاصة (VPN).\n\nيمكن لهذا التطبيق مراقبة أنشطتك على الجهاز والشبكة، بما في ذلك الرسائل الإلكترونية والتطبيقات ومواقع الويب."</string>
- <string name="monitoring_description_vpn_profile_owned" msgid="2958019119161161530">"تتم إدارة ملفك الشخصي للعمل بواسطة <xliff:g id="ORGANIZATION">%1$s</xliff:g>.\n\nويمكن للمشرف مراقبة نشاط الشبكة، بما في ذلك رسائل البريد الإلكتروني والتطبيقات والمواقع الإلكترونية.\n\nللحصول على المزيد من المعلومات، اتصل بالمشرف.\n\nوتجدر الإشارة إلى أنك متصل أيضًا بشبكة ظاهرية خاصة يمكن أن تراقب نشاط الشبكة."</string>
- <string name="legacy_vpn_name" msgid="6604123105765737830">"شبكة ظاهرية خاصة"</string>
+ <string name="monitoring_description_vpn" msgid="4445150119515393526">"لقد منحت تطبيقًا الإذن لإعداد اتصال شبكة افتراضية خاصة (VPN).\n\nيمكن لهذا التطبيق مراقبة أنشطتك على الجهاز والشبكة، بما في ذلك الرسائل الإلكترونية والتطبيقات ومواقع الويب."</string>
+ <string name="monitoring_description_vpn_profile_owned" msgid="2958019119161161530">"تتم إدارة ملفك الشخصي للعمل بواسطة <xliff:g id="ORGANIZATION">%1$s</xliff:g>.\n\nويمكن للمشرف مراقبة نشاط الشبكة، بما في ذلك رسائل البريد الإلكتروني والتطبيقات والمواقع الإلكترونية.\n\nللحصول على المزيد من المعلومات، اتصل بالمشرف.\n\nوتجدر الإشارة إلى أنك متصل أيضًا بشبكة افتراضية خاصة يمكن أن تراقب نشاط الشبكة."</string>
+ <string name="legacy_vpn_name" msgid="6604123105765737830">"شبكة افتراضية خاصة"</string>
<string name="monitoring_description_app" msgid="1828472472674709532">"تم ربطك بـ <xliff:g id="APPLICATION">%1$s</xliff:g>، الذي يمكنه مراقبة أنشطتك على الشبكة، بما في ذلك الرسائل الإلكترونية والتطبيقات ومواقع الويب."</string>
<string name="monitoring_description_app_personal" msgid="484599052118316268">"أنت متصل بـ <xliff:g id="APPLICATION">%1$s</xliff:g>، الذي يمكنه مراقبة أنشطتك الشخصية على الشبكة، بما في ذلك الرسائل الإلكترونية والتطبيقات ومواقع الويب."</string>
<string name="branded_monitoring_description_app_personal" msgid="2669518213949202599">"أنت متصل بـ <xliff:g id="APPLICATION">%1$s</xliff:g>، الذي يمكنه مراقبة أنشطتك الشخصية على الشبكة، بما في ذلك الرسائل الإلكترونية والتطبيقات ومواقع الويب."</string>
diff --git a/packages/SystemUI/res/values-az/strings.xml b/packages/SystemUI/res/values-az/strings.xml
index a5fb448..a8ad009 100644
--- a/packages/SystemUI/res/values-az/strings.xml
+++ b/packages/SystemUI/res/values-az/strings.xml
@@ -310,6 +310,8 @@
<string name="quick_settings_more_settings" msgid="326112621462813682">"Digər ayarlar"</string>
<string name="quick_settings_done" msgid="3402999958839153376">"Hazır"</string>
<string name="quick_settings_connected" msgid="1722253542984847487">"Qoşulu"</string>
+ <!-- no translation found for quick_settings_connected_battery_level (4136051440381328892) -->
+ <skip />
<string name="quick_settings_connecting" msgid="47623027419264404">"Qoşulur..."</string>
<string name="quick_settings_tethering_label" msgid="7153452060448575549">"Birləşmə"</string>
<string name="quick_settings_hotspot_label" msgid="6046917934974004879">"Hotspot"</string>
diff --git a/packages/SystemUI/res/values-b+sr+Latn/strings.xml b/packages/SystemUI/res/values-b+sr+Latn/strings.xml
index 9d8473e..ed4eb72 100644
--- a/packages/SystemUI/res/values-b+sr+Latn/strings.xml
+++ b/packages/SystemUI/res/values-b+sr+Latn/strings.xml
@@ -312,6 +312,8 @@
<string name="quick_settings_more_settings" msgid="326112621462813682">"Još podešavanja"</string>
<string name="quick_settings_done" msgid="3402999958839153376">"Gotovo"</string>
<string name="quick_settings_connected" msgid="1722253542984847487">"Povezan"</string>
+ <!-- no translation found for quick_settings_connected_battery_level (4136051440381328892) -->
+ <skip />
<string name="quick_settings_connecting" msgid="47623027419264404">"Povezuje se..."</string>
<string name="quick_settings_tethering_label" msgid="7153452060448575549">"Povezivanje"</string>
<string name="quick_settings_hotspot_label" msgid="6046917934974004879">"Hotspot"</string>
diff --git a/packages/SystemUI/res/values-be/strings.xml b/packages/SystemUI/res/values-be/strings.xml
index 8d36b0b..48a56b7 100644
--- a/packages/SystemUI/res/values-be/strings.xml
+++ b/packages/SystemUI/res/values-be/strings.xml
@@ -316,6 +316,8 @@
<string name="quick_settings_more_settings" msgid="326112621462813682">"Дадатковыя налады"</string>
<string name="quick_settings_done" msgid="3402999958839153376">"Гатова"</string>
<string name="quick_settings_connected" msgid="1722253542984847487">"Падлучана"</string>
+ <!-- no translation found for quick_settings_connected_battery_level (4136051440381328892) -->
+ <skip />
<string name="quick_settings_connecting" msgid="47623027419264404">"Падлучэнне..."</string>
<string name="quick_settings_tethering_label" msgid="7153452060448575549">"Мадэм"</string>
<string name="quick_settings_hotspot_label" msgid="6046917934974004879">"Кропка доступу"</string>
diff --git a/packages/SystemUI/res/values-bg/strings.xml b/packages/SystemUI/res/values-bg/strings.xml
index bcdcfd5..f6fbaf5 100644
--- a/packages/SystemUI/res/values-bg/strings.xml
+++ b/packages/SystemUI/res/values-bg/strings.xml
@@ -310,6 +310,8 @@
<string name="quick_settings_more_settings" msgid="326112621462813682">"Още настройки"</string>
<string name="quick_settings_done" msgid="3402999958839153376">"Готово"</string>
<string name="quick_settings_connected" msgid="1722253542984847487">"Установена е връзка"</string>
+ <!-- no translation found for quick_settings_connected_battery_level (4136051440381328892) -->
+ <skip />
<string name="quick_settings_connecting" msgid="47623027419264404">"Установява се връзка..."</string>
<string name="quick_settings_tethering_label" msgid="7153452060448575549">"Тетъринг"</string>
<string name="quick_settings_hotspot_label" msgid="6046917934974004879">"Точка за достъп"</string>
@@ -725,8 +727,8 @@
<string name="pip_phone_minimize" msgid="1079119422589131792">"Намаляване"</string>
<string name="pip_phone_close" msgid="8416647892889710330">"Затваряне"</string>
<string name="pip_phone_dismiss_hint" msgid="6351678169095923899">"Преместете надолу с плъзгане, за да отхвърлите"</string>
- <string name="pip_menu_title" msgid="3328510504196964712">"Меню за режима „Картина в картина“"</string>
- <string name="pip_notification_title" msgid="3204024940158161322">"<xliff:g id="NAME">%s</xliff:g> е в режима „Картина в картина“"</string>
+ <string name="pip_menu_title" msgid="3328510504196964712">"Меню за режима „Картина в картината“"</string>
+ <string name="pip_notification_title" msgid="3204024940158161322">"<xliff:g id="NAME">%s</xliff:g> е в режима „Картина в картината“"</string>
<string name="pip_notification_message" msgid="5619512781514343311">"Ако не искате <xliff:g id="NAME">%s</xliff:g> да използва тази функция, докоснете, за да отворите настройките, и я изключете."</string>
<string name="pip_play" msgid="1417176722760265888">"Пускане"</string>
<string name="pip_pause" msgid="8881063404466476571">"Поставяне на пауза"</string>
diff --git a/packages/SystemUI/res/values-bg/strings_tv.xml b/packages/SystemUI/res/values-bg/strings_tv.xml
index ffe9007..a5eb8b93 100644
--- a/packages/SystemUI/res/values-bg/strings_tv.xml
+++ b/packages/SystemUI/res/values-bg/strings_tv.xml
@@ -19,7 +19,7 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="notification_channel_tv_pip" msgid="134047986446577723">"Картина в картина"</string>
+ <string name="notification_channel_tv_pip" msgid="134047986446577723">"Картина в картината"</string>
<string name="pip_notification_unknown_title" msgid="6289156118095849438">"(Програма без заглавие)"</string>
<string name="pip_close" msgid="3480680679023423574">"Затваряне на PIP"</string>
<string name="pip_fullscreen" msgid="8604643018538487816">"Цял екран"</string>
diff --git a/packages/SystemUI/res/values-bn/strings.xml b/packages/SystemUI/res/values-bn/strings.xml
index 58293e2..edcb004 100644
--- a/packages/SystemUI/res/values-bn/strings.xml
+++ b/packages/SystemUI/res/values-bn/strings.xml
@@ -310,6 +310,8 @@
<string name="quick_settings_more_settings" msgid="326112621462813682">"আরো সেটিংস"</string>
<string name="quick_settings_done" msgid="3402999958839153376">"সম্পন্ন হয়েছে"</string>
<string name="quick_settings_connected" msgid="1722253542984847487">"সংযুক্ত হয়েছে"</string>
+ <!-- no translation found for quick_settings_connected_battery_level (4136051440381328892) -->
+ <skip />
<string name="quick_settings_connecting" msgid="47623027419264404">"সংযুক্ত হচ্ছে..."</string>
<string name="quick_settings_tethering_label" msgid="7153452060448575549">"টেদারিং"</string>
<string name="quick_settings_hotspot_label" msgid="6046917934974004879">"হটস্পট"</string>
diff --git a/packages/SystemUI/res/values-bs/strings.xml b/packages/SystemUI/res/values-bs/strings.xml
index 97c2e1c..b8206a0 100644
--- a/packages/SystemUI/res/values-bs/strings.xml
+++ b/packages/SystemUI/res/values-bs/strings.xml
@@ -312,6 +312,8 @@
<string name="quick_settings_more_settings" msgid="326112621462813682">"Više postavki"</string>
<string name="quick_settings_done" msgid="3402999958839153376">"Gotovo"</string>
<string name="quick_settings_connected" msgid="1722253542984847487">"Povezano"</string>
+ <!-- no translation found for quick_settings_connected_battery_level (4136051440381328892) -->
+ <skip />
<string name="quick_settings_connecting" msgid="47623027419264404">"Povezivanje..."</string>
<string name="quick_settings_tethering_label" msgid="7153452060448575549">"Dijeljenje veze"</string>
<string name="quick_settings_hotspot_label" msgid="6046917934974004879">"Pristupna tačka"</string>
diff --git a/packages/SystemUI/res/values-ca/strings.xml b/packages/SystemUI/res/values-ca/strings.xml
index 129d605..0675706 100644
--- a/packages/SystemUI/res/values-ca/strings.xml
+++ b/packages/SystemUI/res/values-ca/strings.xml
@@ -310,6 +310,8 @@
<string name="quick_settings_more_settings" msgid="326112621462813682">"Més opcions"</string>
<string name="quick_settings_done" msgid="3402999958839153376">"Fet"</string>
<string name="quick_settings_connected" msgid="1722253542984847487">"Connectat"</string>
+ <!-- no translation found for quick_settings_connected_battery_level (4136051440381328892) -->
+ <skip />
<string name="quick_settings_connecting" msgid="47623027419264404">"S\'està connectant..."</string>
<string name="quick_settings_tethering_label" msgid="7153452060448575549">"Compartició de xarxa"</string>
<string name="quick_settings_hotspot_label" msgid="6046917934974004879">"Punt d\'accés Wi-Fi"</string>
diff --git a/packages/SystemUI/res/values-cs/strings.xml b/packages/SystemUI/res/values-cs/strings.xml
index 8fc3300..7a0fbfc 100644
--- a/packages/SystemUI/res/values-cs/strings.xml
+++ b/packages/SystemUI/res/values-cs/strings.xml
@@ -316,6 +316,8 @@
<string name="quick_settings_more_settings" msgid="326112621462813682">"Další nastavení"</string>
<string name="quick_settings_done" msgid="3402999958839153376">"Hotovo"</string>
<string name="quick_settings_connected" msgid="1722253542984847487">"Připojeno"</string>
+ <!-- no translation found for quick_settings_connected_battery_level (4136051440381328892) -->
+ <skip />
<string name="quick_settings_connecting" msgid="47623027419264404">"Připojování..."</string>
<string name="quick_settings_tethering_label" msgid="7153452060448575549">"Sdílené připojení"</string>
<string name="quick_settings_hotspot_label" msgid="6046917934974004879">"Hotspot"</string>
@@ -739,8 +741,8 @@
<string name="pip_phone_minimize" msgid="1079119422589131792">"Minimalizovat"</string>
<string name="pip_phone_close" msgid="8416647892889710330">"Zavřít"</string>
<string name="pip_phone_dismiss_hint" msgid="6351678169095923899">"Nápovědu zavřete přetažením dolů"</string>
- <string name="pip_menu_title" msgid="3328510504196964712">"Nabídka typu obraz v obraze"</string>
- <string name="pip_notification_title" msgid="3204024940158161322">"Aplikace <xliff:g id="NAME">%s</xliff:g> je v zobrazení obraz v obraze"</string>
+ <string name="pip_menu_title" msgid="3328510504196964712">"Nabídka režimu obraz v obraze"</string>
+ <string name="pip_notification_title" msgid="3204024940158161322">"Aplikace <xliff:g id="NAME">%s</xliff:g> je v režimu obraz v obraze"</string>
<string name="pip_notification_message" msgid="5619512781514343311">"Pokud nechcete, aby aplikace <xliff:g id="NAME">%s</xliff:g> tuto funkci používala, klepnutím otevřete nastavení a funkci vypněte."</string>
<string name="pip_play" msgid="1417176722760265888">"Přehrát"</string>
<string name="pip_pause" msgid="8881063404466476571">"Pozastavit"</string>
diff --git a/packages/SystemUI/res/values-cs/strings_tv.xml b/packages/SystemUI/res/values-cs/strings_tv.xml
index f27974f..a928218 100644
--- a/packages/SystemUI/res/values-cs/strings_tv.xml
+++ b/packages/SystemUI/res/values-cs/strings_tv.xml
@@ -21,6 +21,6 @@
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="notification_channel_tv_pip" msgid="134047986446577723">"Obraz v obraze"</string>
<string name="pip_notification_unknown_title" msgid="6289156118095849438">"(Bez názvu)"</string>
- <string name="pip_close" msgid="3480680679023423574">"Ukončit PIP"</string>
+ <string name="pip_close" msgid="3480680679023423574">"Ukončit obraz v obraze (PIP)"</string>
<string name="pip_fullscreen" msgid="8604643018538487816">"Celá obrazovka"</string>
</resources>
diff --git a/packages/SystemUI/res/values-da/strings.xml b/packages/SystemUI/res/values-da/strings.xml
index 04a1dde..08f5761 100644
--- a/packages/SystemUI/res/values-da/strings.xml
+++ b/packages/SystemUI/res/values-da/strings.xml
@@ -310,6 +310,8 @@
<string name="quick_settings_more_settings" msgid="326112621462813682">"Flere indstillinger"</string>
<string name="quick_settings_done" msgid="3402999958839153376">"Udfør"</string>
<string name="quick_settings_connected" msgid="1722253542984847487">"Tilsluttet"</string>
+ <!-- no translation found for quick_settings_connected_battery_level (4136051440381328892) -->
+ <skip />
<string name="quick_settings_connecting" msgid="47623027419264404">"Opretter forbindelse…"</string>
<string name="quick_settings_tethering_label" msgid="7153452060448575549">"Netdeling"</string>
<string name="quick_settings_hotspot_label" msgid="6046917934974004879">"Hotspot"</string>
diff --git a/packages/SystemUI/res/values-da/strings_tv.xml b/packages/SystemUI/res/values-da/strings_tv.xml
index d24cb3a..aa8af74 100644
--- a/packages/SystemUI/res/values-da/strings_tv.xml
+++ b/packages/SystemUI/res/values-da/strings_tv.xml
@@ -21,6 +21,6 @@
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="notification_channel_tv_pip" msgid="134047986446577723">"Integreret billede"</string>
<string name="pip_notification_unknown_title" msgid="6289156118095849438">"(Program uden titel)"</string>
- <string name="pip_close" msgid="3480680679023423574">"Luk PIP"</string>
+ <string name="pip_close" msgid="3480680679023423574">"Luk integreret billede"</string>
<string name="pip_fullscreen" msgid="8604643018538487816">"Fuld skærm"</string>
</resources>
diff --git a/packages/SystemUI/res/values-de/strings.xml b/packages/SystemUI/res/values-de/strings.xml
index 8db9281..50d0a44 100644
--- a/packages/SystemUI/res/values-de/strings.xml
+++ b/packages/SystemUI/res/values-de/strings.xml
@@ -301,7 +301,7 @@
<string name="quick_settings_wifi_no_network" msgid="2221993077220856376">"Kein Netz"</string>
<string name="quick_settings_wifi_off_label" msgid="7558778100843885864">"WLAN aus"</string>
<string name="quick_settings_wifi_on_label" msgid="7607810331387031235">"WLAN an"</string>
- <string name="quick_settings_wifi_detail_empty_text" msgid="269990350383909226">"Keine WLAN-Netzwerke verfügbar"</string>
+ <string name="quick_settings_wifi_detail_empty_text" msgid="269990350383909226">"Keine WLANs verfügbar"</string>
<string name="quick_settings_cast_title" msgid="7709016546426454729">"Streamen"</string>
<string name="quick_settings_casting" msgid="6601710681033353316">"Wird übertragen"</string>
<string name="quick_settings_cast_device_default_name" msgid="5367253104742382945">"Unbenanntes Gerät"</string>
@@ -314,6 +314,8 @@
<string name="quick_settings_more_settings" msgid="326112621462813682">"Weitere Einstellungen"</string>
<string name="quick_settings_done" msgid="3402999958839153376">"Fertig"</string>
<string name="quick_settings_connected" msgid="1722253542984847487">"Verbunden"</string>
+ <!-- no translation found for quick_settings_connected_battery_level (4136051440381328892) -->
+ <skip />
<string name="quick_settings_connecting" msgid="47623027419264404">"Verbindung wird hergestellt…"</string>
<string name="quick_settings_tethering_label" msgid="7153452060448575549">"Tethering"</string>
<string name="quick_settings_hotspot_label" msgid="6046917934974004879">"Hotspot"</string>
diff --git a/packages/SystemUI/res/values-el/strings.xml b/packages/SystemUI/res/values-el/strings.xml
index 6419922..4c4bc00 100644
--- a/packages/SystemUI/res/values-el/strings.xml
+++ b/packages/SystemUI/res/values-el/strings.xml
@@ -310,6 +310,8 @@
<string name="quick_settings_more_settings" msgid="326112621462813682">"Περισσότερες ρυθμίσεις"</string>
<string name="quick_settings_done" msgid="3402999958839153376">"Τέλος"</string>
<string name="quick_settings_connected" msgid="1722253542984847487">"Συνδέθηκε"</string>
+ <!-- no translation found for quick_settings_connected_battery_level (4136051440381328892) -->
+ <skip />
<string name="quick_settings_connecting" msgid="47623027419264404">"Σύνδεση…"</string>
<string name="quick_settings_tethering_label" msgid="7153452060448575549">"Πρόσδεση"</string>
<string name="quick_settings_hotspot_label" msgid="6046917934974004879">"Σημείο πρόσβασης Wi-Fi"</string>
diff --git a/packages/SystemUI/res/values-en-rAU/strings.xml b/packages/SystemUI/res/values-en-rAU/strings.xml
index 80c8c88..e832f44 100644
--- a/packages/SystemUI/res/values-en-rAU/strings.xml
+++ b/packages/SystemUI/res/values-en-rAU/strings.xml
@@ -310,6 +310,8 @@
<string name="quick_settings_more_settings" msgid="326112621462813682">"More settings"</string>
<string name="quick_settings_done" msgid="3402999958839153376">"Done"</string>
<string name="quick_settings_connected" msgid="1722253542984847487">"Connected"</string>
+ <!-- no translation found for quick_settings_connected_battery_level (4136051440381328892) -->
+ <skip />
<string name="quick_settings_connecting" msgid="47623027419264404">"Connecting..."</string>
<string name="quick_settings_tethering_label" msgid="7153452060448575549">"Tethering"</string>
<string name="quick_settings_hotspot_label" msgid="6046917934974004879">"Hotspot"</string>
diff --git a/packages/SystemUI/res/values-en-rAU/strings_tv.xml b/packages/SystemUI/res/values-en-rAU/strings_tv.xml
index ffcd655..31cbd83 100644
--- a/packages/SystemUI/res/values-en-rAU/strings_tv.xml
+++ b/packages/SystemUI/res/values-en-rAU/strings_tv.xml
@@ -19,7 +19,7 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="notification_channel_tv_pip" msgid="134047986446577723">"Picture-in-Picture"</string>
+ <string name="notification_channel_tv_pip" msgid="134047986446577723">"Picture-in-picture"</string>
<string name="pip_notification_unknown_title" msgid="6289156118095849438">"(No title program)"</string>
<string name="pip_close" msgid="3480680679023423574">"Close PIP"</string>
<string name="pip_fullscreen" msgid="8604643018538487816">"Full screen"</string>
diff --git a/packages/SystemUI/res/values-en-rGB/strings.xml b/packages/SystemUI/res/values-en-rGB/strings.xml
index 80c8c88..e832f44 100644
--- a/packages/SystemUI/res/values-en-rGB/strings.xml
+++ b/packages/SystemUI/res/values-en-rGB/strings.xml
@@ -310,6 +310,8 @@
<string name="quick_settings_more_settings" msgid="326112621462813682">"More settings"</string>
<string name="quick_settings_done" msgid="3402999958839153376">"Done"</string>
<string name="quick_settings_connected" msgid="1722253542984847487">"Connected"</string>
+ <!-- no translation found for quick_settings_connected_battery_level (4136051440381328892) -->
+ <skip />
<string name="quick_settings_connecting" msgid="47623027419264404">"Connecting..."</string>
<string name="quick_settings_tethering_label" msgid="7153452060448575549">"Tethering"</string>
<string name="quick_settings_hotspot_label" msgid="6046917934974004879">"Hotspot"</string>
diff --git a/packages/SystemUI/res/values-en-rGB/strings_tv.xml b/packages/SystemUI/res/values-en-rGB/strings_tv.xml
index ffcd655..31cbd83 100644
--- a/packages/SystemUI/res/values-en-rGB/strings_tv.xml
+++ b/packages/SystemUI/res/values-en-rGB/strings_tv.xml
@@ -19,7 +19,7 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="notification_channel_tv_pip" msgid="134047986446577723">"Picture-in-Picture"</string>
+ <string name="notification_channel_tv_pip" msgid="134047986446577723">"Picture-in-picture"</string>
<string name="pip_notification_unknown_title" msgid="6289156118095849438">"(No title program)"</string>
<string name="pip_close" msgid="3480680679023423574">"Close PIP"</string>
<string name="pip_fullscreen" msgid="8604643018538487816">"Full screen"</string>
diff --git a/packages/SystemUI/res/values-en-rIN/strings.xml b/packages/SystemUI/res/values-en-rIN/strings.xml
index 80c8c88..e832f44 100644
--- a/packages/SystemUI/res/values-en-rIN/strings.xml
+++ b/packages/SystemUI/res/values-en-rIN/strings.xml
@@ -310,6 +310,8 @@
<string name="quick_settings_more_settings" msgid="326112621462813682">"More settings"</string>
<string name="quick_settings_done" msgid="3402999958839153376">"Done"</string>
<string name="quick_settings_connected" msgid="1722253542984847487">"Connected"</string>
+ <!-- no translation found for quick_settings_connected_battery_level (4136051440381328892) -->
+ <skip />
<string name="quick_settings_connecting" msgid="47623027419264404">"Connecting..."</string>
<string name="quick_settings_tethering_label" msgid="7153452060448575549">"Tethering"</string>
<string name="quick_settings_hotspot_label" msgid="6046917934974004879">"Hotspot"</string>
diff --git a/packages/SystemUI/res/values-en-rIN/strings_tv.xml b/packages/SystemUI/res/values-en-rIN/strings_tv.xml
index ffcd655..31cbd83 100644
--- a/packages/SystemUI/res/values-en-rIN/strings_tv.xml
+++ b/packages/SystemUI/res/values-en-rIN/strings_tv.xml
@@ -19,7 +19,7 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="notification_channel_tv_pip" msgid="134047986446577723">"Picture-in-Picture"</string>
+ <string name="notification_channel_tv_pip" msgid="134047986446577723">"Picture-in-picture"</string>
<string name="pip_notification_unknown_title" msgid="6289156118095849438">"(No title program)"</string>
<string name="pip_close" msgid="3480680679023423574">"Close PIP"</string>
<string name="pip_fullscreen" msgid="8604643018538487816">"Full screen"</string>
diff --git a/packages/SystemUI/res/values-es-rUS/strings.xml b/packages/SystemUI/res/values-es-rUS/strings.xml
index ed31175..0fe9d47 100644
--- a/packages/SystemUI/res/values-es-rUS/strings.xml
+++ b/packages/SystemUI/res/values-es-rUS/strings.xml
@@ -312,6 +312,8 @@
<string name="quick_settings_more_settings" msgid="326112621462813682">"Más configuraciones"</string>
<string name="quick_settings_done" msgid="3402999958839153376">"Listo"</string>
<string name="quick_settings_connected" msgid="1722253542984847487">"Conectado"</string>
+ <!-- no translation found for quick_settings_connected_battery_level (4136051440381328892) -->
+ <skip />
<string name="quick_settings_connecting" msgid="47623027419264404">"Conectando…"</string>
<string name="quick_settings_tethering_label" msgid="7153452060448575549">"Anclaje a red"</string>
<string name="quick_settings_hotspot_label" msgid="6046917934974004879">"Zona"</string>
diff --git a/packages/SystemUI/res/values-es/strings.xml b/packages/SystemUI/res/values-es/strings.xml
index a5df2a7..5a0a625 100644
--- a/packages/SystemUI/res/values-es/strings.xml
+++ b/packages/SystemUI/res/values-es/strings.xml
@@ -312,6 +312,8 @@
<string name="quick_settings_more_settings" msgid="326112621462813682">"Más opciones"</string>
<string name="quick_settings_done" msgid="3402999958839153376">"Listo"</string>
<string name="quick_settings_connected" msgid="1722253542984847487">"Conectado"</string>
+ <!-- no translation found for quick_settings_connected_battery_level (4136051440381328892) -->
+ <skip />
<string name="quick_settings_connecting" msgid="47623027419264404">"Conectando..."</string>
<string name="quick_settings_tethering_label" msgid="7153452060448575549">"Compartir Internet"</string>
<string name="quick_settings_hotspot_label" msgid="6046917934974004879">"Zona Wi-Fi"</string>
diff --git a/packages/SystemUI/res/values-et/strings.xml b/packages/SystemUI/res/values-et/strings.xml
index 3aad843..f476a35 100644
--- a/packages/SystemUI/res/values-et/strings.xml
+++ b/packages/SystemUI/res/values-et/strings.xml
@@ -312,6 +312,8 @@
<string name="quick_settings_more_settings" msgid="326112621462813682">"Rohkem seadeid"</string>
<string name="quick_settings_done" msgid="3402999958839153376">"Valmis"</string>
<string name="quick_settings_connected" msgid="1722253542984847487">"Ühendatud"</string>
+ <!-- no translation found for quick_settings_connected_battery_level (4136051440381328892) -->
+ <skip />
<string name="quick_settings_connecting" msgid="47623027419264404">"Ühenduse loomine ..."</string>
<string name="quick_settings_tethering_label" msgid="7153452060448575549">"Jagamine"</string>
<string name="quick_settings_hotspot_label" msgid="6046917934974004879">"Leviala"</string>
diff --git a/packages/SystemUI/res/values-eu/strings.xml b/packages/SystemUI/res/values-eu/strings.xml
index 76728fe..122baca 100644
--- a/packages/SystemUI/res/values-eu/strings.xml
+++ b/packages/SystemUI/res/values-eu/strings.xml
@@ -312,6 +312,8 @@
<string name="quick_settings_more_settings" msgid="326112621462813682">"Ezarpen gehiago"</string>
<string name="quick_settings_done" msgid="3402999958839153376">"Eginda"</string>
<string name="quick_settings_connected" msgid="1722253542984847487">"Konektatuta"</string>
+ <!-- no translation found for quick_settings_connected_battery_level (4136051440381328892) -->
+ <skip />
<string name="quick_settings_connecting" msgid="47623027419264404">"Konektatzen…"</string>
<string name="quick_settings_tethering_label" msgid="7153452060448575549">"Konexioa partekatzea"</string>
<string name="quick_settings_hotspot_label" msgid="6046917934974004879">"Sare publikoa"</string>
@@ -727,8 +729,8 @@
<string name="pip_phone_minimize" msgid="1079119422589131792">"Minimizatu"</string>
<string name="pip_phone_close" msgid="8416647892889710330">"Itxi"</string>
<string name="pip_phone_dismiss_hint" msgid="6351678169095923899">"Baztertzeko, arrastatu behera"</string>
- <string name="pip_menu_title" msgid="3328510504196964712">"Pantaila txikiaren menua"</string>
- <string name="pip_notification_title" msgid="3204024940158161322">"Pantaila txikian dago <xliff:g id="NAME">%s</xliff:g>"</string>
+ <string name="pip_menu_title" msgid="3328510504196964712">"Pantaila txiki gainjarriaren menua"</string>
+ <string name="pip_notification_title" msgid="3204024940158161322">"Pantaila txiki gainjarrian dago <xliff:g id="NAME">%s</xliff:g>"</string>
<string name="pip_notification_message" msgid="5619512781514343311">"Ez baduzu nahi <xliff:g id="NAME">%s</xliff:g> zerbitzuak eginbide hori erabiltzea, sakatu hau ezarpenak ireki eta aukera desaktibatzeko."</string>
<string name="pip_play" msgid="1417176722760265888">"Erreproduzitu"</string>
<string name="pip_pause" msgid="8881063404466476571">"Pausatu"</string>
diff --git a/packages/SystemUI/res/values-eu/strings_tv.xml b/packages/SystemUI/res/values-eu/strings_tv.xml
index 6dd81a6..081d1fe 100644
--- a/packages/SystemUI/res/values-eu/strings_tv.xml
+++ b/packages/SystemUI/res/values-eu/strings_tv.xml
@@ -19,7 +19,7 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="notification_channel_tv_pip" msgid="134047986446577723">"Pantaila txikia"</string>
+ <string name="notification_channel_tv_pip" msgid="134047986446577723">"Pantaila txiki gainjarria"</string>
<string name="pip_notification_unknown_title" msgid="6289156118095849438">"(Programa izengabea)"</string>
<string name="pip_close" msgid="3480680679023423574">"Itxi PIPa"</string>
<string name="pip_fullscreen" msgid="8604643018538487816">"Pantaila osoa"</string>
diff --git a/packages/SystemUI/res/values-fa/strings.xml b/packages/SystemUI/res/values-fa/strings.xml
index d89611a..a36c1c8 100644
--- a/packages/SystemUI/res/values-fa/strings.xml
+++ b/packages/SystemUI/res/values-fa/strings.xml
@@ -310,6 +310,8 @@
<string name="quick_settings_more_settings" msgid="326112621462813682">"تنظیمات بیشتر"</string>
<string name="quick_settings_done" msgid="3402999958839153376">"تمام"</string>
<string name="quick_settings_connected" msgid="1722253542984847487">"متصل"</string>
+ <!-- no translation found for quick_settings_connected_battery_level (4136051440381328892) -->
+ <skip />
<string name="quick_settings_connecting" msgid="47623027419264404">"در حال اتصال..."</string>
<string name="quick_settings_tethering_label" msgid="7153452060448575549">"اتصال به اینترنت با تلفن همراه"</string>
<string name="quick_settings_hotspot_label" msgid="6046917934974004879">"نقطه اتصال"</string>
diff --git a/packages/SystemUI/res/values-fi/strings.xml b/packages/SystemUI/res/values-fi/strings.xml
index e3193c7..307f5d4 100644
--- a/packages/SystemUI/res/values-fi/strings.xml
+++ b/packages/SystemUI/res/values-fi/strings.xml
@@ -310,6 +310,8 @@
<string name="quick_settings_more_settings" msgid="326112621462813682">"Lisäasetukset"</string>
<string name="quick_settings_done" msgid="3402999958839153376">"Valmis"</string>
<string name="quick_settings_connected" msgid="1722253542984847487">"Yhdistetty"</string>
+ <!-- no translation found for quick_settings_connected_battery_level (4136051440381328892) -->
+ <skip />
<string name="quick_settings_connecting" msgid="47623027419264404">"Yhdistetään…"</string>
<string name="quick_settings_tethering_label" msgid="7153452060448575549">"Jaettu yhteys"</string>
<string name="quick_settings_hotspot_label" msgid="6046917934974004879">"Hotspot"</string>
diff --git a/packages/SystemUI/res/values-fr-rCA/strings.xml b/packages/SystemUI/res/values-fr-rCA/strings.xml
index 1d9a7f3..5bd0179 100644
--- a/packages/SystemUI/res/values-fr-rCA/strings.xml
+++ b/packages/SystemUI/res/values-fr-rCA/strings.xml
@@ -312,6 +312,8 @@
<string name="quick_settings_more_settings" msgid="326112621462813682">"Plus de paramètres"</string>
<string name="quick_settings_done" msgid="3402999958839153376">"Terminé"</string>
<string name="quick_settings_connected" msgid="1722253542984847487">"Connecté"</string>
+ <!-- no translation found for quick_settings_connected_battery_level (4136051440381328892) -->
+ <skip />
<string name="quick_settings_connecting" msgid="47623027419264404">"Connexion en cours…"</string>
<string name="quick_settings_tethering_label" msgid="7153452060448575549">"Partage de connexion"</string>
<string name="quick_settings_hotspot_label" msgid="6046917934974004879">"Point d\'accès sans fil"</string>
diff --git a/packages/SystemUI/res/values-fr/strings.xml b/packages/SystemUI/res/values-fr/strings.xml
index 8ec4cba..2db32f9 100644
--- a/packages/SystemUI/res/values-fr/strings.xml
+++ b/packages/SystemUI/res/values-fr/strings.xml
@@ -312,6 +312,8 @@
<string name="quick_settings_more_settings" msgid="326112621462813682">"Plus de paramètres"</string>
<string name="quick_settings_done" msgid="3402999958839153376">"OK"</string>
<string name="quick_settings_connected" msgid="1722253542984847487">"Connecté"</string>
+ <!-- no translation found for quick_settings_connected_battery_level (4136051440381328892) -->
+ <skip />
<string name="quick_settings_connecting" msgid="47623027419264404">"Connexion en cours..."</string>
<string name="quick_settings_tethering_label" msgid="7153452060448575549">"Partage de connexion"</string>
<string name="quick_settings_hotspot_label" msgid="6046917934974004879">"Point d\'accès"</string>
diff --git a/packages/SystemUI/res/values-gl/strings.xml b/packages/SystemUI/res/values-gl/strings.xml
index c6281f5..aa83682 100644
--- a/packages/SystemUI/res/values-gl/strings.xml
+++ b/packages/SystemUI/res/values-gl/strings.xml
@@ -312,6 +312,8 @@
<string name="quick_settings_more_settings" msgid="326112621462813682">"Máis opcións"</string>
<string name="quick_settings_done" msgid="3402999958839153376">"Feito"</string>
<string name="quick_settings_connected" msgid="1722253542984847487">"Conectado"</string>
+ <!-- no translation found for quick_settings_connected_battery_level (4136051440381328892) -->
+ <skip />
<string name="quick_settings_connecting" msgid="47623027419264404">"Conectando..."</string>
<string name="quick_settings_tethering_label" msgid="7153452060448575549">"Conexión compartida"</string>
<string name="quick_settings_hotspot_label" msgid="6046917934974004879">"Zona wifi"</string>
diff --git a/packages/SystemUI/res/values-gu/strings.xml b/packages/SystemUI/res/values-gu/strings.xml
index b2aca44..abc3e46 100644
--- a/packages/SystemUI/res/values-gu/strings.xml
+++ b/packages/SystemUI/res/values-gu/strings.xml
@@ -310,6 +310,8 @@
<string name="quick_settings_more_settings" msgid="326112621462813682">"વધુ સેટિંગ્સ"</string>
<string name="quick_settings_done" msgid="3402999958839153376">"થઈ ગયું"</string>
<string name="quick_settings_connected" msgid="1722253542984847487">"કનેક્ટ થયેલ"</string>
+ <!-- no translation found for quick_settings_connected_battery_level (4136051440381328892) -->
+ <skip />
<string name="quick_settings_connecting" msgid="47623027419264404">"કનેક્ટ કરી રહ્યું છે..."</string>
<string name="quick_settings_tethering_label" msgid="7153452060448575549">"ટિથરિંગ"</string>
<string name="quick_settings_hotspot_label" msgid="6046917934974004879">"હોટસ્પોટ"</string>
diff --git a/packages/SystemUI/res/values-hi/strings.xml b/packages/SystemUI/res/values-hi/strings.xml
index ee688a1..add9bb6 100644
--- a/packages/SystemUI/res/values-hi/strings.xml
+++ b/packages/SystemUI/res/values-hi/strings.xml
@@ -310,6 +310,8 @@
<string name="quick_settings_more_settings" msgid="326112621462813682">"और सेटिंग"</string>
<string name="quick_settings_done" msgid="3402999958839153376">"पूर्ण"</string>
<string name="quick_settings_connected" msgid="1722253542984847487">"कनेक्ट है"</string>
+ <!-- no translation found for quick_settings_connected_battery_level (4136051440381328892) -->
+ <skip />
<string name="quick_settings_connecting" msgid="47623027419264404">"कनेक्ट हो रहा है..."</string>
<string name="quick_settings_tethering_label" msgid="7153452060448575549">"टेदरिंग"</string>
<string name="quick_settings_hotspot_label" msgid="6046917934974004879">"हॉटस्पॉट"</string>
@@ -726,7 +728,7 @@
<string name="pip_phone_close" msgid="8416647892889710330">"बंद करें"</string>
<string name="pip_phone_dismiss_hint" msgid="6351678169095923899">"खारिज करने के लिए नीचे खींचें"</string>
<string name="pip_menu_title" msgid="3328510504196964712">"चित्र में चित्र मेनू"</string>
- <string name="pip_notification_title" msgid="3204024940158161322">"<xliff:g id="NAME">%s</xliff:g> तस्वीर-में-तस्वीर के अंदर है"</string>
+ <string name="pip_notification_title" msgid="3204024940158161322">"<xliff:g id="NAME">%s</xliff:g> स्क्रीन में स्क्रीन के अंदर है"</string>
<string name="pip_notification_message" msgid="5619512781514343311">"अगर आप नहीं चाहते कि <xliff:g id="NAME">%s</xliff:g> इस सुविधा का उपयोग करे, तो सेटिंग खोलने के लिए टैप करें और उसे बंद करें ."</string>
<string name="pip_play" msgid="1417176722760265888">"चलाएं"</string>
<string name="pip_pause" msgid="8881063404466476571">"रोकें"</string>
diff --git a/packages/SystemUI/res/values-hi/strings_tv.xml b/packages/SystemUI/res/values-hi/strings_tv.xml
index 39f06f6..5e65e46 100644
--- a/packages/SystemUI/res/values-hi/strings_tv.xml
+++ b/packages/SystemUI/res/values-hi/strings_tv.xml
@@ -19,7 +19,7 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="notification_channel_tv_pip" msgid="134047986446577723">"चित्र में चित्र"</string>
+ <string name="notification_channel_tv_pip" msgid="134047986446577723">"स्क्रीन में स्क्रीन"</string>
<string name="pip_notification_unknown_title" msgid="6289156118095849438">"(कोई शीर्षक कार्यक्रम नहीं)"</string>
<string name="pip_close" msgid="3480680679023423574">"PIP बंद करें"</string>
<string name="pip_fullscreen" msgid="8604643018538487816">"पूर्ण स्क्रीन"</string>
diff --git a/packages/SystemUI/res/values-hr/strings.xml b/packages/SystemUI/res/values-hr/strings.xml
index 5706178..9c610fb 100644
--- a/packages/SystemUI/res/values-hr/strings.xml
+++ b/packages/SystemUI/res/values-hr/strings.xml
@@ -312,6 +312,8 @@
<string name="quick_settings_more_settings" msgid="326112621462813682">"Više postavki"</string>
<string name="quick_settings_done" msgid="3402999958839153376">"Gotovo"</string>
<string name="quick_settings_connected" msgid="1722253542984847487">"Povezano"</string>
+ <!-- no translation found for quick_settings_connected_battery_level (4136051440381328892) -->
+ <skip />
<string name="quick_settings_connecting" msgid="47623027419264404">"Povezivanje..."</string>
<string name="quick_settings_tethering_label" msgid="7153452060448575549">"Dijeljenje veze"</string>
<string name="quick_settings_hotspot_label" msgid="6046917934974004879">"Žarišna točka"</string>
diff --git a/packages/SystemUI/res/values-hu/strings.xml b/packages/SystemUI/res/values-hu/strings.xml
index cba779a..45ad6be 100644
--- a/packages/SystemUI/res/values-hu/strings.xml
+++ b/packages/SystemUI/res/values-hu/strings.xml
@@ -310,6 +310,8 @@
<string name="quick_settings_more_settings" msgid="326112621462813682">"További beállítások"</string>
<string name="quick_settings_done" msgid="3402999958839153376">"Kész"</string>
<string name="quick_settings_connected" msgid="1722253542984847487">"Csatlakoztatva"</string>
+ <!-- no translation found for quick_settings_connected_battery_level (4136051440381328892) -->
+ <skip />
<string name="quick_settings_connecting" msgid="47623027419264404">"Csatlakozás…"</string>
<string name="quick_settings_tethering_label" msgid="7153452060448575549">"Megosztás"</string>
<string name="quick_settings_hotspot_label" msgid="6046917934974004879">"Hotspot"</string>
diff --git a/packages/SystemUI/res/values-hy/strings.xml b/packages/SystemUI/res/values-hy/strings.xml
index 22be081..dbc484f3 100644
--- a/packages/SystemUI/res/values-hy/strings.xml
+++ b/packages/SystemUI/res/values-hy/strings.xml
@@ -310,6 +310,8 @@
<string name="quick_settings_more_settings" msgid="326112621462813682">"Հավելյալ կարգավորումներ"</string>
<string name="quick_settings_done" msgid="3402999958839153376">"Պատրաստ է"</string>
<string name="quick_settings_connected" msgid="1722253542984847487">"Կապակցված է"</string>
+ <!-- no translation found for quick_settings_connected_battery_level (4136051440381328892) -->
+ <skip />
<string name="quick_settings_connecting" msgid="47623027419264404">"Միանում է..."</string>
<string name="quick_settings_tethering_label" msgid="7153452060448575549">"Մոդեմի ռեժիմ"</string>
<string name="quick_settings_hotspot_label" msgid="6046917934974004879">"Թեժ կետ"</string>
diff --git a/packages/SystemUI/res/values-in/strings.xml b/packages/SystemUI/res/values-in/strings.xml
index 4eea7a1..1163900 100644
--- a/packages/SystemUI/res/values-in/strings.xml
+++ b/packages/SystemUI/res/values-in/strings.xml
@@ -310,6 +310,8 @@
<string name="quick_settings_more_settings" msgid="326112621462813682">"Setelan lainnya"</string>
<string name="quick_settings_done" msgid="3402999958839153376">"Selesai"</string>
<string name="quick_settings_connected" msgid="1722253542984847487">"Tersambung"</string>
+ <!-- no translation found for quick_settings_connected_battery_level (4136051440381328892) -->
+ <skip />
<string name="quick_settings_connecting" msgid="47623027419264404">"Menyambung..."</string>
<string name="quick_settings_tethering_label" msgid="7153452060448575549">"Menambatkan"</string>
<string name="quick_settings_hotspot_label" msgid="6046917934974004879">"Hotspot"</string>
@@ -725,8 +727,8 @@
<string name="pip_phone_minimize" msgid="1079119422589131792">"Minimalkan"</string>
<string name="pip_phone_close" msgid="8416647892889710330">"Tutup"</string>
<string name="pip_phone_dismiss_hint" msgid="6351678169095923899">"Seret ke bawah untuk menutup"</string>
- <string name="pip_menu_title" msgid="3328510504196964712">"Menu gambar dalam gambar"</string>
- <string name="pip_notification_title" msgid="3204024940158161322">"<xliff:g id="NAME">%s</xliff:g> adalah gambar-dalam-gambar"</string>
+ <string name="pip_menu_title" msgid="3328510504196964712">"Menu picture in picture"</string>
+ <string name="pip_notification_title" msgid="3204024940158161322">"<xliff:g id="NAME">%s</xliff:g> adalah picture-in-picture"</string>
<string name="pip_notification_message" msgid="5619512781514343311">"Jika Anda tidak ingin <xliff:g id="NAME">%s</xliff:g> menggunakan fitur ini, tap untuk membuka setelan dan menonaktifkannya."</string>
<string name="pip_play" msgid="1417176722760265888">"Putar"</string>
<string name="pip_pause" msgid="8881063404466476571">"Jeda"</string>
diff --git a/packages/SystemUI/res/values-in/strings_tv.xml b/packages/SystemUI/res/values-in/strings_tv.xml
index ca3b32f..a1aa168 100644
--- a/packages/SystemUI/res/values-in/strings_tv.xml
+++ b/packages/SystemUI/res/values-in/strings_tv.xml
@@ -19,7 +19,7 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="notification_channel_tv_pip" msgid="134047986446577723">"Gambar-dalam-Gambar"</string>
+ <string name="notification_channel_tv_pip" msgid="134047986446577723">"Picture-in-picture"</string>
<string name="pip_notification_unknown_title" msgid="6289156118095849438">"(Program tanpa judul)"</string>
<string name="pip_close" msgid="3480680679023423574">"Tutup PIP"</string>
<string name="pip_fullscreen" msgid="8604643018538487816">"Layar penuh"</string>
diff --git a/packages/SystemUI/res/values-is/strings.xml b/packages/SystemUI/res/values-is/strings.xml
index 243c5d7..8c1c61d 100644
--- a/packages/SystemUI/res/values-is/strings.xml
+++ b/packages/SystemUI/res/values-is/strings.xml
@@ -310,6 +310,8 @@
<string name="quick_settings_more_settings" msgid="326112621462813682">"Fleiri stillingar"</string>
<string name="quick_settings_done" msgid="3402999958839153376">"Lokið"</string>
<string name="quick_settings_connected" msgid="1722253542984847487">"Tengt"</string>
+ <!-- no translation found for quick_settings_connected_battery_level (4136051440381328892) -->
+ <skip />
<string name="quick_settings_connecting" msgid="47623027419264404">"Tengist..."</string>
<string name="quick_settings_tethering_label" msgid="7153452060448575549">"Tjóðrun"</string>
<string name="quick_settings_hotspot_label" msgid="6046917934974004879">"Heitur reitur"</string>
diff --git a/packages/SystemUI/res/values-it/strings.xml b/packages/SystemUI/res/values-it/strings.xml
index 0eca3ec..df3c443 100644
--- a/packages/SystemUI/res/values-it/strings.xml
+++ b/packages/SystemUI/res/values-it/strings.xml
@@ -312,6 +312,8 @@
<string name="quick_settings_more_settings" msgid="326112621462813682">"Altre impostazioni"</string>
<string name="quick_settings_done" msgid="3402999958839153376">"Fine"</string>
<string name="quick_settings_connected" msgid="1722253542984847487">"Connesso"</string>
+ <!-- no translation found for quick_settings_connected_battery_level (4136051440381328892) -->
+ <skip />
<string name="quick_settings_connecting" msgid="47623027419264404">"Connessione..."</string>
<string name="quick_settings_tethering_label" msgid="7153452060448575549">"Tethering"</string>
<string name="quick_settings_hotspot_label" msgid="6046917934974004879">"Hotspot"</string>
@@ -727,8 +729,8 @@
<string name="pip_phone_minimize" msgid="1079119422589131792">"Riduci a icona"</string>
<string name="pip_phone_close" msgid="8416647892889710330">"Chiudi"</string>
<string name="pip_phone_dismiss_hint" msgid="6351678169095923899">"Trascina verso il basso per ignorare"</string>
- <string name="pip_menu_title" msgid="3328510504196964712">"Menu Picture-in-picture"</string>
- <string name="pip_notification_title" msgid="3204024940158161322">"<xliff:g id="NAME">%s</xliff:g> è in picture-in-picture"</string>
+ <string name="pip_menu_title" msgid="3328510504196964712">"Menu Picture in picture"</string>
+ <string name="pip_notification_title" msgid="3204024940158161322">"<xliff:g id="NAME">%s</xliff:g> è in Picture in picture"</string>
<string name="pip_notification_message" msgid="5619512781514343311">"Se non desideri che l\'app <xliff:g id="NAME">%s</xliff:g> utilizzi questa funzione, tocca per aprire le impostazioni e disattivarla."</string>
<string name="pip_play" msgid="1417176722760265888">"Riproduci"</string>
<string name="pip_pause" msgid="8881063404466476571">"Metti in pausa"</string>
diff --git a/packages/SystemUI/res/values-it/strings_tv.xml b/packages/SystemUI/res/values-it/strings_tv.xml
index 629e306..81d76d5 100644
--- a/packages/SystemUI/res/values-it/strings_tv.xml
+++ b/packages/SystemUI/res/values-it/strings_tv.xml
@@ -19,7 +19,7 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="notification_channel_tv_pip" msgid="134047986446577723">"Picture-in-Picture"</string>
+ <string name="notification_channel_tv_pip" msgid="134047986446577723">"Picture in picture"</string>
<string name="pip_notification_unknown_title" msgid="6289156118095849438">"(Programma senza titolo)"</string>
<string name="pip_close" msgid="3480680679023423574">"Chiudi PIP"</string>
<string name="pip_fullscreen" msgid="8604643018538487816">"Schermo intero"</string>
diff --git a/packages/SystemUI/res/values-iw/strings.xml b/packages/SystemUI/res/values-iw/strings.xml
index b4e09fb..d4cf5d3 100644
--- a/packages/SystemUI/res/values-iw/strings.xml
+++ b/packages/SystemUI/res/values-iw/strings.xml
@@ -314,6 +314,8 @@
<string name="quick_settings_more_settings" msgid="326112621462813682">"הגדרות נוספות"</string>
<string name="quick_settings_done" msgid="3402999958839153376">"בוצע"</string>
<string name="quick_settings_connected" msgid="1722253542984847487">"מחובר"</string>
+ <!-- no translation found for quick_settings_connected_battery_level (4136051440381328892) -->
+ <skip />
<string name="quick_settings_connecting" msgid="47623027419264404">"מתחבר..."</string>
<string name="quick_settings_tethering_label" msgid="7153452060448575549">"שיתוף אינטרנט בין ניידים"</string>
<string name="quick_settings_hotspot_label" msgid="6046917934974004879">"נקודה לשיתוף אינטרנט"</string>
diff --git a/packages/SystemUI/res/values-ja/strings.xml b/packages/SystemUI/res/values-ja/strings.xml
index 55437b4..3eb9060 100644
--- a/packages/SystemUI/res/values-ja/strings.xml
+++ b/packages/SystemUI/res/values-ja/strings.xml
@@ -312,6 +312,8 @@
<string name="quick_settings_more_settings" msgid="326112621462813682">"詳細設定"</string>
<string name="quick_settings_done" msgid="3402999958839153376">"完了"</string>
<string name="quick_settings_connected" msgid="1722253542984847487">"接続済み"</string>
+ <!-- no translation found for quick_settings_connected_battery_level (4136051440381328892) -->
+ <skip />
<string name="quick_settings_connecting" msgid="47623027419264404">"接続しています..."</string>
<string name="quick_settings_tethering_label" msgid="7153452060448575549">"テザリング"</string>
<string name="quick_settings_hotspot_label" msgid="6046917934974004879">"アクセスポイント"</string>
@@ -727,8 +729,8 @@
<string name="pip_phone_minimize" msgid="1079119422589131792">"最小化"</string>
<string name="pip_phone_close" msgid="8416647892889710330">"閉じる"</string>
<string name="pip_phone_dismiss_hint" msgid="6351678169095923899">"下にドラッグして閉じる"</string>
- <string name="pip_menu_title" msgid="3328510504196964712">"PIP メニュー"</string>
- <string name="pip_notification_title" msgid="3204024940158161322">"<xliff:g id="NAME">%s</xliff:g>は PIP 表示中です"</string>
+ <string name="pip_menu_title" msgid="3328510504196964712">"ピクチャー イン ピクチャー メニュー"</string>
+ <string name="pip_notification_title" msgid="3204024940158161322">"<xliff:g id="NAME">%s</xliff:g>はピクチャー イン ピクチャーで表示中です"</string>
<string name="pip_notification_message" msgid="5619512781514343311">"<xliff:g id="NAME">%s</xliff:g>でこの機能を使用しない場合は、タップして設定を開いて OFF にしてください。"</string>
<string name="pip_play" msgid="1417176722760265888">"再生"</string>
<string name="pip_pause" msgid="8881063404466476571">"一時停止"</string>
diff --git a/packages/SystemUI/res/values-ja/strings_tv.xml b/packages/SystemUI/res/values-ja/strings_tv.xml
index 134bb18..4596551 100644
--- a/packages/SystemUI/res/values-ja/strings_tv.xml
+++ b/packages/SystemUI/res/values-ja/strings_tv.xml
@@ -19,7 +19,7 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="notification_channel_tv_pip" msgid="134047986446577723">"PIP"</string>
+ <string name="notification_channel_tv_pip" msgid="134047986446577723">"ピクチャー イン ピクチャー"</string>
<string name="pip_notification_unknown_title" msgid="6289156118095849438">"(無題の番組)"</string>
<string name="pip_close" msgid="3480680679023423574">"PIP を閉じる"</string>
<string name="pip_fullscreen" msgid="8604643018538487816">"全画面表示"</string>
diff --git a/packages/SystemUI/res/values-ka/strings.xml b/packages/SystemUI/res/values-ka/strings.xml
index 88e1d05..c7b977a 100644
--- a/packages/SystemUI/res/values-ka/strings.xml
+++ b/packages/SystemUI/res/values-ka/strings.xml
@@ -310,6 +310,8 @@
<string name="quick_settings_more_settings" msgid="326112621462813682">"დამატებითი პარამეტრები"</string>
<string name="quick_settings_done" msgid="3402999958839153376">"დასრულდა"</string>
<string name="quick_settings_connected" msgid="1722253542984847487">"დაკავშირებულია"</string>
+ <!-- no translation found for quick_settings_connected_battery_level (4136051440381328892) -->
+ <skip />
<string name="quick_settings_connecting" msgid="47623027419264404">"დაკავშირება..."</string>
<string name="quick_settings_tethering_label" msgid="7153452060448575549">"მოდემის რეჟიმი"</string>
<string name="quick_settings_hotspot_label" msgid="6046917934974004879">"წვდომის წერტილი"</string>
diff --git a/packages/SystemUI/res/values-kk/strings.xml b/packages/SystemUI/res/values-kk/strings.xml
index 97bf3c0..dded6d3 100644
--- a/packages/SystemUI/res/values-kk/strings.xml
+++ b/packages/SystemUI/res/values-kk/strings.xml
@@ -310,6 +310,8 @@
<string name="quick_settings_more_settings" msgid="326112621462813682">"Қосымша параметрлер"</string>
<string name="quick_settings_done" msgid="3402999958839153376">"Дайын"</string>
<string name="quick_settings_connected" msgid="1722253542984847487">"Қосылды"</string>
+ <!-- no translation found for quick_settings_connected_battery_level (4136051440381328892) -->
+ <skip />
<string name="quick_settings_connecting" msgid="47623027419264404">"Қосылуда…"</string>
<string name="quick_settings_tethering_label" msgid="7153452060448575549">"Тетеринг"</string>
<string name="quick_settings_hotspot_label" msgid="6046917934974004879">"Хот-спот"</string>
diff --git a/packages/SystemUI/res/values-kk/strings_tv.xml b/packages/SystemUI/res/values-kk/strings_tv.xml
index 305ad2e..7112017 100644
--- a/packages/SystemUI/res/values-kk/strings_tv.xml
+++ b/packages/SystemUI/res/values-kk/strings_tv.xml
@@ -19,7 +19,7 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="notification_channel_tv_pip" msgid="134047986446577723">"Сурет ішіндегі сурет"</string>
+ <string name="notification_channel_tv_pip" msgid="134047986446577723">"Суреттегі сурет"</string>
<string name="pip_notification_unknown_title" msgid="6289156118095849438">"(Атаусыз бағдарлама)"</string>
<string name="pip_close" msgid="3480680679023423574">"PIP жабу"</string>
<string name="pip_fullscreen" msgid="8604643018538487816">"Толық экран"</string>
diff --git a/packages/SystemUI/res/values-km/strings.xml b/packages/SystemUI/res/values-km/strings.xml
index 35c6280..b01edb2 100644
--- a/packages/SystemUI/res/values-km/strings.xml
+++ b/packages/SystemUI/res/values-km/strings.xml
@@ -310,6 +310,8 @@
<string name="quick_settings_more_settings" msgid="326112621462813682">"ការកំណត់ច្រើនទៀត"</string>
<string name="quick_settings_done" msgid="3402999958839153376">"រួចរាល់"</string>
<string name="quick_settings_connected" msgid="1722253542984847487">"បានភ្ជាប់"</string>
+ <!-- no translation found for quick_settings_connected_battery_level (4136051440381328892) -->
+ <skip />
<string name="quick_settings_connecting" msgid="47623027419264404">"កំពុងតភ្ជាប់..."</string>
<string name="quick_settings_tethering_label" msgid="7153452060448575549">"ការភ្ជាប់"</string>
<string name="quick_settings_hotspot_label" msgid="6046917934974004879">"ហតស្ប៉ត"</string>
@@ -725,8 +727,8 @@
<string name="pip_phone_minimize" msgid="1079119422589131792">"បង្រួម"</string>
<string name="pip_phone_close" msgid="8416647892889710330">"បិទ"</string>
<string name="pip_phone_dismiss_hint" msgid="6351678169095923899">"អូសចុះក្រោមដើម្បីបដិសេធ"</string>
- <string name="pip_menu_title" msgid="3328510504196964712">"ម៉ឺនុយរូបភាពក្នុងរូបភាព"</string>
- <string name="pip_notification_title" msgid="3204024940158161322">"<xliff:g id="NAME">%s</xliff:g> ស្ថិតក្នុងមុខងាររូបភាពក្នុងរូបភាព"</string>
+ <string name="pip_menu_title" msgid="3328510504196964712">"ម៉ឺនុយរូបក្នុងរូប"</string>
+ <string name="pip_notification_title" msgid="3204024940158161322">"<xliff:g id="NAME">%s</xliff:g> ស្ថិតក្នុងមុខងាររូបក្នុងរូប"</string>
<string name="pip_notification_message" msgid="5619512781514343311">"ប្រសិនបើអ្នកមិនចង់ឲ្យ <xliff:g id="NAME">%s</xliff:g> ប្រើមុខងារនេះ សូមចុចបើកការកំណត់ រួចបិទវា។"</string>
<string name="pip_play" msgid="1417176722760265888">"លេង"</string>
<string name="pip_pause" msgid="8881063404466476571">"ផ្អាក"</string>
diff --git a/packages/SystemUI/res/values-km/strings_tv.xml b/packages/SystemUI/res/values-km/strings_tv.xml
index 5da818e..641bba3 100644
--- a/packages/SystemUI/res/values-km/strings_tv.xml
+++ b/packages/SystemUI/res/values-km/strings_tv.xml
@@ -19,7 +19,7 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="notification_channel_tv_pip" msgid="134047986446577723">"រូបភាពក្នុងរូបភាព"</string>
+ <string name="notification_channel_tv_pip" msgid="134047986446577723">"រូបក្នុងរូប"</string>
<string name="pip_notification_unknown_title" msgid="6289156118095849438">"(កម្មវិធីគ្មានចំណងជើង)"</string>
<string name="pip_close" msgid="3480680679023423574">"បិទ PIP"</string>
<string name="pip_fullscreen" msgid="8604643018538487816">"ពេញអេក្រង់"</string>
diff --git a/packages/SystemUI/res/values-kn/strings.xml b/packages/SystemUI/res/values-kn/strings.xml
index 525da4a..cad05a6 100644
--- a/packages/SystemUI/res/values-kn/strings.xml
+++ b/packages/SystemUI/res/values-kn/strings.xml
@@ -310,6 +310,8 @@
<string name="quick_settings_more_settings" msgid="326112621462813682">"ಹೆಚ್ಚಿನ ಸೆಟ್ಟಿಂಗ್ಗಳು"</string>
<string name="quick_settings_done" msgid="3402999958839153376">"ಮುಗಿದಿದೆ"</string>
<string name="quick_settings_connected" msgid="1722253542984847487">"ಸಂಪರ್ಕಗೊಂಡಿದೆ"</string>
+ <!-- no translation found for quick_settings_connected_battery_level (4136051440381328892) -->
+ <skip />
<string name="quick_settings_connecting" msgid="47623027419264404">"ಸಂಪರ್ಕಿಸಲಾಗುತ್ತಿದೆ..."</string>
<string name="quick_settings_tethering_label" msgid="7153452060448575549">"ಟೆಥರಿಂಗ್"</string>
<string name="quick_settings_hotspot_label" msgid="6046917934974004879">"ಹಾಟ್ಸ್ಪಾಟ್"</string>
diff --git a/packages/SystemUI/res/values-ko/strings.xml b/packages/SystemUI/res/values-ko/strings.xml
index 32202076..1df6377 100644
--- a/packages/SystemUI/res/values-ko/strings.xml
+++ b/packages/SystemUI/res/values-ko/strings.xml
@@ -312,6 +312,8 @@
<string name="quick_settings_more_settings" msgid="326112621462813682">"설정 더보기"</string>
<string name="quick_settings_done" msgid="3402999958839153376">"완료"</string>
<string name="quick_settings_connected" msgid="1722253542984847487">"연결됨"</string>
+ <!-- no translation found for quick_settings_connected_battery_level (4136051440381328892) -->
+ <skip />
<string name="quick_settings_connecting" msgid="47623027419264404">"연결 중..."</string>
<string name="quick_settings_tethering_label" msgid="7153452060448575549">"테더링"</string>
<string name="quick_settings_hotspot_label" msgid="6046917934974004879">"핫스팟"</string>
diff --git a/packages/SystemUI/res/values-ky/strings.xml b/packages/SystemUI/res/values-ky/strings.xml
index 444e225..ce3edb5 100644
--- a/packages/SystemUI/res/values-ky/strings.xml
+++ b/packages/SystemUI/res/values-ky/strings.xml
@@ -310,6 +310,8 @@
<string name="quick_settings_more_settings" msgid="326112621462813682">"Дагы жөндөөлөр"</string>
<string name="quick_settings_done" msgid="3402999958839153376">"Бүттү"</string>
<string name="quick_settings_connected" msgid="1722253542984847487">"Туташкан"</string>
+ <!-- no translation found for quick_settings_connected_battery_level (4136051440381328892) -->
+ <skip />
<string name="quick_settings_connecting" msgid="47623027419264404">"Туташууда…"</string>
<string name="quick_settings_tethering_label" msgid="7153452060448575549">"Тетеринг"</string>
<string name="quick_settings_hotspot_label" msgid="6046917934974004879">"Туташуу чекити"</string>
diff --git a/packages/SystemUI/res/values-lo/strings.xml b/packages/SystemUI/res/values-lo/strings.xml
index b6c4aa7..5a889d8 100644
--- a/packages/SystemUI/res/values-lo/strings.xml
+++ b/packages/SystemUI/res/values-lo/strings.xml
@@ -310,6 +310,8 @@
<string name="quick_settings_more_settings" msgid="326112621462813682">"ການຕັ້ງຄ່າເພີ່ມເຕີມ"</string>
<string name="quick_settings_done" msgid="3402999958839153376">"ແລ້ວໆ"</string>
<string name="quick_settings_connected" msgid="1722253542984847487">"ເຊື່ອມຕໍ່ແລ້ວ"</string>
+ <!-- no translation found for quick_settings_connected_battery_level (4136051440381328892) -->
+ <skip />
<string name="quick_settings_connecting" msgid="47623027419264404">"ກຳລັງເຊື່ອມຕໍ່..."</string>
<string name="quick_settings_tethering_label" msgid="7153452060448575549">"ການປ່ອນສັນຍານ"</string>
<string name="quick_settings_hotspot_label" msgid="6046917934974004879">"ຮັອດສະປອດ"</string>
diff --git a/packages/SystemUI/res/values-lt/strings.xml b/packages/SystemUI/res/values-lt/strings.xml
index 78f0c73..e6df867 100644
--- a/packages/SystemUI/res/values-lt/strings.xml
+++ b/packages/SystemUI/res/values-lt/strings.xml
@@ -314,6 +314,8 @@
<string name="quick_settings_more_settings" msgid="326112621462813682">"Daugiau nustatymų"</string>
<string name="quick_settings_done" msgid="3402999958839153376">"Atlikta"</string>
<string name="quick_settings_connected" msgid="1722253542984847487">"Prijungtas"</string>
+ <!-- no translation found for quick_settings_connected_battery_level (4136051440381328892) -->
+ <skip />
<string name="quick_settings_connecting" msgid="47623027419264404">"Prisijungiama..."</string>
<string name="quick_settings_tethering_label" msgid="7153452060448575549">"Susiejimas"</string>
<string name="quick_settings_hotspot_label" msgid="6046917934974004879">"Viešosios interneto prieigos taškas"</string>
diff --git a/packages/SystemUI/res/values-lv/strings.xml b/packages/SystemUI/res/values-lv/strings.xml
index 336a246..d45096d 100644
--- a/packages/SystemUI/res/values-lv/strings.xml
+++ b/packages/SystemUI/res/values-lv/strings.xml
@@ -312,6 +312,8 @@
<string name="quick_settings_more_settings" msgid="326112621462813682">"Vairāk iestatījumu"</string>
<string name="quick_settings_done" msgid="3402999958839153376">"Gatavs"</string>
<string name="quick_settings_connected" msgid="1722253542984847487">"Pievienota"</string>
+ <!-- no translation found for quick_settings_connected_battery_level (4136051440381328892) -->
+ <skip />
<string name="quick_settings_connecting" msgid="47623027419264404">"Notiek savienojuma izveide…"</string>
<string name="quick_settings_tethering_label" msgid="7153452060448575549">"Piesaiste"</string>
<string name="quick_settings_hotspot_label" msgid="6046917934974004879">"Tīklājs"</string>
diff --git a/packages/SystemUI/res/values-mk/strings.xml b/packages/SystemUI/res/values-mk/strings.xml
index 12973fd..9aa8fc4 100644
--- a/packages/SystemUI/res/values-mk/strings.xml
+++ b/packages/SystemUI/res/values-mk/strings.xml
@@ -310,6 +310,8 @@
<string name="quick_settings_more_settings" msgid="326112621462813682">"Повеќе поставки"</string>
<string name="quick_settings_done" msgid="3402999958839153376">"Готово"</string>
<string name="quick_settings_connected" msgid="1722253542984847487">"Поврзано"</string>
+ <!-- no translation found for quick_settings_connected_battery_level (4136051440381328892) -->
+ <skip />
<string name="quick_settings_connecting" msgid="47623027419264404">"Се поврзува..."</string>
<string name="quick_settings_tethering_label" msgid="7153452060448575549">"Поврзување"</string>
<string name="quick_settings_hotspot_label" msgid="6046917934974004879">"Точка на пристап"</string>
diff --git a/packages/SystemUI/res/values-ml/strings.xml b/packages/SystemUI/res/values-ml/strings.xml
index a07c868..3976176 100644
--- a/packages/SystemUI/res/values-ml/strings.xml
+++ b/packages/SystemUI/res/values-ml/strings.xml
@@ -310,6 +310,8 @@
<string name="quick_settings_more_settings" msgid="326112621462813682">"കൂടുതൽ ക്രമീകരണങ്ങൾ"</string>
<string name="quick_settings_done" msgid="3402999958839153376">"പൂർത്തിയാക്കി"</string>
<string name="quick_settings_connected" msgid="1722253542984847487">"കണക്റ്റുചെയ്തു"</string>
+ <!-- no translation found for quick_settings_connected_battery_level (4136051440381328892) -->
+ <skip />
<string name="quick_settings_connecting" msgid="47623027419264404">"കണക്റ്റുചെയ്യുന്നു..."</string>
<string name="quick_settings_tethering_label" msgid="7153452060448575549">"ടെതറിംഗ്"</string>
<string name="quick_settings_hotspot_label" msgid="6046917934974004879">"ഹോട്ട്സ്പോട്ട്"</string>
diff --git a/packages/SystemUI/res/values-mn/strings.xml b/packages/SystemUI/res/values-mn/strings.xml
index 20bb6ea..f00e8eb 100644
--- a/packages/SystemUI/res/values-mn/strings.xml
+++ b/packages/SystemUI/res/values-mn/strings.xml
@@ -308,6 +308,8 @@
<string name="quick_settings_more_settings" msgid="326112621462813682">"Өөр тохиргоо"</string>
<string name="quick_settings_done" msgid="3402999958839153376">"Дууссан"</string>
<string name="quick_settings_connected" msgid="1722253542984847487">"Холбогдсон"</string>
+ <!-- no translation found for quick_settings_connected_battery_level (4136051440381328892) -->
+ <skip />
<string name="quick_settings_connecting" msgid="47623027419264404">"Холбогдож байна..."</string>
<string name="quick_settings_tethering_label" msgid="7153452060448575549">"Модем болгох"</string>
<string name="quick_settings_hotspot_label" msgid="6046917934974004879">"Сүлжээний цэг"</string>
@@ -725,8 +727,8 @@
<string name="pip_phone_minimize" msgid="1079119422589131792">"Багасгах"</string>
<string name="pip_phone_close" msgid="8416647892889710330">"Хаах"</string>
<string name="pip_phone_dismiss_hint" msgid="6351678169095923899">"Хаахын тулд доош чирэх"</string>
- <string name="pip_menu_title" msgid="3328510504196964712">"Зургийн цэсэнд байгаа зураг"</string>
- <string name="pip_notification_title" msgid="3204024940158161322">"<xliff:g id="NAME">%s</xliff:g> зураг доторх зурганд байна"</string>
+ <string name="pip_menu_title" msgid="3328510504196964712">"Дэлгэцэн доторх дэлгэцийн цэс"</string>
+ <string name="pip_notification_title" msgid="3204024940158161322">"<xliff:g id="NAME">%s</xliff:g> дэлгэцэн доторх дэлгэцэд байна"</string>
<string name="pip_notification_message" msgid="5619512781514343311">"Та <xliff:g id="NAME">%s</xliff:g>-д энэ онцлогийг ашиглуулахыг хүсэхгүй байвал тохиргоог нээгээд, үүнийг унтраана уу."</string>
<string name="pip_play" msgid="1417176722760265888">"Тоглуулах"</string>
<string name="pip_pause" msgid="8881063404466476571">"Түр зогсоох"</string>
diff --git a/packages/SystemUI/res/values-mn/strings_tv.xml b/packages/SystemUI/res/values-mn/strings_tv.xml
index bbc94c8..e250c2d 100644
--- a/packages/SystemUI/res/values-mn/strings_tv.xml
+++ b/packages/SystemUI/res/values-mn/strings_tv.xml
@@ -19,7 +19,7 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="notification_channel_tv_pip" msgid="134047986446577723">"Зураг-доторх-Зураг"</string>
+ <string name="notification_channel_tv_pip" msgid="134047986446577723">"Дэлгэцэн-доторх-Дэлгэц"</string>
<string name="pip_notification_unknown_title" msgid="6289156118095849438">"(Гарчиггүй хөтөлбөр)"</string>
<string name="pip_close" msgid="3480680679023423574">"PIP-г хаах"</string>
<string name="pip_fullscreen" msgid="8604643018538487816">"Бүтэн дэлгэц"</string>
diff --git a/packages/SystemUI/res/values-mr/strings.xml b/packages/SystemUI/res/values-mr/strings.xml
index 2ddf75c..2ff5e63 100644
--- a/packages/SystemUI/res/values-mr/strings.xml
+++ b/packages/SystemUI/res/values-mr/strings.xml
@@ -310,6 +310,8 @@
<string name="quick_settings_more_settings" msgid="326112621462813682">"अधिक सेटिंग्ज"</string>
<string name="quick_settings_done" msgid="3402999958839153376">"पूर्ण झाले"</string>
<string name="quick_settings_connected" msgid="1722253542984847487">"कनेक्ट केलेले"</string>
+ <!-- no translation found for quick_settings_connected_battery_level (4136051440381328892) -->
+ <skip />
<string name="quick_settings_connecting" msgid="47623027419264404">"कनेक्ट करीत आहे..."</string>
<string name="quick_settings_tethering_label" msgid="7153452060448575549">"टेदरिंग"</string>
<string name="quick_settings_hotspot_label" msgid="6046917934974004879">"हॉटस्पॉट"</string>
diff --git a/packages/SystemUI/res/values-ms/strings.xml b/packages/SystemUI/res/values-ms/strings.xml
index 6a30d506..1c6e543 100644
--- a/packages/SystemUI/res/values-ms/strings.xml
+++ b/packages/SystemUI/res/values-ms/strings.xml
@@ -310,6 +310,8 @@
<string name="quick_settings_more_settings" msgid="326112621462813682">"Lagi tetapan"</string>
<string name="quick_settings_done" msgid="3402999958839153376">"Selesai"</string>
<string name="quick_settings_connected" msgid="1722253542984847487">"Disambungkan"</string>
+ <!-- no translation found for quick_settings_connected_battery_level (4136051440381328892) -->
+ <skip />
<string name="quick_settings_connecting" msgid="47623027419264404">"Menyambung..."</string>
<string name="quick_settings_tethering_label" msgid="7153452060448575549">"Penambatan"</string>
<string name="quick_settings_hotspot_label" msgid="6046917934974004879">"Tempat liputan"</string>
diff --git a/packages/SystemUI/res/values-my/strings.xml b/packages/SystemUI/res/values-my/strings.xml
index 6a42627..cf9baee 100644
--- a/packages/SystemUI/res/values-my/strings.xml
+++ b/packages/SystemUI/res/values-my/strings.xml
@@ -262,7 +262,7 @@
<string name="accessibility_rotation_lock_on_portrait" msgid="5809367521644012115">"ဖန်သားပြင် အနေအထားက ဒေါင်လိုက်အဖြစ် ပုံသေ လုပ်ထားပါသည်"</string>
<string name="accessibility_rotation_lock_off_changed" msgid="8134601071026305153">"ယခုတော့ မျက်နှာပြင်သည် အလိုအလျောက် လည်နေမည်။"</string>
<string name="accessibility_rotation_lock_on_landscape_changed" msgid="3135965553707519743">"မျက်နှာပြင် အနေအထားကို ဘေးတိုက် အဖြစ် သော့ချထားသည်။"</string>
- <string name="accessibility_rotation_lock_on_portrait_changed" msgid="8922481981834012126">"မျက်နှာပြင် အနေအထားကို ထောင်လိုက် အဖြစ် သော့ချထားသည်။"</string>
+ <string name="accessibility_rotation_lock_on_portrait_changed" msgid="8922481981834012126">"မျက်နှာပြင်အနေအထားကို ထောင်လိုက်အဖြစ် ပုံသေသတ်မှတ်ထားသည်။"</string>
<string name="dessert_case" msgid="1295161776223959221">"မုန့်ထည့်သော ပုံး"</string>
<string name="start_dreams" msgid="5640361424498338327">"ဖန်သားပြင်အသုံးပြုမှု ချွေတာမှုစနစ်"</string>
<string name="ethernet_label" msgid="7967563676324087464">"အီသာနက်"</string>
@@ -310,6 +310,8 @@
<string name="quick_settings_more_settings" msgid="326112621462813682">"နောက်ထပ် ဆက်တင်များ"</string>
<string name="quick_settings_done" msgid="3402999958839153376">"လုပ်ပြီး"</string>
<string name="quick_settings_connected" msgid="1722253542984847487">"ချိတ်ဆက်ထား"</string>
+ <!-- no translation found for quick_settings_connected_battery_level (4136051440381328892) -->
+ <skip />
<string name="quick_settings_connecting" msgid="47623027419264404">"ဆက်သွယ်နေ..."</string>
<string name="quick_settings_tethering_label" msgid="7153452060448575549">"တွဲချီပေးခြင်း"</string>
<string name="quick_settings_hotspot_label" msgid="6046917934974004879">"ဟော့စပေါ့"</string>
diff --git a/packages/SystemUI/res/values-nb/strings.xml b/packages/SystemUI/res/values-nb/strings.xml
index 71c28ac..e14646e 100644
--- a/packages/SystemUI/res/values-nb/strings.xml
+++ b/packages/SystemUI/res/values-nb/strings.xml
@@ -310,6 +310,8 @@
<string name="quick_settings_more_settings" msgid="326112621462813682">"Flere innstillinger"</string>
<string name="quick_settings_done" msgid="3402999958839153376">"Ferdig"</string>
<string name="quick_settings_connected" msgid="1722253542984847487">"Tilkoblet"</string>
+ <!-- no translation found for quick_settings_connected_battery_level (4136051440381328892) -->
+ <skip />
<string name="quick_settings_connecting" msgid="47623027419264404">"Kobler til …"</string>
<string name="quick_settings_tethering_label" msgid="7153452060448575549">"Internettdeling"</string>
<string name="quick_settings_hotspot_label" msgid="6046917934974004879">"Wi-Fi-sone"</string>
diff --git a/packages/SystemUI/res/values-ne/strings.xml b/packages/SystemUI/res/values-ne/strings.xml
index 6c6b62c..a174672 100644
--- a/packages/SystemUI/res/values-ne/strings.xml
+++ b/packages/SystemUI/res/values-ne/strings.xml
@@ -310,6 +310,8 @@
<string name="quick_settings_more_settings" msgid="326112621462813682">"थप सेटिङहरू"</string>
<string name="quick_settings_done" msgid="3402999958839153376">"भयो"</string>
<string name="quick_settings_connected" msgid="1722253542984847487">"जोडिएको"</string>
+ <!-- no translation found for quick_settings_connected_battery_level (4136051440381328892) -->
+ <skip />
<string name="quick_settings_connecting" msgid="47623027419264404">"जडान हुँदै..."</string>
<string name="quick_settings_tethering_label" msgid="7153452060448575549">"टेदर गर्दै"</string>
<string name="quick_settings_hotspot_label" msgid="6046917934974004879">"हटस्पट"</string>
@@ -726,7 +728,7 @@
<string name="pip_phone_close" msgid="8416647892889710330">"बन्द गर्नुहोस्"</string>
<string name="pip_phone_dismiss_hint" msgid="6351678169095923899">"खारेज गर्न तल तान्नुहोस्"</string>
<string name="pip_menu_title" msgid="3328510504196964712">"तस्बिर मेनुमा तस्बिर"</string>
- <string name="pip_notification_title" msgid="3204024940158161322">"<xliff:g id="NAME">%s</xliff:g> तस्बिरभित्रको तस्बिरमा छ"</string>
+ <string name="pip_notification_title" msgid="3204024940158161322">"<xliff:g id="NAME">%s</xliff:g> Picture-in-picture मा छ"</string>
<string name="pip_notification_message" msgid="5619512781514343311">"तपाईं <xliff:g id="NAME">%s</xliff:g> ले सुविधा प्रयोग नगरोस् भन्ने चाहनुहुन्छ भने ट्याप गरेर सेटिङहरू खोल्नुहोस् र यसलाई निष्क्रिय पार्नुहोस्।"</string>
<string name="pip_play" msgid="1417176722760265888">"प्ले गर्नुहोस्"</string>
<string name="pip_pause" msgid="8881063404466476571">"पज गर्नुहोस्"</string>
diff --git a/packages/SystemUI/res/values-ne/strings_tv.xml b/packages/SystemUI/res/values-ne/strings_tv.xml
index 2c5c186..2e42b6c 100644
--- a/packages/SystemUI/res/values-ne/strings_tv.xml
+++ b/packages/SystemUI/res/values-ne/strings_tv.xml
@@ -19,7 +19,7 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="notification_channel_tv_pip" msgid="134047986446577723">"तस्बिरभित्रको तस्बिर"</string>
+ <string name="notification_channel_tv_pip" msgid="134047986446577723">"Picture-in-Picture"</string>
<string name="pip_notification_unknown_title" msgid="6289156118095849438">"(शीर्षकविहीन कार्यक्रम)"</string>
<string name="pip_close" msgid="3480680679023423574">"PIP लाई बन्द गर्नुहोस्"</string>
<string name="pip_fullscreen" msgid="8604643018538487816">"पूर्ण स्क्रिन"</string>
diff --git a/packages/SystemUI/res/values-nl/strings.xml b/packages/SystemUI/res/values-nl/strings.xml
index 8e3100f..fb494c0 100644
--- a/packages/SystemUI/res/values-nl/strings.xml
+++ b/packages/SystemUI/res/values-nl/strings.xml
@@ -310,6 +310,8 @@
<string name="quick_settings_more_settings" msgid="326112621462813682">"Meer instellingen"</string>
<string name="quick_settings_done" msgid="3402999958839153376">"Gereed"</string>
<string name="quick_settings_connected" msgid="1722253542984847487">"Verbonden"</string>
+ <!-- no translation found for quick_settings_connected_battery_level (4136051440381328892) -->
+ <skip />
<string name="quick_settings_connecting" msgid="47623027419264404">"Verbinding maken…"</string>
<string name="quick_settings_tethering_label" msgid="7153452060448575549">"Tethering"</string>
<string name="quick_settings_hotspot_label" msgid="6046917934974004879">"Hotspot"</string>
@@ -725,8 +727,8 @@
<string name="pip_phone_minimize" msgid="1079119422589131792">"Minimaliseren"</string>
<string name="pip_phone_close" msgid="8416647892889710330">"Sluiten"</string>
<string name="pip_phone_dismiss_hint" msgid="6351678169095923899">"Sleep omlaag om te sluiten"</string>
- <string name="pip_menu_title" msgid="3328510504196964712">"Beeld-in-beeld-menu"</string>
- <string name="pip_notification_title" msgid="3204024940158161322">"<xliff:g id="NAME">%s</xliff:g> is in beeld-in-beeld"</string>
+ <string name="pip_menu_title" msgid="3328510504196964712">"Scherm-in-scherm-menu"</string>
+ <string name="pip_notification_title" msgid="3204024940158161322">"<xliff:g id="NAME">%s</xliff:g> is in scherm-in-scherm"</string>
<string name="pip_notification_message" msgid="5619512781514343311">"Als je niet wilt dat <xliff:g id="NAME">%s</xliff:g> deze functie gebruikt, tik je om de instellingen te openen en schakel je de functie uit."</string>
<string name="pip_play" msgid="1417176722760265888">"Afspelen"</string>
<string name="pip_pause" msgid="8881063404466476571">"Onderbreken"</string>
diff --git a/packages/SystemUI/res/values-nl/strings_tv.xml b/packages/SystemUI/res/values-nl/strings_tv.xml
index fae484f..8270fee 100644
--- a/packages/SystemUI/res/values-nl/strings_tv.xml
+++ b/packages/SystemUI/res/values-nl/strings_tv.xml
@@ -19,7 +19,7 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="notification_channel_tv_pip" msgid="134047986446577723">"Beeld-in-beeld"</string>
+ <string name="notification_channel_tv_pip" msgid="134047986446577723">"Scherm-in-scherm"</string>
<string name="pip_notification_unknown_title" msgid="6289156118095849438">"(Naamloos programma)"</string>
<string name="pip_close" msgid="3480680679023423574">"PIP sluiten"</string>
<string name="pip_fullscreen" msgid="8604643018538487816">"Volledig scherm"</string>
diff --git a/packages/SystemUI/res/values-pa/strings.xml b/packages/SystemUI/res/values-pa/strings.xml
index 2da7606..23f60fd 100644
--- a/packages/SystemUI/res/values-pa/strings.xml
+++ b/packages/SystemUI/res/values-pa/strings.xml
@@ -310,6 +310,8 @@
<string name="quick_settings_more_settings" msgid="326112621462813682">"ਹੋਰ ਸੈਟਿੰਗਾਂ"</string>
<string name="quick_settings_done" msgid="3402999958839153376">"ਹੋ ਗਿਆ"</string>
<string name="quick_settings_connected" msgid="1722253542984847487">"ਕਨੈਕਟ ਕੀਤਾ"</string>
+ <!-- no translation found for quick_settings_connected_battery_level (4136051440381328892) -->
+ <skip />
<string name="quick_settings_connecting" msgid="47623027419264404">"ਕਨੈਕਟ ਕਰ ਰਿਹਾ ਹੈ..."</string>
<string name="quick_settings_tethering_label" msgid="7153452060448575549">"ਟੀਥਰਿੰਗ"</string>
<string name="quick_settings_hotspot_label" msgid="6046917934974004879">"ਹੌਟਸਪੌਟ"</string>
diff --git a/packages/SystemUI/res/values-pl/strings.xml b/packages/SystemUI/res/values-pl/strings.xml
index f925b60..5c7b037 100644
--- a/packages/SystemUI/res/values-pl/strings.xml
+++ b/packages/SystemUI/res/values-pl/strings.xml
@@ -314,6 +314,8 @@
<string name="quick_settings_more_settings" msgid="326112621462813682">"Więcej ustawień"</string>
<string name="quick_settings_done" msgid="3402999958839153376">"Gotowe"</string>
<string name="quick_settings_connected" msgid="1722253542984847487">"Połączono"</string>
+ <!-- no translation found for quick_settings_connected_battery_level (4136051440381328892) -->
+ <skip />
<string name="quick_settings_connecting" msgid="47623027419264404">"Łączę..."</string>
<string name="quick_settings_tethering_label" msgid="7153452060448575549">"Powiązanie"</string>
<string name="quick_settings_hotspot_label" msgid="6046917934974004879">"Hotspot"</string>
diff --git a/packages/SystemUI/res/values-pt-rBR/strings.xml b/packages/SystemUI/res/values-pt-rBR/strings.xml
index ab7d3db..e0e1c76 100644
--- a/packages/SystemUI/res/values-pt-rBR/strings.xml
+++ b/packages/SystemUI/res/values-pt-rBR/strings.xml
@@ -312,6 +312,8 @@
<string name="quick_settings_more_settings" msgid="326112621462813682">"Mais configurações"</string>
<string name="quick_settings_done" msgid="3402999958839153376">"Concluído"</string>
<string name="quick_settings_connected" msgid="1722253542984847487">"Conectado"</string>
+ <!-- no translation found for quick_settings_connected_battery_level (4136051440381328892) -->
+ <skip />
<string name="quick_settings_connecting" msgid="47623027419264404">"Conectando..."</string>
<string name="quick_settings_tethering_label" msgid="7153452060448575549">"Tethering"</string>
<string name="quick_settings_hotspot_label" msgid="6046917934974004879">"Ponto de acesso"</string>
diff --git a/packages/SystemUI/res/values-pt-rPT/strings.xml b/packages/SystemUI/res/values-pt-rPT/strings.xml
index 2f31c02..37e1c7ed 100644
--- a/packages/SystemUI/res/values-pt-rPT/strings.xml
+++ b/packages/SystemUI/res/values-pt-rPT/strings.xml
@@ -310,6 +310,8 @@
<string name="quick_settings_more_settings" msgid="326112621462813682">"Mais definições"</string>
<string name="quick_settings_done" msgid="3402999958839153376">"Concluído"</string>
<string name="quick_settings_connected" msgid="1722253542984847487">"Ligado"</string>
+ <!-- no translation found for quick_settings_connected_battery_level (4136051440381328892) -->
+ <skip />
<string name="quick_settings_connecting" msgid="47623027419264404">"A ligar..."</string>
<string name="quick_settings_tethering_label" msgid="7153452060448575549">"Associação"</string>
<string name="quick_settings_hotspot_label" msgid="6046917934974004879">"Zona Wi-Fi"</string>
@@ -725,8 +727,8 @@
<string name="pip_phone_minimize" msgid="1079119422589131792">"Minimizar"</string>
<string name="pip_phone_close" msgid="8416647892889710330">"Fechar"</string>
<string name="pip_phone_dismiss_hint" msgid="6351678169095923899">"Arrastar para baixo para ignorar"</string>
- <string name="pip_menu_title" msgid="3328510504196964712">"Menu de imagem na imagem"</string>
- <string name="pip_notification_title" msgid="3204024940158161322">"A aplicação <xliff:g id="NAME">%s</xliff:g> está no modo de imagem na imagem"</string>
+ <string name="pip_menu_title" msgid="3328510504196964712">"Menu de ecrã no ecrã"</string>
+ <string name="pip_notification_title" msgid="3204024940158161322">"A aplicação <xliff:g id="NAME">%s</xliff:g> está no modo de ecrã no ecrã"</string>
<string name="pip_notification_message" msgid="5619512781514343311">"Se não pretende que a aplicação <xliff:g id="NAME">%s</xliff:g> utilize esta funcionalidade, toque para abrir as definições e desative-a."</string>
<string name="pip_play" msgid="1417176722760265888">"Reproduzir"</string>
<string name="pip_pause" msgid="8881063404466476571">"Colocar em pausa"</string>
diff --git a/packages/SystemUI/res/values-pt-rPT/strings_tv.xml b/packages/SystemUI/res/values-pt-rPT/strings_tv.xml
index a621877..ee90009 100644
--- a/packages/SystemUI/res/values-pt-rPT/strings_tv.xml
+++ b/packages/SystemUI/res/values-pt-rPT/strings_tv.xml
@@ -19,7 +19,7 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="notification_channel_tv_pip" msgid="134047986446577723">"Imagem na imagem"</string>
+ <string name="notification_channel_tv_pip" msgid="134047986446577723">"Ecrã no ecrã"</string>
<string name="pip_notification_unknown_title" msgid="6289156118095849438">"(Sem título do programa)"</string>
<string name="pip_close" msgid="3480680679023423574">"Fechar PIP"</string>
<string name="pip_fullscreen" msgid="8604643018538487816">"Ecrã inteiro"</string>
diff --git a/packages/SystemUI/res/values-pt/strings.xml b/packages/SystemUI/res/values-pt/strings.xml
index ab7d3db..e0e1c76 100644
--- a/packages/SystemUI/res/values-pt/strings.xml
+++ b/packages/SystemUI/res/values-pt/strings.xml
@@ -312,6 +312,8 @@
<string name="quick_settings_more_settings" msgid="326112621462813682">"Mais configurações"</string>
<string name="quick_settings_done" msgid="3402999958839153376">"Concluído"</string>
<string name="quick_settings_connected" msgid="1722253542984847487">"Conectado"</string>
+ <!-- no translation found for quick_settings_connected_battery_level (4136051440381328892) -->
+ <skip />
<string name="quick_settings_connecting" msgid="47623027419264404">"Conectando..."</string>
<string name="quick_settings_tethering_label" msgid="7153452060448575549">"Tethering"</string>
<string name="quick_settings_hotspot_label" msgid="6046917934974004879">"Ponto de acesso"</string>
diff --git a/packages/SystemUI/res/values-ro/strings.xml b/packages/SystemUI/res/values-ro/strings.xml
index bba92ec..be529f3 100644
--- a/packages/SystemUI/res/values-ro/strings.xml
+++ b/packages/SystemUI/res/values-ro/strings.xml
@@ -314,6 +314,8 @@
<string name="quick_settings_more_settings" msgid="326112621462813682">"Mai multe setări"</string>
<string name="quick_settings_done" msgid="3402999958839153376">"Terminat"</string>
<string name="quick_settings_connected" msgid="1722253542984847487">"Conectat"</string>
+ <!-- no translation found for quick_settings_connected_battery_level (4136051440381328892) -->
+ <skip />
<string name="quick_settings_connecting" msgid="47623027419264404">"Se conectează..."</string>
<string name="quick_settings_tethering_label" msgid="7153452060448575549">"Tethering"</string>
<string name="quick_settings_hotspot_label" msgid="6046917934974004879">"Hotspot"</string>
@@ -733,7 +735,7 @@
<string name="pip_phone_minimize" msgid="1079119422589131792">"Minimizați"</string>
<string name="pip_phone_close" msgid="8416647892889710330">"Închideți"</string>
<string name="pip_phone_dismiss_hint" msgid="6351678169095923899">"Trageți în jos pentru a închide"</string>
- <string name="pip_menu_title" msgid="3328510504196964712">"Meniul imagine în imagine"</string>
+ <string name="pip_menu_title" msgid="3328510504196964712">"Meniul picture-in-picture"</string>
<string name="pip_notification_title" msgid="3204024940158161322">"<xliff:g id="NAME">%s</xliff:g> este în modul picture-in-picture"</string>
<string name="pip_notification_message" msgid="5619512781514343311">"Dacă nu doriți ca <xliff:g id="NAME">%s</xliff:g> să utilizeze această funcție, atingeți pentru a deschide setările și dezactivați-o."</string>
<string name="pip_play" msgid="1417176722760265888">"Redați"</string>
diff --git a/packages/SystemUI/res/values-ru/strings.xml b/packages/SystemUI/res/values-ru/strings.xml
index 35c860c..88deda0 100644
--- a/packages/SystemUI/res/values-ru/strings.xml
+++ b/packages/SystemUI/res/values-ru/strings.xml
@@ -316,6 +316,8 @@
<string name="quick_settings_more_settings" msgid="326112621462813682">"Настройки"</string>
<string name="quick_settings_done" msgid="3402999958839153376">"Готово"</string>
<string name="quick_settings_connected" msgid="1722253542984847487">"Подключено"</string>
+ <!-- no translation found for quick_settings_connected_battery_level (4136051440381328892) -->
+ <skip />
<string name="quick_settings_connecting" msgid="47623027419264404">"Соединение..."</string>
<string name="quick_settings_tethering_label" msgid="7153452060448575549">"Режим модема"</string>
<string name="quick_settings_hotspot_label" msgid="6046917934974004879">"Точка доступа"</string>
diff --git a/packages/SystemUI/res/values-si/strings.xml b/packages/SystemUI/res/values-si/strings.xml
index 1eab251..9cd3701 100644
--- a/packages/SystemUI/res/values-si/strings.xml
+++ b/packages/SystemUI/res/values-si/strings.xml
@@ -310,6 +310,8 @@
<string name="quick_settings_more_settings" msgid="326112621462813682">"තව සැකසීම්"</string>
<string name="quick_settings_done" msgid="3402999958839153376">"නිමයි"</string>
<string name="quick_settings_connected" msgid="1722253542984847487">"සම්බන්ධිත"</string>
+ <!-- no translation found for quick_settings_connected_battery_level (4136051440381328892) -->
+ <skip />
<string name="quick_settings_connecting" msgid="47623027419264404">"සම්බන්ධ වෙමින්..."</string>
<string name="quick_settings_tethering_label" msgid="7153452060448575549">"ටෙදරින්"</string>
<string name="quick_settings_hotspot_label" msgid="6046917934974004879">"හොට්ස්පොට්"</string>
diff --git a/packages/SystemUI/res/values-sk/strings.xml b/packages/SystemUI/res/values-sk/strings.xml
index f6b1e50..a93013e 100644
--- a/packages/SystemUI/res/values-sk/strings.xml
+++ b/packages/SystemUI/res/values-sk/strings.xml
@@ -66,7 +66,7 @@
<string name="usb_debugging_message" msgid="2220143855912376496">"Digitálny odtlačok RSA počítača je:\n<xliff:g id="FINGERPRINT">%1$s</xliff:g>"</string>
<string name="usb_debugging_always" msgid="303335496705863070">"Vždy povoliť z tohto počítača"</string>
<string name="usb_debugging_secondary_user_title" msgid="6353808721761220421">"Ladenie cez USB nie je povolené"</string>
- <string name="usb_debugging_secondary_user_message" msgid="8572228137833020196">"Používateľ, ktorý je práve prihlásený na tomto zariadení, nemôže zapnúť ladenie USB. Ak chcete použiť túto funkciu, prepnite na používateľa s oprávneniami správcu."</string>
+ <string name="usb_debugging_secondary_user_message" msgid="8572228137833020196">"Používateľ, ktorý je práve prihlásený na tomto zariadení, nemôže zapnúť ladenie cez USB. Ak chcete použiť túto funkciu, prepnite na používateľa s oprávneniami správcu."</string>
<string name="compat_mode_on" msgid="6623839244840638213">"Priblížiť na celú obrazovku"</string>
<string name="compat_mode_off" msgid="4434467572461327898">"Na celú obrazovku"</string>
<string name="screenshot_saving_ticker" msgid="7403652894056693515">"Prebieha ukladanie snímky obrazovky..."</string>
@@ -316,6 +316,8 @@
<string name="quick_settings_more_settings" msgid="326112621462813682">"Ďalšie nastavenia"</string>
<string name="quick_settings_done" msgid="3402999958839153376">"Hotovo"</string>
<string name="quick_settings_connected" msgid="1722253542984847487">"Pripojené"</string>
+ <!-- no translation found for quick_settings_connected_battery_level (4136051440381328892) -->
+ <skip />
<string name="quick_settings_connecting" msgid="47623027419264404">"Pripája sa..."</string>
<string name="quick_settings_tethering_label" msgid="7153452060448575549">"Zdieľané pripojenie"</string>
<string name="quick_settings_hotspot_label" msgid="6046917934974004879">"Hotspot"</string>
@@ -739,8 +741,8 @@
<string name="pip_phone_minimize" msgid="1079119422589131792">"Minimalizovať"</string>
<string name="pip_phone_close" msgid="8416647892889710330">"Zavrieť"</string>
<string name="pip_phone_dismiss_hint" msgid="6351678169095923899">"Zrušíte presunutím nadol"</string>
- <string name="pip_menu_title" msgid="3328510504196964712">"Ponuka obrazu v obraze"</string>
- <string name="pip_notification_title" msgid="3204024940158161322">"<xliff:g id="NAME">%s</xliff:g> je na obraze v obraze"</string>
+ <string name="pip_menu_title" msgid="3328510504196964712">"Ponuka režimu obraz v obraze"</string>
+ <string name="pip_notification_title" msgid="3204024940158161322">"<xliff:g id="NAME">%s</xliff:g> je v režime obraz v obraze"</string>
<string name="pip_notification_message" msgid="5619512781514343311">"Ak nechcete, aby aplikácia <xliff:g id="NAME">%s</xliff:g> používala túto funkciu, klepnutím otvorte nastavenia a vypnite ju."</string>
<string name="pip_play" msgid="1417176722760265888">"Prehrať"</string>
<string name="pip_pause" msgid="8881063404466476571">"Pozastaviť"</string>
diff --git a/packages/SystemUI/res/values-sl/strings.xml b/packages/SystemUI/res/values-sl/strings.xml
index 270fb6d..449ac24 100644
--- a/packages/SystemUI/res/values-sl/strings.xml
+++ b/packages/SystemUI/res/values-sl/strings.xml
@@ -316,6 +316,8 @@
<string name="quick_settings_more_settings" msgid="326112621462813682">"Več nastavitev"</string>
<string name="quick_settings_done" msgid="3402999958839153376">"Končano"</string>
<string name="quick_settings_connected" msgid="1722253542984847487">"Povezava je vzpostavljena"</string>
+ <!-- no translation found for quick_settings_connected_battery_level (4136051440381328892) -->
+ <skip />
<string name="quick_settings_connecting" msgid="47623027419264404">"Vzpostavljanje povezave ..."</string>
<string name="quick_settings_tethering_label" msgid="7153452060448575549">"Internet prek mobilne naprave"</string>
<string name="quick_settings_hotspot_label" msgid="6046917934974004879">"Dostopna točka"</string>
diff --git a/packages/SystemUI/res/values-sq/strings.xml b/packages/SystemUI/res/values-sq/strings.xml
index c9b22ff..a254953 100644
--- a/packages/SystemUI/res/values-sq/strings.xml
+++ b/packages/SystemUI/res/values-sq/strings.xml
@@ -310,6 +310,8 @@
<string name="quick_settings_more_settings" msgid="326112621462813682">"Cilësime të tjera"</string>
<string name="quick_settings_done" msgid="3402999958839153376">"U krye!"</string>
<string name="quick_settings_connected" msgid="1722253542984847487">"I lidhur"</string>
+ <!-- no translation found for quick_settings_connected_battery_level (4136051440381328892) -->
+ <skip />
<string name="quick_settings_connecting" msgid="47623027419264404">"Po lidhet..."</string>
<string name="quick_settings_tethering_label" msgid="7153452060448575549">"Lidhje çiftimi"</string>
<string name="quick_settings_hotspot_label" msgid="6046917934974004879">"Qasje në zona publike interneti"</string>
diff --git a/packages/SystemUI/res/values-sr/strings.xml b/packages/SystemUI/res/values-sr/strings.xml
index 8556eae..561a56a 100644
--- a/packages/SystemUI/res/values-sr/strings.xml
+++ b/packages/SystemUI/res/values-sr/strings.xml
@@ -312,6 +312,8 @@
<string name="quick_settings_more_settings" msgid="326112621462813682">"Још подешавања"</string>
<string name="quick_settings_done" msgid="3402999958839153376">"Готово"</string>
<string name="quick_settings_connected" msgid="1722253542984847487">"Повезан"</string>
+ <!-- no translation found for quick_settings_connected_battery_level (4136051440381328892) -->
+ <skip />
<string name="quick_settings_connecting" msgid="47623027419264404">"Повезује се..."</string>
<string name="quick_settings_tethering_label" msgid="7153452060448575549">"Повезивање"</string>
<string name="quick_settings_hotspot_label" msgid="6046917934974004879">"Хотспот"</string>
diff --git a/packages/SystemUI/res/values-sv/strings.xml b/packages/SystemUI/res/values-sv/strings.xml
index ce9e7e2..cb5c214 100644
--- a/packages/SystemUI/res/values-sv/strings.xml
+++ b/packages/SystemUI/res/values-sv/strings.xml
@@ -310,6 +310,8 @@
<string name="quick_settings_more_settings" msgid="326112621462813682">"Fler inställningar"</string>
<string name="quick_settings_done" msgid="3402999958839153376">"Klart"</string>
<string name="quick_settings_connected" msgid="1722253542984847487">"Ansluten"</string>
+ <!-- no translation found for quick_settings_connected_battery_level (4136051440381328892) -->
+ <skip />
<string name="quick_settings_connecting" msgid="47623027419264404">"Ansluter ..."</string>
<string name="quick_settings_tethering_label" msgid="7153452060448575549">"Internetdelning"</string>
<string name="quick_settings_hotspot_label" msgid="6046917934974004879">"Trådlös surfzon"</string>
diff --git a/packages/SystemUI/res/values-sw/strings.xml b/packages/SystemUI/res/values-sw/strings.xml
index 3a35ff6..31d2328 100644
--- a/packages/SystemUI/res/values-sw/strings.xml
+++ b/packages/SystemUI/res/values-sw/strings.xml
@@ -310,6 +310,8 @@
<string name="quick_settings_more_settings" msgid="326112621462813682">"Mipangilio zaidi"</string>
<string name="quick_settings_done" msgid="3402999958839153376">"Nimemaliza"</string>
<string name="quick_settings_connected" msgid="1722253542984847487">"Imeunganishwa"</string>
+ <!-- no translation found for quick_settings_connected_battery_level (4136051440381328892) -->
+ <skip />
<string name="quick_settings_connecting" msgid="47623027419264404">"Inaunganisha..."</string>
<string name="quick_settings_tethering_label" msgid="7153452060448575549">"Kusambaza mtandao"</string>
<string name="quick_settings_hotspot_label" msgid="6046917934974004879">"Mtandao-hewa"</string>
@@ -726,7 +728,7 @@
<string name="pip_phone_close" msgid="8416647892889710330">"Funga"</string>
<string name="pip_phone_dismiss_hint" msgid="6351678169095923899">"Buruta ili uondoe"</string>
<string name="pip_menu_title" msgid="3328510504196964712">"Menyu ya picha ndani ya picha"</string>
- <string name="pip_notification_title" msgid="3204024940158161322">"<xliff:g id="NAME">%s</xliff:g> iko katika picha ndani ya picha"</string>
+ <string name="pip_notification_title" msgid="3204024940158161322">"<xliff:g id="NAME">%s</xliff:g> iko katika hali ya picha ndani ya picha nyingine"</string>
<string name="pip_notification_message" msgid="5619512781514343311">"Ikiwa hutaki <xliff:g id="NAME">%s</xliff:g> itumie kipengele hiki, gonga ili ufungue mipangilio na uizime."</string>
<string name="pip_play" msgid="1417176722760265888">"Cheza"</string>
<string name="pip_pause" msgid="8881063404466476571">"Sitisha"</string>
diff --git a/packages/SystemUI/res/values-ta/strings.xml b/packages/SystemUI/res/values-ta/strings.xml
index 8a9cba2..30defe3 100644
--- a/packages/SystemUI/res/values-ta/strings.xml
+++ b/packages/SystemUI/res/values-ta/strings.xml
@@ -310,6 +310,8 @@
<string name="quick_settings_more_settings" msgid="326112621462813682">"அமைப்பில் மாற்று"</string>
<string name="quick_settings_done" msgid="3402999958839153376">"முடிந்தது"</string>
<string name="quick_settings_connected" msgid="1722253542984847487">"இணைக்கப்பட்டது"</string>
+ <!-- no translation found for quick_settings_connected_battery_level (4136051440381328892) -->
+ <skip />
<string name="quick_settings_connecting" msgid="47623027419264404">"இணைக்கிறது..."</string>
<string name="quick_settings_tethering_label" msgid="7153452060448575549">"டெதெரிங்"</string>
<string name="quick_settings_hotspot_label" msgid="6046917934974004879">"ஹாட்ஸ்பாட்"</string>
@@ -725,8 +727,8 @@
<string name="pip_phone_minimize" msgid="1079119422589131792">"சிறிதாக்கு"</string>
<string name="pip_phone_close" msgid="8416647892889710330">"மூடு"</string>
<string name="pip_phone_dismiss_hint" msgid="6351678169095923899">"நிராகரிக்க, கீழே இழுக்கவும்"</string>
- <string name="pip_menu_title" msgid="3328510504196964712">"பிக்ச்சர் இன் பிக்ச்சர் மெனு"</string>
- <string name="pip_notification_title" msgid="3204024940158161322">"<xliff:g id="NAME">%s</xliff:g> தற்போது பிக்ச்சர் இன் பிக்ச்சரில் உள்ளது"</string>
+ <string name="pip_menu_title" msgid="3328510504196964712">"பிக்ச்சர்-இன்-பிக்ச்சர் மெனு"</string>
+ <string name="pip_notification_title" msgid="3204024940158161322">"<xliff:g id="NAME">%s</xliff:g> தற்போது பிக்ச்சர்-இன்-பிக்ச்சரில் உள்ளது"</string>
<string name="pip_notification_message" msgid="5619512781514343311">"<xliff:g id="NAME">%s</xliff:g> இந்த அம்சத்தைப் பயன்படுத்த வேண்டாம் என நினைத்தால், அமைப்புகளைத் திறந்து அதை முடக்க, தட்டவும்."</string>
<string name="pip_play" msgid="1417176722760265888">"இயக்கு"</string>
<string name="pip_pause" msgid="8881063404466476571">"இடைநிறுத்து"</string>
diff --git a/packages/SystemUI/res/values-ta/strings_tv.xml b/packages/SystemUI/res/values-ta/strings_tv.xml
index 5ddab56..f7c81ee 100644
--- a/packages/SystemUI/res/values-ta/strings_tv.xml
+++ b/packages/SystemUI/res/values-ta/strings_tv.xml
@@ -19,7 +19,7 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="notification_channel_tv_pip" msgid="134047986446577723">"பிக்ச்சர் இன் பிக்ச்சர்"</string>
+ <string name="notification_channel_tv_pip" msgid="134047986446577723">"பிக்ச்சர்-இன்-பிக்ச்சர்"</string>
<string name="pip_notification_unknown_title" msgid="6289156118095849438">"(தலைப்பு இல்லை)"</string>
<string name="pip_close" msgid="3480680679023423574">"PIPஐ மூடு"</string>
<string name="pip_fullscreen" msgid="8604643018538487816">"முழுத்திரை"</string>
diff --git a/packages/SystemUI/res/values-te/strings.xml b/packages/SystemUI/res/values-te/strings.xml
index b3421a9..2a2d394 100644
--- a/packages/SystemUI/res/values-te/strings.xml
+++ b/packages/SystemUI/res/values-te/strings.xml
@@ -310,6 +310,8 @@
<string name="quick_settings_more_settings" msgid="326112621462813682">"మరిన్ని సెట్టింగ్లు"</string>
<string name="quick_settings_done" msgid="3402999958839153376">"పూర్తయింది"</string>
<string name="quick_settings_connected" msgid="1722253542984847487">"కనెక్ట్ చేయబడినది"</string>
+ <!-- no translation found for quick_settings_connected_battery_level (4136051440381328892) -->
+ <skip />
<string name="quick_settings_connecting" msgid="47623027419264404">"కనెక్ట్ అవుతోంది..."</string>
<string name="quick_settings_tethering_label" msgid="7153452060448575549">"టీథరింగ్"</string>
<string name="quick_settings_hotspot_label" msgid="6046917934974004879">"హాట్స్పాట్"</string>
diff --git a/packages/SystemUI/res/values-th/strings.xml b/packages/SystemUI/res/values-th/strings.xml
index 944c429..969ba34 100644
--- a/packages/SystemUI/res/values-th/strings.xml
+++ b/packages/SystemUI/res/values-th/strings.xml
@@ -310,6 +310,8 @@
<string name="quick_settings_more_settings" msgid="326112621462813682">"การตั้งค่าเพิ่มเติม"</string>
<string name="quick_settings_done" msgid="3402999958839153376">"เสร็จสิ้น"</string>
<string name="quick_settings_connected" msgid="1722253542984847487">"เชื่อมต่อ"</string>
+ <!-- no translation found for quick_settings_connected_battery_level (4136051440381328892) -->
+ <skip />
<string name="quick_settings_connecting" msgid="47623027419264404">"กำลังเชื่อมต่อ..."</string>
<string name="quick_settings_tethering_label" msgid="7153452060448575549">"การปล่อยสัญญาณ"</string>
<string name="quick_settings_hotspot_label" msgid="6046917934974004879">"ฮอตสปอต"</string>
diff --git a/packages/SystemUI/res/values-tl/strings.xml b/packages/SystemUI/res/values-tl/strings.xml
index b478705..1d223d03 100644
--- a/packages/SystemUI/res/values-tl/strings.xml
+++ b/packages/SystemUI/res/values-tl/strings.xml
@@ -310,6 +310,8 @@
<string name="quick_settings_more_settings" msgid="326112621462813682">"Marami pang setting"</string>
<string name="quick_settings_done" msgid="3402999958839153376">"Tapos na"</string>
<string name="quick_settings_connected" msgid="1722253542984847487">"Nakakonekta"</string>
+ <!-- no translation found for quick_settings_connected_battery_level (4136051440381328892) -->
+ <skip />
<string name="quick_settings_connecting" msgid="47623027419264404">"Kumokonekta..."</string>
<string name="quick_settings_tethering_label" msgid="7153452060448575549">"Nagte-tether"</string>
<string name="quick_settings_hotspot_label" msgid="6046917934974004879">"Hotspot"</string>
diff --git a/packages/SystemUI/res/values-tr/strings.xml b/packages/SystemUI/res/values-tr/strings.xml
index 8c18bf0..0b2fa4e 100644
--- a/packages/SystemUI/res/values-tr/strings.xml
+++ b/packages/SystemUI/res/values-tr/strings.xml
@@ -310,6 +310,8 @@
<string name="quick_settings_more_settings" msgid="326112621462813682">"Diğer ayarlar"</string>
<string name="quick_settings_done" msgid="3402999958839153376">"Bitti"</string>
<string name="quick_settings_connected" msgid="1722253542984847487">"Bağlı"</string>
+ <!-- no translation found for quick_settings_connected_battery_level (4136051440381328892) -->
+ <skip />
<string name="quick_settings_connecting" msgid="47623027419264404">"Bağlanılıyor..."</string>
<string name="quick_settings_tethering_label" msgid="7153452060448575549">"Tethering"</string>
<string name="quick_settings_hotspot_label" msgid="6046917934974004879">"Hotspot"</string>
@@ -725,8 +727,8 @@
<string name="pip_phone_minimize" msgid="1079119422589131792">"Simge durumuna getir"</string>
<string name="pip_phone_close" msgid="8416647892889710330">"Kapat"</string>
<string name="pip_phone_dismiss_hint" msgid="6351678169095923899">"Kapatmak için aşağıya sürükleyin"</string>
- <string name="pip_menu_title" msgid="3328510504196964712">"Ekran içinde ekran menüsü"</string>
- <string name="pip_notification_title" msgid="3204024940158161322">"<xliff:g id="NAME">%s</xliff:g>, ekran içinde ekran özelliğini kullanıyor"</string>
+ <string name="pip_menu_title" msgid="3328510504196964712">"Pencere içinde pencere menüsü"</string>
+ <string name="pip_notification_title" msgid="3204024940158161322">"<xliff:g id="NAME">%s</xliff:g>, pencere içinde pencere özelliğini kullanıyor"</string>
<string name="pip_notification_message" msgid="5619512781514343311">"<xliff:g id="NAME">%s</xliff:g> uygulamasının bu özelliği kullanmasını istemiyorsanız dokunarak ayarları açın ve söz konusu özelliği kapatın."</string>
<string name="pip_play" msgid="1417176722760265888">"Oynat"</string>
<string name="pip_pause" msgid="8881063404466476571">"Duraklat"</string>
diff --git a/packages/SystemUI/res/values-tr/strings_tv.xml b/packages/SystemUI/res/values-tr/strings_tv.xml
index ec2c784..fb39510 100644
--- a/packages/SystemUI/res/values-tr/strings_tv.xml
+++ b/packages/SystemUI/res/values-tr/strings_tv.xml
@@ -19,7 +19,7 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="notification_channel_tv_pip" msgid="134047986446577723">"Ekran İçinde Ekran"</string>
+ <string name="notification_channel_tv_pip" msgid="134047986446577723">"Pencere İçinde Pencere"</string>
<string name="pip_notification_unknown_title" msgid="6289156118095849438">"(Başlıksız program)"</string>
<string name="pip_close" msgid="3480680679023423574">"PIP\'yi kapat"</string>
<string name="pip_fullscreen" msgid="8604643018538487816">"Tam ekran"</string>
diff --git a/packages/SystemUI/res/values-uk/strings.xml b/packages/SystemUI/res/values-uk/strings.xml
index 8fb2363..d11cfda 100644
--- a/packages/SystemUI/res/values-uk/strings.xml
+++ b/packages/SystemUI/res/values-uk/strings.xml
@@ -316,6 +316,8 @@
<string name="quick_settings_more_settings" msgid="326112621462813682">"Більше налаштувань"</string>
<string name="quick_settings_done" msgid="3402999958839153376">"Готово"</string>
<string name="quick_settings_connected" msgid="1722253542984847487">"Під’єднано"</string>
+ <!-- no translation found for quick_settings_connected_battery_level (4136051440381328892) -->
+ <skip />
<string name="quick_settings_connecting" msgid="47623027419264404">"З’єднання…"</string>
<string name="quick_settings_tethering_label" msgid="7153452060448575549">"Режим модема"</string>
<string name="quick_settings_hotspot_label" msgid="6046917934974004879">"Точка доступу"</string>
diff --git a/packages/SystemUI/res/values-ur/strings.xml b/packages/SystemUI/res/values-ur/strings.xml
index c00b741..e071922 100644
--- a/packages/SystemUI/res/values-ur/strings.xml
+++ b/packages/SystemUI/res/values-ur/strings.xml
@@ -310,6 +310,8 @@
<string name="quick_settings_more_settings" msgid="326112621462813682">"مزید ترتیبات"</string>
<string name="quick_settings_done" msgid="3402999958839153376">"ہو گیا"</string>
<string name="quick_settings_connected" msgid="1722253542984847487">"مربوط"</string>
+ <!-- no translation found for quick_settings_connected_battery_level (4136051440381328892) -->
+ <skip />
<string name="quick_settings_connecting" msgid="47623027419264404">"مربوط ہو رہا ہے…"</string>
<string name="quick_settings_tethering_label" msgid="7153452060448575549">"ٹیتھرنگ"</string>
<string name="quick_settings_hotspot_label" msgid="6046917934974004879">"ہاٹ اسپاٹ"</string>
diff --git a/packages/SystemUI/res/values-uz/strings.xml b/packages/SystemUI/res/values-uz/strings.xml
index caf4df7..cf6fa00 100644
--- a/packages/SystemUI/res/values-uz/strings.xml
+++ b/packages/SystemUI/res/values-uz/strings.xml
@@ -312,6 +312,8 @@
<string name="quick_settings_more_settings" msgid="326112621462813682">"Boshqa sozlamalar"</string>
<string name="quick_settings_done" msgid="3402999958839153376">"Tayyor"</string>
<string name="quick_settings_connected" msgid="1722253542984847487">"Ulangan"</string>
+ <!-- no translation found for quick_settings_connected_battery_level (4136051440381328892) -->
+ <skip />
<string name="quick_settings_connecting" msgid="47623027419264404">"Ulanmoqda…"</string>
<string name="quick_settings_tethering_label" msgid="7153452060448575549">"Modem rejimi"</string>
<string name="quick_settings_hotspot_label" msgid="6046917934974004879">"Hotspot"</string>
diff --git a/packages/SystemUI/res/values-vi/strings.xml b/packages/SystemUI/res/values-vi/strings.xml
index 9a2ef2d..5b884ec 100644
--- a/packages/SystemUI/res/values-vi/strings.xml
+++ b/packages/SystemUI/res/values-vi/strings.xml
@@ -310,6 +310,8 @@
<string name="quick_settings_more_settings" msgid="326112621462813682">"Cài đặt khác"</string>
<string name="quick_settings_done" msgid="3402999958839153376">"Xong"</string>
<string name="quick_settings_connected" msgid="1722253542984847487">"Đã kết nối"</string>
+ <!-- no translation found for quick_settings_connected_battery_level (4136051440381328892) -->
+ <skip />
<string name="quick_settings_connecting" msgid="47623027419264404">"Đang kết nối..."</string>
<string name="quick_settings_tethering_label" msgid="7153452060448575549">"Đang dùng làm điểm truy cập Internet"</string>
<string name="quick_settings_hotspot_label" msgid="6046917934974004879">"Điểm phát sóng"</string>
diff --git a/packages/SystemUI/res/values-zh-rCN/strings.xml b/packages/SystemUI/res/values-zh-rCN/strings.xml
index 094d9e3..4065ff6 100644
--- a/packages/SystemUI/res/values-zh-rCN/strings.xml
+++ b/packages/SystemUI/res/values-zh-rCN/strings.xml
@@ -60,7 +60,7 @@
<string name="label_view" msgid="6304565553218192990">"查看"</string>
<string name="always_use_device" msgid="1450287437017315906">"默认情况下用于该USB设备"</string>
<string name="always_use_accessory" msgid="1210954576979621596">"默认情况下用于该USB配件"</string>
- <string name="usb_debugging_title" msgid="4513918393387141949">"允许USB调试吗?"</string>
+ <string name="usb_debugging_title" msgid="4513918393387141949">"允许 USB 调试吗?"</string>
<string name="usb_debugging_message" msgid="2220143855912376496">"这台计算机的 RSA 密钥指纹如下:\n<xliff:g id="FINGERPRINT">%1$s</xliff:g>"</string>
<string name="usb_debugging_always" msgid="303335496705863070">"一律允许使用这台计算机进行调试"</string>
<string name="usb_debugging_secondary_user_title" msgid="6353808721761220421">"不允许使用 USB 调试功能"</string>
@@ -310,6 +310,8 @@
<string name="quick_settings_more_settings" msgid="326112621462813682">"更多设置"</string>
<string name="quick_settings_done" msgid="3402999958839153376">"完成"</string>
<string name="quick_settings_connected" msgid="1722253542984847487">"已连接"</string>
+ <!-- no translation found for quick_settings_connected_battery_level (4136051440381328892) -->
+ <skip />
<string name="quick_settings_connecting" msgid="47623027419264404">"正在连接…"</string>
<string name="quick_settings_tethering_label" msgid="7153452060448575549">"网络共享"</string>
<string name="quick_settings_hotspot_label" msgid="6046917934974004879">"热点"</string>
diff --git a/packages/SystemUI/res/values-zh-rHK/strings.xml b/packages/SystemUI/res/values-zh-rHK/strings.xml
index 7152052..5fc1ff63 100644
--- a/packages/SystemUI/res/values-zh-rHK/strings.xml
+++ b/packages/SystemUI/res/values-zh-rHK/strings.xml
@@ -312,6 +312,8 @@
<string name="quick_settings_more_settings" msgid="326112621462813682">"更多設定"</string>
<string name="quick_settings_done" msgid="3402999958839153376">"完成"</string>
<string name="quick_settings_connected" msgid="1722253542984847487">"已連線"</string>
+ <!-- no translation found for quick_settings_connected_battery_level (4136051440381328892) -->
+ <skip />
<string name="quick_settings_connecting" msgid="47623027419264404">"正在連線…"</string>
<string name="quick_settings_tethering_label" msgid="7153452060448575549">"網絡共享"</string>
<string name="quick_settings_hotspot_label" msgid="6046917934974004879">"熱點"</string>
diff --git a/packages/SystemUI/res/values-zh-rTW/strings.xml b/packages/SystemUI/res/values-zh-rTW/strings.xml
index a184f3af..9bbb188 100644
--- a/packages/SystemUI/res/values-zh-rTW/strings.xml
+++ b/packages/SystemUI/res/values-zh-rTW/strings.xml
@@ -310,6 +310,8 @@
<string name="quick_settings_more_settings" msgid="326112621462813682">"更多設定"</string>
<string name="quick_settings_done" msgid="3402999958839153376">"完成"</string>
<string name="quick_settings_connected" msgid="1722253542984847487">"已連線"</string>
+ <!-- no translation found for quick_settings_connected_battery_level (4136051440381328892) -->
+ <skip />
<string name="quick_settings_connecting" msgid="47623027419264404">"連線中..."</string>
<string name="quick_settings_tethering_label" msgid="7153452060448575549">"網路共用"</string>
<string name="quick_settings_hotspot_label" msgid="6046917934974004879">"無線基地台"</string>
diff --git a/packages/SystemUI/res/values-zu/strings.xml b/packages/SystemUI/res/values-zu/strings.xml
index d2584d7..1a70bc4 100644
--- a/packages/SystemUI/res/values-zu/strings.xml
+++ b/packages/SystemUI/res/values-zu/strings.xml
@@ -310,6 +310,8 @@
<string name="quick_settings_more_settings" msgid="326112621462813682">"Izilungiselelo eziningi"</string>
<string name="quick_settings_done" msgid="3402999958839153376">"Kwenziwe"</string>
<string name="quick_settings_connected" msgid="1722253542984847487">"Ixhunyiwe"</string>
+ <!-- no translation found for quick_settings_connected_battery_level (4136051440381328892) -->
+ <skip />
<string name="quick_settings_connecting" msgid="47623027419264404">"Iyaxhuma..."</string>
<string name="quick_settings_tethering_label" msgid="7153452060448575549">"Ukusebenzisa njengemodemu"</string>
<string name="quick_settings_hotspot_label" msgid="6046917934974004879">"I-Hotspot"</string>
diff --git a/packages/SystemUI/res/values/config.xml b/packages/SystemUI/res/values/config.xml
index c0068d3..02a2e8f 100644
--- a/packages/SystemUI/res/values/config.xml
+++ b/packages/SystemUI/res/values/config.xml
@@ -247,6 +247,11 @@
-->
<string name="doze_pickup_subtype_performs_proximity_check"></string>
+ <!-- Type of a sensor that provides a low-power estimate of the desired display
+ brightness, suitable to listen to while the device is asleep (e.g. during
+ always-on display) -->
+ <string name="doze_brightness_sensor_type" translatable="false"></string>
+
<!-- Doze: pulse parameter - how long does it take to fade in? -->
<integer name="doze_pulse_duration_in">900</integer>
diff --git a/packages/SystemUI/res/values/dimens.xml b/packages/SystemUI/res/values/dimens.xml
index c37069f..1fd9b2e 100644
--- a/packages/SystemUI/res/values/dimens.xml
+++ b/packages/SystemUI/res/values/dimens.xml
@@ -196,7 +196,7 @@
<dimen name="status_bar_header_padding_bottom">48dp</dimen>
<!-- The height of the container that holds the system icons in the quick settings header. -->
- <dimen name="qs_header_system_icons_area_height">32dp</dimen>
+ <dimen name="qs_header_system_icons_area_height">40dp</dimen>
<!-- The height of the container that holds the system icons in the quick settings header in the
car setting. -->
diff --git a/packages/SystemUI/res/values/styles.xml b/packages/SystemUI/res/values/styles.xml
index 5274b64..93a0742 100644
--- a/packages/SystemUI/res/values/styles.xml
+++ b/packages/SystemUI/res/values/styles.xml
@@ -16,7 +16,7 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android">
- <style name="RecentsTheme" parent="@android:style/Theme.Material">
+ <style name="RecentsTheme" parent="RecentsBase">
<!-- NoTitle -->
<item name="android:windowNoTitle">true</item>
<!-- Misc -->
@@ -27,6 +27,12 @@
<item name="android:ambientShadowAlpha">0.35</item>
</style>
+ <!-- OverlayManager might replace this style entirely, use RecentsTheme to set a property
+ that should exist in both light and dark versions of Recents -->
+ <style name="RecentsBase" parent="@android:style/Theme.Material">
+ <item name="android:textColorPrimaryInverse">@*android:color/primary_text_material_dark</item>
+ <item name="android:textColorSecondaryInverse">@*android:color/secondary_text_material_dark</item>
+ </style>
<!-- Recents theme -->
<style name="RecentsTheme.Wallpaper">
@@ -35,6 +41,8 @@
<item name="android:windowShowWallpaper">true</item>
<item name="android:windowDisablePreview">true</item>
<item name="clearAllStyle">@style/ClearAllButtonDefaultMargins</item>
+ <item name="bgProtectTextColor">?android:attr/textColorPrimaryInverse</item>
+ <item name="bgProtectSecondaryTextColor">?android:attr/textColorSecondaryInverse</item>
</style>
<style name="ClearAllButtonDefaultMargins">
@@ -47,6 +55,8 @@
<!-- Performance optimized Recents theme (no wallpaper) -->
<style name="RecentsTheme.NoWallpaper">
<item name="android:windowBackground">@android:color/black</item>
+ <item name="bgProtectTextColor">@android:color/white</item>
+ <item name="bgProtectSecondaryTextColor">@android:color/white</item>
</style>
<!-- Theme used for the activity that shows when the system forced an app to be resizable -->
@@ -290,7 +300,10 @@
<style name="Animation.StatusBar">
</style>
- <style name="systemui_theme" parent="@*android:style/Theme.DeviceDefault.QuickSettings">
+ <!-- Overlay manager may replace this theme -->
+ <style name="systemui_base" parent="@*android:style/Theme.DeviceDefault.QuickSettings" />
+
+ <style name="systemui_theme" parent="systemui_base">
<item name="lightIconTheme">@style/DualToneLightTheme</item>
<item name="darkIconTheme">@style/DualToneDarkTheme</item>
<item name="bgProtectTextColor">?android:attr/textColorPrimaryInverse</item>
@@ -303,7 +316,10 @@
<item name="*android:successColor">?android:attr/textColorPrimaryInverse</item>
</style>
- <style name="qs_theme" parent="systemui_theme">
+ <!-- Overlay manager may replace this theme -->
+ <style name="qs_base" parent="@*android:style/Theme.DeviceDefault.QuickSettings" />
+
+ <style name="qs_theme" parent="qs_base">
<item name="lightIconTheme">@style/QSIconTheme</item>
<item name="darkIconTheme">@style/QSIconTheme</item>
</style>
@@ -459,7 +475,7 @@
<item name="android:paddingEnd">8dp</item>
</style>
- <style name="edit_theme" parent="@*android:style/Theme.DeviceDefault.QuickSettings">
+ <style name="edit_theme" parent="qs_base">
<item name="android:colorBackground">?android:attr/colorSecondary</item>
</style>
diff --git a/packages/SystemUI/src/com/android/systemui/ExpandHelper.java b/packages/SystemUI/src/com/android/systemui/ExpandHelper.java
index 7fed3e8..377fab5 100644
--- a/packages/SystemUI/src/com/android/systemui/ExpandHelper.java
+++ b/packages/SystemUI/src/com/android/systemui/ExpandHelper.java
@@ -545,6 +545,16 @@
*/
@VisibleForTesting
void finishExpanding(boolean forceAbort, float velocity) {
+ finishExpanding(forceAbort, velocity, true /* allowAnimation */);
+ }
+
+ /**
+ * Finish the current expand motion
+ * @param forceAbort whether the expansion should be forcefully aborted and returned to the old
+ * state
+ * @param velocity the velocity this was expanded/ collapsed with
+ */
+ private void finishExpanding(boolean forceAbort, float velocity, boolean allowAnimation) {
if (!mExpanding) return;
if (DEBUG) Log.d(TAG, "scale in finishing on view: " + mResizedView);
@@ -568,7 +578,7 @@
mCallback.expansionStateChanged(false);
int naturalHeight = mScaler.getNaturalHeight();
float targetHeight = nowExpanded ? naturalHeight : mSmallSize;
- if (targetHeight != currentHeight && mEnabled) {
+ if (targetHeight != currentHeight && mEnabled && allowAnimation) {
mScaleAnimation.setFloatValues(targetHeight);
mScaleAnimation.setupStartValues();
final View scaledView = mResizedView;
@@ -622,10 +632,22 @@
}
/**
+ * Use this to abort any pending expansions in progress and force that there will be no
+ * animations.
+ */
+ public void cancelImmediately() {
+ cancel(false /* allowAnimation */);
+ }
+
+ /**
* Use this to abort any pending expansions in progress.
*/
public void cancel() {
- finishExpanding(true /* forceAbort */, 0f /* velocity */);
+ cancel(true /* allowAnimation */);
+ }
+
+ private void cancel(boolean allowAnimation) {
+ finishExpanding(true /* forceAbort */, 0f /* velocity */, allowAnimation);
clearView();
// reset the gesture detector
diff --git a/packages/SystemUI/src/com/android/systemui/HardwareUiLayout.java b/packages/SystemUI/src/com/android/systemui/HardwareUiLayout.java
index bb0f2f9..22bb2a3 100644
--- a/packages/SystemUI/src/com/android/systemui/HardwareUiLayout.java
+++ b/packages/SystemUI/src/com/android/systemui/HardwareUiLayout.java
@@ -19,6 +19,7 @@
import android.animation.AnimatorSet;
import android.animation.ObjectAnimator;
import android.content.Context;
+import android.content.res.Configuration;
import android.provider.Settings;
import android.util.AttributeSet;
import android.view.Gravity;
@@ -28,9 +29,15 @@
import android.view.ViewTreeObserver;
import android.widget.FrameLayout;
import android.widget.LinearLayout;
-
import com.android.systemui.tuner.TunerService;
import com.android.systemui.tuner.TunerService.Tunable;
+import com.android.systemui.util.leak.RotationUtils;
+
+import java.util.ArrayList;
+
+import static com.android.systemui.util.leak.RotationUtils.ROTATION_LANDSCAPE;
+import static com.android.systemui.util.leak.RotationUtils.ROTATION_NONE;
+import static com.android.systemui.util.leak.RotationUtils.ROTATION_SEASCAPE;
public class HardwareUiLayout extends FrameLayout implements Tunable {
@@ -49,7 +56,7 @@
private int mEndPoint;
private boolean mEdgeBleed;
private boolean mRoundedDivider;
- private boolean mLandscape;
+ private int mRotation = ROTATION_NONE;
private boolean mRotatedBackground;
public HardwareUiLayout(Context context, AttributeSet attrs) {
@@ -93,8 +100,10 @@
private void updateEdgeMargin(int edge) {
if (mChild != null) {
MarginLayoutParams params = (MarginLayoutParams) mChild.getLayoutParams();
- if (mLandscape) {
+ if (mRotation == ROTATION_LANDSCAPE) {
params.topMargin = edge;
+ } else if (mRotation == ROTATION_SEASCAPE) {
+ params.bottomMargin = edge;
} else {
params.rightMargin = edge;
}
@@ -118,6 +127,7 @@
mChild.addOnLayoutChangeListener(
(v, left, top, right, bottom, oldLeft, oldTop, oldRight, oldBottom) ->
updatePosition());
+ updateRotation();
} else {
return;
}
@@ -127,30 +137,69 @@
animateChild(mOldHeight, newHeight);
}
post(() -> updatePosition());
- boolean landscape = getMeasuredWidth() > getMeasuredHeight();
- if (landscape != mLandscape) {
- mLandscape = landscape;
- if (mLandscape) {
- toLandscape();
- if (mChild instanceof LinearLayout) {
- mRotatedBackground = true;
- mBackground.setRotatedBackground(true);
- ((LinearLayout) mChild).setOrientation(LinearLayout.HORIZONTAL);
- swapDimens(mChild);
+ }
+
+ @Override
+ protected void onConfigurationChanged(Configuration newConfig) {
+ super.onConfigurationChanged(newConfig);
+ updateRotation();
+ }
+
+ private void updateRotation() {
+ int rotation = RotationUtils.getRotation(getContext());
+ if (rotation != mRotation) {
+ rotate(mRotation, rotation);
+ mRotation = rotation;
+ }
+ }
+
+ private void rotate(int from, int to) {
+ if (from != ROTATION_NONE && to != ROTATION_NONE) {
+ // Rather than handling this confusing case, just do 2 rotations.
+ rotate(from, ROTATION_NONE);
+ rotate(ROTATION_NONE, to);
+ return;
+ }
+ if (from == ROTATION_LANDSCAPE || to == ROTATION_SEASCAPE) {
+ rotateRight();
+ } else {
+ rotateLeft();
+ }
+ if (to != ROTATION_NONE) {
+ if (mChild instanceof LinearLayout) {
+ mRotatedBackground = true;
+ mBackground.setRotatedBackground(true);
+ LinearLayout linearLayout = (LinearLayout) mChild;
+ if (to == ROTATION_SEASCAPE) {
+ swapOrder(linearLayout);
}
- } else {
- fromLandscape();
- if (mChild instanceof LinearLayout) {
- mRotatedBackground = false;
- mBackground.setRotatedBackground(false);
- ((LinearLayout) mChild).setOrientation(LinearLayout.VERTICAL);
- swapDimens(mChild);
+ linearLayout.setOrientation(LinearLayout.HORIZONTAL);
+ swapDimens(this.mChild);
+ }
+ } else {
+ if (mChild instanceof LinearLayout) {
+ mRotatedBackground = false;
+ mBackground.setRotatedBackground(false);
+ LinearLayout linearLayout = (LinearLayout) mChild;
+ if (from == ROTATION_SEASCAPE) {
+ swapOrder(linearLayout);
}
+ linearLayout.setOrientation(LinearLayout.VERTICAL);
+ swapDimens(mChild);
}
}
}
- private void fromLandscape() {
+ private void swapOrder(LinearLayout linearLayout) {
+ ArrayList<View> children = new ArrayList<>();
+ for (int i = 0; i < linearLayout.getChildCount(); i++) {
+ children.add(0, linearLayout.getChildAt(i));
+ linearLayout.removeViewAt(i);
+ }
+ children.forEach(v -> linearLayout.addView(v));
+ }
+
+ private void rotateRight() {
rotateRight(this);
rotateRight(mChild);
swapDimens(this);
@@ -202,7 +251,7 @@
return retGravity;
}
- private void toLandscape() {
+ private void rotateLeft() {
rotateLeft(this);
rotateLeft(mChild);
swapDimens(this);
diff --git a/packages/SystemUI/src/com/android/systemui/Prefs.java b/packages/SystemUI/src/com/android/systemui/Prefs.java
index 3cc81df..4437d31 100644
--- a/packages/SystemUI/src/com/android/systemui/Prefs.java
+++ b/packages/SystemUI/src/com/android/systemui/Prefs.java
@@ -47,6 +47,7 @@
Key.QS_INVERT_COLORS_ADDED,
Key.QS_WORK_ADDED,
Key.QS_NIGHTDISPLAY_ADDED,
+ Key.SEEN_MULTI_USER,
})
public @interface Key {
@Deprecated
@@ -62,12 +63,18 @@
String DND_FAVORITE_BUCKET_INDEX = "DndCountdownMinuteIndex";
String DND_NONE_SELECTED = "DndNoneSelected";
String DND_FAVORITE_ZEN = "DndFavoriteZen";
- String QS_HOTSPOT_ADDED = "QsHotspotAdded";
- String QS_DATA_SAVER_ADDED = "QsDataSaverAdded";
String QS_DATA_SAVER_DIALOG_SHOWN = "QsDataSaverDialogShown";
+ @Deprecated
+ String QS_HOTSPOT_ADDED = "QsHotspotAdded";
+ @Deprecated
+ String QS_DATA_SAVER_ADDED = "QsDataSaverAdded";
+ @Deprecated
String QS_INVERT_COLORS_ADDED = "QsInvertColorsAdded";
+ @Deprecated
String QS_WORK_ADDED = "QsWorkAdded";
+ @Deprecated
String QS_NIGHTDISPLAY_ADDED = "QsNightDisplayAdded";
+ String SEEN_MULTI_USER = "HasSeenMultiUser";
}
public static boolean getBoolean(Context context, @Key String key, boolean defaultValue) {
diff --git a/packages/SystemUI/src/com/android/systemui/RoundedCorners.java b/packages/SystemUI/src/com/android/systemui/RoundedCorners.java
index 73e0d7f..40ea4ec 100644
--- a/packages/SystemUI/src/com/android/systemui/RoundedCorners.java
+++ b/packages/SystemUI/src/com/android/systemui/RoundedCorners.java
@@ -93,16 +93,17 @@
private void setupPadding(int padding) {
// Add some padding to all the content near the edge of the screen.
StatusBar sb = getComponent(StatusBar.class);
- View statusBar = sb.getStatusBarWindow();
+ View statusBar = (sb != null ? sb.getStatusBarWindow() : null);
+ if (statusBar != null) {
+ TunablePadding.addTunablePadding(statusBar.findViewById(R.id.keyguard_header), PADDING,
+ padding, FLAG_END);
- TunablePadding.addTunablePadding(statusBar.findViewById(R.id.keyguard_header), PADDING,
- padding, FLAG_END);
-
- FragmentHostManager fragmentHostManager = FragmentHostManager.get(statusBar);
- fragmentHostManager.addTagListener(CollapsedStatusBarFragment.TAG,
- new TunablePaddingTagListener(padding, R.id.status_bar));
- fragmentHostManager.addTagListener(QS.TAG,
- new TunablePaddingTagListener(padding, R.id.header));
+ FragmentHostManager fragmentHostManager = FragmentHostManager.get(statusBar);
+ fragmentHostManager.addTagListener(CollapsedStatusBarFragment.TAG,
+ new TunablePaddingTagListener(padding, R.id.status_bar));
+ fragmentHostManager.addTagListener(QS.TAG,
+ new TunablePaddingTagListener(padding, R.id.header));
+ }
}
private WindowManager.LayoutParams getWindowLayoutParams() {
diff --git a/packages/SystemUI/src/com/android/systemui/classifier/FalsingManager.java b/packages/SystemUI/src/com/android/systemui/classifier/FalsingManager.java
index 8506734..e92ed2f 100644
--- a/packages/SystemUI/src/com/android/systemui/classifier/FalsingManager.java
+++ b/packages/SystemUI/src/com/android/systemui/classifier/FalsingManager.java
@@ -34,7 +34,6 @@
import com.android.systemui.Dependency;
import com.android.systemui.UiOffloadThread;
import com.android.systemui.analytics.DataCollector;
-import com.android.systemui.recents.misc.SystemServicesProxy;
import com.android.systemui.statusbar.StatusBarState;
import java.io.PrintWriter;
@@ -76,6 +75,7 @@
private boolean mSessionActive = false;
private int mState = StatusBarState.SHADE;
private boolean mScreenOn;
+ private boolean mShowingAod;
private Runnable mPendingWtf;
protected final ContentObserver mSettingsObserver = new ContentObserver(mHandler) {
@@ -122,7 +122,7 @@
.append(" mState=").append(StatusBarState.toShortString(mState))
.toString()
);
- return isEnabled() && mScreenOn && (mState == StatusBarState.KEYGUARD);
+ return isEnabled() && mScreenOn && (mState == StatusBarState.KEYGUARD) && !mShowingAod;
}
private boolean sessionEntrypoint() {
@@ -144,6 +144,14 @@
}
}
+ public void updateSessionActive() {
+ if (shouldSessionBeActive()) {
+ sessionEntrypoint();
+ } else {
+ sessionExitpoint(false /* force */);
+ }
+ }
+
private void onSessionStart() {
if (FalsingLog.ENABLED) {
FalsingLog.i("onSessionStart", "classifierEnabled=" + isClassiferEnabled());
@@ -249,6 +257,11 @@
return mEnforceBouncer;
}
+ public void setShowingAod(boolean showingAod) {
+ mShowingAod = showingAod;
+ updateSessionActive();
+ }
+
public void setStatusBarState(int state) {
if (FalsingLog.ENABLED) {
FalsingLog.i("setStatusBarState", new StringBuilder()
@@ -257,11 +270,7 @@
.toString());
}
mState = state;
- if (shouldSessionBeActive()) {
- sessionEntrypoint();
- } else {
- sessionExitpoint(false /* force */);
- }
+ updateSessionActive();
}
public void onScreenTurningOn() {
diff --git a/packages/SystemUI/src/com/android/systemui/doze/DozeFactory.java b/packages/SystemUI/src/com/android/systemui/doze/DozeFactory.java
index 1cc10c2..4804ac2 100644
--- a/packages/SystemUI/src/com/android/systemui/doze/DozeFactory.java
+++ b/packages/SystemUI/src/com/android/systemui/doze/DozeFactory.java
@@ -19,11 +19,14 @@
import android.app.AlarmManager;
import android.app.Application;
import android.content.Context;
+import android.hardware.Sensor;
import android.hardware.SensorManager;
import android.os.Handler;
import com.android.internal.hardware.AmbientDisplayConfiguration;
+import com.android.systemui.R;
import com.android.systemui.SystemUIApplication;
+import com.android.systemui.classifier.FalsingManager;
import com.android.systemui.statusbar.phone.DozeParameters;
import com.android.systemui.util.wakelock.DelayedWakeLock;
import com.android.systemui.util.wakelock.WakeLock;
@@ -46,25 +49,38 @@
WakeLock wakeLock = new DelayedWakeLock(handler,
WakeLock.createPartial(context, "Doze"));
- DozeMachine machine = new DozeMachine(
- DozeSuspendScreenStatePreventingAdapter.wrapIfNeeded(
- DozeScreenStatePreventingAdapter.wrapIfNeeded(dozeService, params), params),
- config,
- wakeLock);
+ DozeMachine.Service wrappedService = DozeSuspendScreenStatePreventingAdapter.wrapIfNeeded(
+ DozeScreenStatePreventingAdapter.wrapIfNeeded(dozeService, params), params);
+ DozeMachine machine = new DozeMachine(wrappedService, config, wakeLock);
machine.setParts(new DozeMachine.Part[]{
- createDozeTriggers(context, sensorManager, host, config, params, handler, wakeLock,
- machine),
+ new DozePauser(handler, machine, alarmManager),
+ new DozeFalsingManagerAdapter(FalsingManager.getInstance(context)),
+ createDozeTriggers(context, sensorManager, host, alarmManager, config, params,
+ handler, wakeLock, machine),
createDozeUi(context, host, wakeLock, machine, handler, alarmManager),
+ createDozeScreenState(wrappedService),
+ createDozeScreenBrightness(context, wrappedService, sensorManager, handler),
});
return machine;
}
+ private DozeMachine.Part createDozeScreenState(DozeMachine.Service service) {
+ return new DozeScreenState(service);
+ }
+
+ private DozeMachine.Part createDozeScreenBrightness(Context context,
+ DozeMachine.Service service, SensorManager sensorManager, Handler handler) {
+ Sensor sensor = DozeSensors.findSensorWithType(sensorManager,
+ context.getString(R.string.doze_brightness_sensor_type));
+ return new DozeScreenBrightness(context, service, sensorManager, sensor, handler);
+ }
+
private DozeTriggers createDozeTriggers(Context context, SensorManager sensorManager,
- DozeHost host, AmbientDisplayConfiguration config, DozeParameters params,
- Handler handler, WakeLock wakeLock, DozeMachine machine) {
+ DozeHost host, AlarmManager alarmManager, AmbientDisplayConfiguration config,
+ DozeParameters params, Handler handler, WakeLock wakeLock, DozeMachine machine) {
boolean allowPulseTriggers = true;
- return new DozeTriggers(context, machine, host, config, params,
+ return new DozeTriggers(context, machine, host, alarmManager, config, params,
sensorManager, handler, wakeLock, allowPulseTriggers);
}
diff --git a/packages/SystemUI/src/com/android/systemui/doze/DozeFalsingManagerAdapter.java b/packages/SystemUI/src/com/android/systemui/doze/DozeFalsingManagerAdapter.java
new file mode 100644
index 0000000..00ca9a4
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/doze/DozeFalsingManagerAdapter.java
@@ -0,0 +1,47 @@
+/*
+ * 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.doze;
+
+import com.android.systemui.classifier.FalsingManager;
+
+/**
+ * Notifies FalsingManager of whether or not AOD is showing.
+ */
+public class DozeFalsingManagerAdapter implements DozeMachine.Part {
+
+ private final FalsingManager mFalsingManager;
+
+ public DozeFalsingManagerAdapter(FalsingManager falsingManager) {
+ mFalsingManager = falsingManager;
+ }
+
+ @Override
+ public void transitionTo(DozeMachine.State oldState, DozeMachine.State newState) {
+ mFalsingManager.setShowingAod(isAodMode(newState));
+ }
+
+ private boolean isAodMode(DozeMachine.State state) {
+ switch (state) {
+ case DOZE_AOD:
+ case DOZE_AOD_PAUSING:
+ case DOZE_AOD_PAUSED:
+ return true;
+ default:
+ return false;
+ }
+ }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/doze/DozeMachine.java b/packages/SystemUI/src/com/android/systemui/doze/DozeMachine.java
index 5526e6b..0be4eda8 100644
--- a/packages/SystemUI/src/com/android/systemui/doze/DozeMachine.java
+++ b/packages/SystemUI/src/com/android/systemui/doze/DozeMachine.java
@@ -60,13 +60,16 @@
/** Doze is done. DozeService is finished. */
FINISH,
/** AOD, but the display is temporarily off. */
- DOZE_AOD_PAUSED;
+ DOZE_AOD_PAUSED,
+ /** AOD, prox is near, transitions to DOZE_AOD_PAUSED after a timeout. */
+ DOZE_AOD_PAUSING;
boolean canPulse() {
switch (this) {
case DOZE:
case DOZE_AOD:
case DOZE_AOD_PAUSED:
+ case DOZE_AOD_PAUSING:
return true;
default:
return false;
@@ -93,6 +96,7 @@
case DOZE_PULSING:
return Display.STATE_ON;
case DOZE_AOD:
+ case DOZE_AOD_PAUSING:
return Display.STATE_DOZE_SUSPEND;
default:
return Display.STATE_UNKNOWN;
@@ -222,7 +226,6 @@
updatePulseReason(newState, oldState, pulseReason);
performTransitionOnComponents(oldState, newState);
- updateScreenState(newState);
updateWakeLockState(newState);
resolveIntermediateState(newState);
@@ -284,7 +287,8 @@
if (mState == State.FINISH) {
return State.FINISH;
}
- if ((mState == State.DOZE_AOD_PAUSED || mState == State.DOZE_AOD || mState == State.DOZE)
+ if ((mState == State.DOZE_AOD_PAUSED || mState == State.DOZE_AOD_PAUSING
+ || mState == State.DOZE_AOD || mState == State.DOZE)
&& requestedState == State.DOZE_PULSE_DONE) {
Log.i(TAG, "Dropping pulse done because current state is already done: " + mState);
return mState;
@@ -307,13 +311,6 @@
}
}
- private void updateScreenState(State newState) {
- int state = newState.screenState();
- if (state != Display.STATE_UNKNOWN) {
- mDozeService.setDozeScreenState(state);
- }
- }
-
private void resolveIntermediateState(State state) {
switch (state) {
case INITIALIZED:
@@ -360,5 +357,36 @@
/** Request waking up. */
void requestWakeUp();
+
+ /** Set screen brightness */
+ void setDozeScreenBrightness(int brightness);
+
+ class Delegate implements Service {
+ private final Service mDelegate;
+
+ public Delegate(Service delegate) {
+ mDelegate = delegate;
+ }
+
+ @Override
+ public void finish() {
+ mDelegate.finish();
+ }
+
+ @Override
+ public void setDozeScreenState(int state) {
+ mDelegate.setDozeScreenState(state);
+ }
+
+ @Override
+ public void requestWakeUp() {
+ mDelegate.requestWakeUp();
+ }
+
+ @Override
+ public void setDozeScreenBrightness(int brightness) {
+ mDelegate.setDozeScreenBrightness(brightness);
+ }
+ }
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/doze/DozePauser.java b/packages/SystemUI/src/com/android/systemui/doze/DozePauser.java
new file mode 100644
index 0000000..a33b454c
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/doze/DozePauser.java
@@ -0,0 +1,53 @@
+/*
+ * 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.doze;
+
+import android.app.AlarmManager;
+import android.os.Handler;
+
+import com.android.systemui.util.AlarmTimeout;
+
+/**
+ * Moves the doze machine from the pausing to the paused state after a timeout.
+ */
+public class DozePauser implements DozeMachine.Part {
+ public static final String TAG = DozePauser.class.getSimpleName();
+ private static final long TIMEOUT = 10 * 1000;
+ private final AlarmTimeout mPauseTimeout;
+ private final DozeMachine mMachine;
+
+ public DozePauser(Handler handler, DozeMachine machine, AlarmManager alarmManager) {
+ mMachine = machine;
+ mPauseTimeout = new AlarmTimeout(alarmManager, this::onTimeout, TAG, handler);
+ }
+
+ @Override
+ public void transitionTo(DozeMachine.State oldState, DozeMachine.State newState) {
+ switch (newState) {
+ case DOZE_AOD_PAUSING:
+ mPauseTimeout.schedule(TIMEOUT, AlarmTimeout.MODE_IGNORE_IF_SCHEDULED);
+ break;
+ default:
+ mPauseTimeout.cancel();
+ break;
+ }
+ }
+
+ private void onTimeout() {
+ mMachine.requestState(DozeMachine.State.DOZE_AOD_PAUSED);
+ }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/doze/DozeScreenBrightness.java b/packages/SystemUI/src/com/android/systemui/doze/DozeScreenBrightness.java
new file mode 100644
index 0000000..e461986
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/doze/DozeScreenBrightness.java
@@ -0,0 +1,92 @@
+/*
+ * 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.doze;
+
+import android.content.Context;
+import android.hardware.Sensor;
+import android.hardware.SensorEvent;
+import android.hardware.SensorEventListener;
+import android.hardware.SensorManager;
+import android.os.Handler;
+
+/**
+ * Controls the screen brightness when dozing.
+ */
+public class DozeScreenBrightness implements DozeMachine.Part, SensorEventListener {
+ private final Context mContext;
+ private final DozeMachine.Service mDozeService;
+ private final Handler mHandler;
+ private final SensorManager mSensorManager;
+ private final Sensor mLightSensor;
+ private boolean mRegistered;
+
+ public DozeScreenBrightness(Context context, DozeMachine.Service service,
+ SensorManager sensorManager, Sensor lightSensor, Handler handler) {
+ mContext = context;
+ mDozeService = service;
+ mSensorManager = sensorManager;
+ mLightSensor = lightSensor;
+ mHandler = handler;
+ }
+
+ @Override
+ public void transitionTo(DozeMachine.State oldState, DozeMachine.State newState) {
+ switch (newState) {
+ case INITIALIZED:
+ resetBrightnessToDefault();
+ break;
+ case DOZE_AOD:
+ case DOZE_REQUEST_PULSE:
+ setLightSensorEnabled(true);
+ break;
+ case DOZE:
+ case DOZE_AOD_PAUSED:
+ setLightSensorEnabled(false);
+ resetBrightnessToDefault();
+ break;
+ case FINISH:
+ setLightSensorEnabled(false);
+ break;
+ }
+ }
+
+ @Override
+ public void onSensorChanged(SensorEvent event) {
+ if (mRegistered) {
+ mDozeService.setDozeScreenBrightness(Math.max(1, (int) event.values[0]));
+ }
+ }
+
+ @Override
+ public void onAccuracyChanged(Sensor sensor, int accuracy) {
+ }
+
+ private void resetBrightnessToDefault() {
+ mDozeService.setDozeScreenBrightness(mContext.getResources().getInteger(
+ com.android.internal.R.integer.config_screenBrightnessDoze));
+ }
+
+ private void setLightSensorEnabled(boolean enabled) {
+ if (enabled && !mRegistered && mLightSensor != null) {
+ mRegistered = mSensorManager.registerListener(this, mLightSensor,
+ SensorManager.SENSOR_DELAY_NORMAL, mHandler);
+ } else if (!enabled && mRegistered) {
+ mSensorManager.unregisterListener(this);
+ mRegistered = false;
+ }
+ }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/doze/DozeScreenState.java b/packages/SystemUI/src/com/android/systemui/doze/DozeScreenState.java
new file mode 100644
index 0000000..846ec27
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/doze/DozeScreenState.java
@@ -0,0 +1,39 @@
+/*
+ * 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.doze;
+
+import android.content.Context;
+import android.view.Display;
+
+/**
+ * Controls the screen when dozing.
+ */
+public class DozeScreenState implements DozeMachine.Part {
+ private final DozeMachine.Service mDozeService;
+
+ public DozeScreenState(DozeMachine.Service service) {
+ mDozeService = service;
+ }
+
+ @Override
+ public void transitionTo(DozeMachine.State oldState, DozeMachine.State newState) {
+ int screenState = newState.screenState();
+ if (screenState != Display.STATE_UNKNOWN) {
+ mDozeService.setDozeScreenState(screenState);
+ }
+ }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/doze/DozeScreenStatePreventingAdapter.java b/packages/SystemUI/src/com/android/systemui/doze/DozeScreenStatePreventingAdapter.java
index ad5897a..5d0a9d7 100644
--- a/packages/SystemUI/src/com/android/systemui/doze/DozeScreenStatePreventingAdapter.java
+++ b/packages/SystemUI/src/com/android/systemui/doze/DozeScreenStatePreventingAdapter.java
@@ -24,18 +24,11 @@
/**
* Prevents usage of doze screen states on devices that don't support them.
*/
-public class DozeScreenStatePreventingAdapter implements DozeMachine.Service {
-
- private final DozeMachine.Service mInner;
+public class DozeScreenStatePreventingAdapter extends DozeMachine.Service.Delegate {
@VisibleForTesting
DozeScreenStatePreventingAdapter(DozeMachine.Service inner) {
- mInner = inner;
- }
-
- @Override
- public void finish() {
- mInner.finish();
+ super(inner);
}
@Override
@@ -43,12 +36,7 @@
if (state == Display.STATE_DOZE || state == Display.STATE_DOZE_SUSPEND) {
state = Display.STATE_ON;
}
- mInner.setDozeScreenState(state);
- }
-
- @Override
- public void requestWakeUp() {
- mInner.requestWakeUp();
+ super.setDozeScreenState(state);
}
/**
diff --git a/packages/SystemUI/src/com/android/systemui/doze/DozeSensors.java b/packages/SystemUI/src/com/android/systemui/doze/DozeSensors.java
index 23da716..67de020 100644
--- a/packages/SystemUI/src/com/android/systemui/doze/DozeSensors.java
+++ b/packages/SystemUI/src/com/android/systemui/doze/DozeSensors.java
@@ -18,6 +18,7 @@
import android.annotation.AnyThread;
import android.app.ActivityManager;
+import android.app.AlarmManager;
import android.content.ContentResolver;
import android.content.Context;
import android.database.ContentObserver;
@@ -29,6 +30,7 @@
import android.hardware.TriggerEventListener;
import android.net.Uri;
import android.os.Handler;
+import android.os.SystemClock;
import android.os.UserHandle;
import android.provider.Settings;
import android.text.TextUtils;
@@ -38,6 +40,7 @@
import com.android.internal.logging.MetricsLogger;
import com.android.internal.logging.nano.MetricsProto;
import com.android.systemui.statusbar.phone.DozeParameters;
+import com.android.systemui.util.AlarmTimeout;
import com.android.systemui.util.wakelock.WakeLock;
import java.io.PrintWriter;
@@ -51,6 +54,7 @@
private static final String TAG = "DozeSensors";
private final Context mContext;
+ private final AlarmManager mAlarmManager;
private final SensorManager mSensorManager;
private final TriggerSensor[] mSensors;
private final ContentResolver mResolver;
@@ -65,10 +69,12 @@
private final ProxSensor mProxSensor;
- public DozeSensors(Context context, SensorManager sensorManager, DozeParameters dozeParameters,
+ public DozeSensors(Context context, AlarmManager alarmManager, SensorManager sensorManager,
+ DozeParameters dozeParameters,
AmbientDisplayConfiguration config, WakeLock wakeLock, Callback callback,
Consumer<Boolean> proxCallback) {
mContext = context;
+ mAlarmManager = alarmManager;
mSensorManager = sensorManager;
mDozeParameters = dozeParameters;
mConfig = config;
@@ -100,10 +106,14 @@
}
private Sensor findSensorWithType(String type) {
+ return findSensorWithType(mSensorManager, type);
+ }
+
+ static Sensor findSensorWithType(SensorManager sensorManager, String type) {
if (TextUtils.isEmpty(type)) {
return null;
}
- List<Sensor> sensorList = mSensorManager.getSensorList(Sensor.TYPE_ALL);
+ List<Sensor> sensorList = sensorManager.getSensorList(Sensor.TYPE_ALL);
for (Sensor s : sensorList) {
if (type.equals(s.getStringType())) {
return s;
@@ -140,7 +150,7 @@
}
public void setProxListening(boolean listen) {
- mProxSensor.setRegistered(listen);
+ mProxSensor.setRequested(listen);
}
private final ContentObserver mSettingsObserver = new ContentObserver(mHandler) {
@@ -168,11 +178,23 @@
private class ProxSensor implements SensorEventListener {
+ static final long COOLDOWN_TRIGGER = 2 * 1000;
+ static final long COOLDOWN_PERIOD = 5 * 1000;
+
+ boolean mRequested;
boolean mRegistered;
Boolean mCurrentlyFar;
+ long mLastNear;
+ final AlarmTimeout mCooldownTimer;
- void setRegistered(boolean register) {
- if (mRegistered == register) {
+
+ public ProxSensor() {
+ mCooldownTimer = new AlarmTimeout(mAlarmManager, this::updateRegistered,
+ "prox_cooldown", mHandler);
+ }
+
+ void setRequested(boolean requested) {
+ if (mRequested == requested) {
// Send an update even if we don't re-register.
mHandler.post(() -> {
if (mCurrentlyFar != null) {
@@ -181,6 +203,18 @@
});
return;
}
+ mRequested = requested;
+ updateRegistered();
+ }
+
+ private void updateRegistered() {
+ setRegistered(mRequested && !mCooldownTimer.isScheduled());
+ }
+
+ private void setRegistered(boolean register) {
+ if (mRegistered == register) {
+ return;
+ }
if (register) {
mRegistered = mSensorManager.registerListener(this,
mSensorManager.getDefaultSensor(Sensor.TYPE_PROXIMITY),
@@ -196,6 +230,17 @@
public void onSensorChanged(SensorEvent event) {
mCurrentlyFar = event.values[0] >= event.sensor.getMaximumRange();
mProxCallback.accept(mCurrentlyFar);
+
+ long now = SystemClock.elapsedRealtime();
+ if (!mCurrentlyFar) {
+ mLastNear = now;
+ } else if (mCurrentlyFar && now - mLastNear < COOLDOWN_TRIGGER) {
+ // If the last near was very recent, we might be using more power for prox
+ // wakeups than we're saving from turning of the screen. Instead, turn it off
+ // for a while.
+ mCooldownTimer.schedule(COOLDOWN_PERIOD, AlarmTimeout.MODE_IGNORE_IF_SCHEDULED);
+ updateRegistered();
+ }
}
@Override
diff --git a/packages/SystemUI/src/com/android/systemui/doze/DozeService.java b/packages/SystemUI/src/com/android/systemui/doze/DozeService.java
index d9fb087..98b1106 100644
--- a/packages/SystemUI/src/com/android/systemui/doze/DozeService.java
+++ b/packages/SystemUI/src/com/android/systemui/doze/DozeService.java
@@ -76,8 +76,6 @@
super.onDreamingStarted();
mDozeMachine.requestState(DozeMachine.State.INITIALIZED);
startDozing();
- setDozeScreenBrightness(getResources().getInteger(
- com.android.internal.R.integer.config_screenBrightnessDoze));
if (mDozePlugin != null) {
mDozePlugin.onDreamingStarted();
}
diff --git a/packages/SystemUI/src/com/android/systemui/doze/DozeSuspendScreenStatePreventingAdapter.java b/packages/SystemUI/src/com/android/systemui/doze/DozeSuspendScreenStatePreventingAdapter.java
index 1e06797..1c6521f 100644
--- a/packages/SystemUI/src/com/android/systemui/doze/DozeSuspendScreenStatePreventingAdapter.java
+++ b/packages/SystemUI/src/com/android/systemui/doze/DozeSuspendScreenStatePreventingAdapter.java
@@ -24,18 +24,11 @@
/**
* Prevents usage of doze screen states on devices that don't support them.
*/
-public class DozeSuspendScreenStatePreventingAdapter implements DozeMachine.Service {
-
- private final DozeMachine.Service mInner;
+public class DozeSuspendScreenStatePreventingAdapter extends DozeMachine.Service.Delegate {
@VisibleForTesting
DozeSuspendScreenStatePreventingAdapter(DozeMachine.Service inner) {
- mInner = inner;
- }
-
- @Override
- public void finish() {
- mInner.finish();
+ super(inner);
}
@Override
@@ -43,12 +36,7 @@
if (state == Display.STATE_DOZE_SUSPEND) {
state = Display.STATE_DOZE;
}
- mInner.setDozeScreenState(state);
- }
-
- @Override
- public void requestWakeUp() {
- mInner.requestWakeUp();
+ super.setDozeScreenState(state);
}
/**
diff --git a/packages/SystemUI/src/com/android/systemui/doze/DozeTriggers.java b/packages/SystemUI/src/com/android/systemui/doze/DozeTriggers.java
index 8d1d6e0..9981972 100644
--- a/packages/SystemUI/src/com/android/systemui/doze/DozeTriggers.java
+++ b/packages/SystemUI/src/com/android/systemui/doze/DozeTriggers.java
@@ -16,6 +16,7 @@
package com.android.systemui.doze;
+import android.app.AlarmManager;
import android.app.UiModeManager;
import android.content.BroadcastReceiver;
import android.content.Context;
@@ -70,7 +71,7 @@
public DozeTriggers(Context context, DozeMachine machine, DozeHost dozeHost,
- AmbientDisplayConfiguration config,
+ AlarmManager alarmManager, AmbientDisplayConfiguration config,
DozeParameters dozeParameters, SensorManager sensorManager, Handler handler,
WakeLock wakeLock, boolean allowPulseTriggers) {
mContext = context;
@@ -82,8 +83,8 @@
mHandler = handler;
mWakeLock = wakeLock;
mAllowPulseTriggers = allowPulseTriggers;
- mDozeSensors = new DozeSensors(context, mSensorManager, dozeParameters, config,
- wakeLock, this::onSensor, this::onProximityFar);
+ mDozeSensors = new DozeSensors(context, alarmManager, mSensorManager, dozeParameters,
+ config, wakeLock, this::onSensor, this::onProximityFar);
mUiModeManager = mContext.getSystemService(UiModeManager.class);
}
@@ -152,18 +153,22 @@
private void onProximityFar(boolean far) {
final boolean near = !far;
- DozeMachine.State state = mMachine.getState();
+ final DozeMachine.State state = mMachine.getState();
+ final boolean paused = (state == DozeMachine.State.DOZE_AOD_PAUSED);
+ final boolean pausing = (state == DozeMachine.State.DOZE_AOD_PAUSING);
+ final boolean aod = (state == DozeMachine.State.DOZE_AOD);
+
if (near && state == DozeMachine.State.DOZE_PULSING) {
if (DEBUG) Log.i(TAG, "Prox NEAR, ending pulse");
DozeLog.tracePulseCanceledByProx(mContext);
mMachine.requestState(DozeMachine.State.DOZE_PULSE_DONE);
}
- if (far && state == DozeMachine.State.DOZE_AOD_PAUSED) {
+ if (far && (paused || pausing)) {
if (DEBUG) Log.i(TAG, "Prox FAR, unpausing AOD");
mMachine.requestState(DozeMachine.State.DOZE_AOD);
- } else if (near && state == DozeMachine.State.DOZE_AOD) {
+ } else if (near && aod) {
if (DEBUG) Log.i(TAG, "Prox NEAR, pausing AOD");
- mMachine.requestState(DozeMachine.State.DOZE_AOD_PAUSED);
+ mMachine.requestState(DozeMachine.State.DOZE_AOD_PAUSING);
}
}
@@ -186,12 +191,13 @@
case DOZE:
case DOZE_AOD:
mDozeSensors.setProxListening(newState != DozeMachine.State.DOZE);
- mDozeSensors.setListening(true);
if (oldState != DozeMachine.State.INITIALIZED) {
mDozeSensors.reregisterAllSensors();
}
+ mDozeSensors.setListening(true);
break;
case DOZE_AOD_PAUSED:
+ case DOZE_AOD_PAUSING:
mDozeSensors.setProxListening(true);
mDozeSensors.setListening(false);
break;
diff --git a/packages/SystemUI/src/com/android/systemui/doze/DozeUi.java b/packages/SystemUI/src/com/android/systemui/doze/DozeUi.java
index cf87fca..1dc37cd 100644
--- a/packages/SystemUI/src/com/android/systemui/doze/DozeUi.java
+++ b/packages/SystemUI/src/com/android/systemui/doze/DozeUi.java
@@ -23,6 +23,7 @@
import android.text.format.Formatter;
import android.util.Log;
+import com.android.systemui.util.AlarmTimeout;
import com.android.systemui.util.wakelock.WakeLock;
import java.util.Calendar;
@@ -35,26 +36,23 @@
private static final long TIME_TICK_DEADLINE_MILLIS = 90 * 1000; // 1.5min
private final Context mContext;
- private final AlarmManager mAlarmManager;
private final DozeHost mHost;
private final Handler mHandler;
private final WakeLock mWakeLock;
private final DozeMachine mMachine;
- private final AlarmManager.OnAlarmListener mTimeTick;
+ private final AlarmTimeout mTimeTicker;
- private boolean mTimeTickScheduled = false;
private long mLastTimeTickElapsed = 0;
public DozeUi(Context context, AlarmManager alarmManager, DozeMachine machine,
WakeLock wakeLock, DozeHost host, Handler handler) {
mContext = context;
- mAlarmManager = alarmManager;
mMachine = machine;
mWakeLock = wakeLock;
mHost = host;
mHandler = handler;
- mTimeTick = this::onTimeTick;
+ mTimeTicker = new AlarmTimeout(alarmManager, this::onTimeTick, "doze_time_tick", handler);
}
private void pulseWhileDozing(int reason) {
@@ -76,6 +74,7 @@
public void transitionTo(DozeMachine.State oldState, DozeMachine.State newState) {
switch (newState) {
case DOZE_AOD:
+ case DOZE_AOD_PAUSING:
scheduleTimeTick();
break;
case DOZE:
@@ -112,25 +111,21 @@
}
private void scheduleTimeTick() {
- if (mTimeTickScheduled) {
+ if (mTimeTicker.isScheduled()) {
return;
}
long delta = roundToNextMinute(System.currentTimeMillis()) - System.currentTimeMillis();
- mAlarmManager.setExact(AlarmManager.ELAPSED_REALTIME_WAKEUP,
- SystemClock.elapsedRealtime() + delta, "doze_time_tick", mTimeTick, mHandler);
-
- mTimeTickScheduled = true;
+ mTimeTicker.schedule(delta, AlarmTimeout.MODE_IGNORE_IF_SCHEDULED);
mLastTimeTickElapsed = SystemClock.elapsedRealtime();
}
private void unscheduleTimeTick() {
- if (!mTimeTickScheduled) {
+ if (!mTimeTicker.isScheduled()) {
return;
}
verifyLastTimeTick();
- mAlarmManager.cancel(mTimeTick);
- mTimeTickScheduled = false;
+ mTimeTicker.cancel();
}
private void verifyLastTimeTick() {
@@ -153,10 +148,6 @@
}
private void onTimeTick() {
- if (!mTimeTickScheduled) {
- // Alarm was canceled, but we still got the callback. Ignore.
- return;
- }
verifyLastTimeTick();
mHost.dozeTimeTick();
@@ -164,7 +155,6 @@
// Keep wakelock until a frame has been pushed.
mHandler.post(mWakeLock.wrap(() -> {}));
- mTimeTickScheduled = false;
scheduleTimeTick();
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/globalactions/GlobalActionsDialog.java b/packages/SystemUI/src/com/android/systemui/globalactions/GlobalActionsDialog.java
index 1a8a474..31d41ac 100644
--- a/packages/SystemUI/src/com/android/systemui/globalactions/GlobalActionsDialog.java
+++ b/packages/SystemUI/src/com/android/systemui/globalactions/GlobalActionsDialog.java
@@ -682,10 +682,14 @@
/** {@inheritDoc} */
public void onClick(DialogInterface dialog, int which) {
- if (!(mAdapter.getItem(which) instanceof SilentModeTriStateAction)) {
+ Action item = mAdapter.getItem(which);
+ if ((item instanceof PowerAction)
+ || (item instanceof RestartAction)) {
+ if (mDialog != null) mDialog.fadeOut();
+ } else if (!(item instanceof SilentModeTriStateAction)) {
dialog.dismiss();
}
- mAdapter.getItem(which).onPress();
+ item.onPress();
}
/**
@@ -1321,6 +1325,17 @@
.start();
}
+ public void fadeOut() {
+ mHardwareLayout.setTranslationX(0);
+ mHardwareLayout.setAlpha(1);
+ mListView.animate()
+ .alpha(0)
+ .translationX(getAnimTranslation())
+ .setDuration(300)
+ .setInterpolator(new LogAccelerateInterpolator())
+ .start();
+ }
+
private float getAnimTranslation() {
return getContext().getResources().getDimension(
com.android.systemui.R.dimen.global_actions_panel_width) / 2;
diff --git a/packages/SystemUI/src/com/android/systemui/qs/AutoAddTracker.java b/packages/SystemUI/src/com/android/systemui/qs/AutoAddTracker.java
new file mode 100644
index 0000000..f960dc5
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/qs/AutoAddTracker.java
@@ -0,0 +1,98 @@
+/*
+ * 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.qs;
+
+import static com.android.systemui.statusbar.phone.AutoTileManager.HOTSPOT;
+import static com.android.systemui.statusbar.phone.AutoTileManager.INVERSION;
+import static com.android.systemui.statusbar.phone.AutoTileManager.NIGHT;
+import static com.android.systemui.statusbar.phone.AutoTileManager.SAVER;
+import static com.android.systemui.statusbar.phone.AutoTileManager.WORK;
+
+import android.content.Context;
+import android.database.ContentObserver;
+import android.os.Handler;
+import android.provider.Settings.Secure;
+import android.text.TextUtils;
+import android.util.ArraySet;
+
+import com.android.internal.annotations.VisibleForTesting;
+import com.android.systemui.Prefs;
+import com.android.systemui.Prefs.Key;
+
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.Collections;
+
+public class AutoAddTracker {
+
+ private static final String[][] CONVERT_PREFS = {
+ {Key.QS_HOTSPOT_ADDED, HOTSPOT},
+ {Key.QS_DATA_SAVER_ADDED, SAVER},
+ {Key.QS_INVERT_COLORS_ADDED, INVERSION},
+ {Key.QS_WORK_ADDED, WORK},
+ {Key.QS_NIGHTDISPLAY_ADDED, NIGHT},
+ };
+
+ private final ArraySet<String> mAutoAdded;
+ private final Context mContext;
+
+ public AutoAddTracker(Context context) {
+ mContext = context;
+ mAutoAdded = new ArraySet<>(getAdded());
+ for (String[] convertPref : CONVERT_PREFS) {
+ if (Prefs.getBoolean(context, convertPref[0], false)) {
+ setTileAdded(convertPref[1]);
+ Prefs.putBoolean(context, convertPref[0], false);
+ }
+ }
+ mContext.getContentResolver().registerContentObserver(
+ Secure.getUriFor(Secure.QS_AUTO_ADDED_TILES), false, mObserver);
+ }
+
+ public boolean isAdded(String tile) {
+ return mAutoAdded.contains(tile);
+ }
+
+ public void setTileAdded(String tile) {
+ if (mAutoAdded.add(tile)) {
+ saveTiles();
+ }
+ }
+
+ public void destroy() {
+ mContext.getContentResolver().unregisterContentObserver(mObserver);
+ }
+
+ private void saveTiles() {
+ Secure.putString(mContext.getContentResolver(), Secure.QS_AUTO_ADDED_TILES,
+ TextUtils.join(",", mAutoAdded));
+ }
+
+ private Collection<String> getAdded() {
+ String current = Secure.getString(mContext.getContentResolver(), Secure.QS_AUTO_ADDED_TILES);
+ if (current == null) {
+ return Collections.emptyList();
+ }
+ return Arrays.asList(current.split(","));
+ }
+
+ @VisibleForTesting
+ protected final ContentObserver mObserver = new ContentObserver(new Handler()) {
+ @Override
+ public void onChange(boolean selfChange) {
+ mAutoAdded.addAll(getAdded());
+ }
+ };
+}
diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSDetailClipper.java b/packages/SystemUI/src/com/android/systemui/qs/QSDetailClipper.java
index a318efc..c454048 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/QSDetailClipper.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/QSDetailClipper.java
@@ -100,4 +100,8 @@
mAnimator = null;
};
};
+
+ public void showBackground() {
+ mBackground.showSecondLayer();
+ }
}
diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSFragment.java b/packages/SystemUI/src/com/android/systemui/qs/QSFragment.java
index f9ccb50..4a91ee0 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/QSFragment.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/QSFragment.java
@@ -89,6 +89,13 @@
if (savedInstanceState != null) {
setExpanded(savedInstanceState.getBoolean(EXTRA_EXPANDED));
setListening(savedInstanceState.getBoolean(EXTRA_LISTENING));
+ int[] loc = new int[2];
+ View edit = view.findViewById(android.R.id.edit);
+ edit.getLocationInWindow(loc);
+ int x = loc[0] + edit.getWidth() / 2;
+ int y = loc[1] + edit.getHeight() / 2;
+ mQSCustomizer.setEditLocation(x, y);
+ mQSCustomizer.restoreInstanceState(savedInstanceState);
}
}
@@ -105,6 +112,7 @@
super.onSaveInstanceState(outState);
outState.putBoolean(EXTRA_EXPANDED, mQsExpanded);
outState.putBoolean(EXTRA_LISTENING, mListening);
+ mQSCustomizer.saveInstanceState(outState);
}
@VisibleForTesting
diff --git a/packages/SystemUI/src/com/android/systemui/qs/customize/QSCustomizer.java b/packages/SystemUI/src/com/android/systemui/qs/customize/QSCustomizer.java
index 30053e3..6c95a80 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/customize/QSCustomizer.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/customize/QSCustomizer.java
@@ -20,6 +20,9 @@
import android.animation.AnimatorListenerAdapter;
import android.content.Context;
import android.content.res.Configuration;
+import android.graphics.drawable.Drawable;
+import android.graphics.drawable.TransitionDrawable;
+import android.os.Bundle;
import android.os.Handler;
import android.os.Looper;
import android.support.v7.widget.DefaultItemAnimator;
@@ -42,6 +45,7 @@
import com.android.systemui.R;
import com.android.systemui.plugins.qs.QS;
import com.android.systemui.plugins.qs.QSTile;
+import com.android.systemui.qs.QSContainerImpl;
import com.android.systemui.qs.QSDetailClipper;
import com.android.systemui.qs.QSTileHost;
import com.android.systemui.statusbar.phone.NotificationsQuickSettingsContainer;
@@ -60,6 +64,7 @@
public class QSCustomizer extends LinearLayout implements OnMenuItemClickListener {
private static final int MENU_RESET = Menu.FIRST;
+ private static final String EXTRA_QS_CUSTOMIZING = "qs_customizing";
private final QSDetailClipper mClipper;
@@ -109,11 +114,16 @@
DefaultItemAnimator animator = new DefaultItemAnimator();
animator.setMoveDuration(TileAdapter.MOVE_DURATION);
mRecyclerView.setItemAnimator(animator);
+ updateNavBackDrop(getResources().getConfiguration());
}
@Override
protected void onConfigurationChanged(Configuration newConfig) {
super.onConfigurationChanged(newConfig);
+ updateNavBackDrop(newConfig);
+ }
+
+ private void updateNavBackDrop(Configuration newConfig) {
View navBackdrop = findViewById(R.id.nav_bar_background);
if (navBackdrop != null) {
boolean shouldShow = newConfig.smallestScreenWidthDp >= 600
@@ -154,6 +164,21 @@
}
}
+
+ public void showImmediately() {
+ if (!isShown) {
+ setVisibility(VISIBLE);
+ mClipper.showBackground();
+ isShown = true;
+ setTileSpecs();
+ setCustomizing(true);
+ queryTiles();
+ mNotifQsContainer.setCustomizerAnimating(false);
+ mNotifQsContainer.setCustomizerShowing(true);
+ Dependency.get(KeyguardMonitor.class).addCallback(mKeyguardCallback);
+ }
+ }
+
private void queryTiles() {
mFinishedFetchingTiles = false;
Runnable tileQueryFetchCompletion = () -> {
@@ -227,6 +252,35 @@
}
}
+
+ public void saveInstanceState(Bundle outState) {
+ if (isShown) {
+ Dependency.get(KeyguardMonitor.class).removeCallback(mKeyguardCallback);
+ }
+ outState.putBoolean(EXTRA_QS_CUSTOMIZING, mCustomizing);
+ }
+
+ public void restoreInstanceState(Bundle savedInstanceState) {
+ boolean customizing = savedInstanceState.getBoolean(EXTRA_QS_CUSTOMIZING);
+ if (customizing) {
+ setVisibility(VISIBLE);
+ addOnLayoutChangeListener(new OnLayoutChangeListener() {
+ @Override
+ public void onLayoutChange(View v, int left, int top, int right, int bottom,
+ int oldLeft,
+ int oldTop, int oldRight, int oldBottom) {
+ removeOnLayoutChangeListener(this);
+ showImmediately();
+ }
+ });
+ }
+ }
+
+ public void setEditLocation(int x, int y) {
+ mX = x;
+ mY = y;
+ }
+
private final Callback mKeyguardCallback = () -> {
if (!isAttachedToWindow()) return;
if (Dependency.get(KeyguardMonitor.class).isShowing() && !mOpening) {
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tileimpl/QSFactoryImpl.java b/packages/SystemUI/src/com/android/systemui/qs/tileimpl/QSFactoryImpl.java
index 17a0d33..77c3bfa 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tileimpl/QSFactoryImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tileimpl/QSFactoryImpl.java
@@ -16,7 +16,9 @@
import android.content.Context;
import android.util.Log;
+import android.view.ContextThemeWrapper;
+import com.android.systemui.R;
import com.android.systemui.plugins.qs.*;
import com.android.systemui.plugins.qs.QSTileView;
import com.android.systemui.qs.external.CustomTile;
@@ -78,7 +80,7 @@
@Override
public QSTileView createTileView(QSTile tile, boolean collapsedView) {
- Context context = mHost.getContext();
+ Context context = new ContextThemeWrapper(mHost.getContext(), R.style.qs_theme);
QSIconView icon = tile.createTileView(context);
if (collapsedView) {
return new QSTileBaseView(context, icon, collapsedView);
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tileimpl/QSIconViewImpl.java b/packages/SystemUI/src/com/android/systemui/qs/tileimpl/QSIconViewImpl.java
index cdd0ebc..6659650 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tileimpl/QSIconViewImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tileimpl/QSIconViewImpl.java
@@ -144,22 +144,26 @@
}
public static void animateGrayScale(int fromColor, int toColor, ImageView iv) {
- final float fromAlpha = Color.alpha(fromColor);
- final float toAlpha = Color.alpha(toColor);
- final float fromChannel = Color.red(fromColor);
- final float toChannel = Color.red(toColor);
+ if (ValueAnimator.areAnimatorsEnabled()) {
+ final float fromAlpha = Color.alpha(fromColor);
+ final float toAlpha = Color.alpha(toColor);
+ final float fromChannel = Color.red(fromColor);
+ final float toChannel = Color.red(toColor);
- ValueAnimator anim = ValueAnimator.ofFloat(0, 1);
- anim.setDuration(QS_ANIM_LENGTH);
+ ValueAnimator anim = ValueAnimator.ofFloat(0, 1);
+ anim.setDuration(QS_ANIM_LENGTH);
+ anim.addUpdateListener(animation -> {
+ float fraction = animation.getAnimatedFraction();
+ int alpha = (int) (fromAlpha + (toAlpha - fromAlpha) * fraction);
+ int channel = (int) (fromChannel + (toChannel - fromChannel) * fraction);
- anim.addUpdateListener(animation -> {
- float fraction = animation.getAnimatedFraction();
- int alpha = (int) (fromAlpha + (toAlpha - fromAlpha) * fraction);
- int channel = (int) (fromChannel + (toChannel - fromChannel) * fraction);
+ setTint(iv, Color.argb(alpha, channel, channel, channel));
+ });
- setTint(iv, Color.argb(alpha, channel, channel, channel));
- });
- anim.start();
+ anim.start();
+ } else {
+ setTint(iv, toColor);
+ }
}
public static void setTint(ImageView iv, int color) {
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/BluetoothTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/BluetoothTile.java
index 36677a4..14afbfa 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/BluetoothTile.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/BluetoothTile.java
@@ -30,6 +30,7 @@
import com.android.internal.logging.MetricsLogger;
import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
+import com.android.settingslib.Utils;
import com.android.settingslib.bluetooth.CachedBluetoothDevice;
import com.android.systemui.Dependency;
import com.android.systemui.R;
@@ -271,7 +272,14 @@
int state = mController.getMaxConnectionState(device);
if (state == BluetoothProfile.STATE_CONNECTED) {
item.icon = R.drawable.ic_qs_bluetooth_connected;
- item.line2 = mContext.getString(R.string.quick_settings_connected);
+ int batteryLevel = device.getBatteryLevel();
+ if (batteryLevel != BluetoothDevice.BATTERY_LEVEL_UNKNOWN) {
+ item.line2 = mContext.getString(
+ R.string.quick_settings_connected_battery_level,
+ Utils.formatPercentage(batteryLevel));
+ } else {
+ item.line2 = mContext.getString(R.string.quick_settings_connected);
+ }
item.canDisconnect = true;
items.add(connectedDevices, item);
connectedDevices++;
diff --git a/packages/SystemUI/src/com/android/systemui/recents/RecentsActivity.java b/packages/SystemUI/src/com/android/systemui/recents/RecentsActivity.java
index 4de1214..fa16f8e 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/RecentsActivity.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/RecentsActivity.java
@@ -24,6 +24,7 @@
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
+import android.content.pm.ActivityInfo;
import android.content.res.Configuration;
import android.net.Uri;
import android.os.Bundle;
@@ -42,9 +43,9 @@
import com.android.internal.logging.MetricsLogger;
import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
+import com.android.keyguard.LatencyTracker;
import com.android.systemui.DejankUtils;
import com.android.systemui.Interpolators;
-import com.android.keyguard.LatencyTracker;
import com.android.systemui.R;
import com.android.systemui.recents.events.EventBus;
import com.android.systemui.recents.events.activity.CancelEnterRecentsWindowAnimationEvent;
@@ -110,11 +111,10 @@
private RecentsPackageMonitor mPackageMonitor;
private Handler mHandler = new Handler();
private long mLastTabKeyEventTime;
- private int mLastDeviceOrientation = Configuration.ORIENTATION_UNDEFINED;
- private int mLastDisplayDensity;
private boolean mFinishedOnStartup;
private boolean mIgnoreAltTabRelease;
private boolean mIsVisible;
+ private Configuration mLastConfig;
// Top level views
private RecentsView mRecentsView;
@@ -333,16 +333,11 @@
setContentView(R.layout.recents);
takeKeyEvents(true);
mRecentsView = findViewById(R.id.recents_view);
- mRecentsView.setSystemUiVisibility(View.SYSTEM_UI_FLAG_LAYOUT_STABLE |
- View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN |
- View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION);
mScrimViews = new SystemBarScrimViews(this);
getWindow().getAttributes().privateFlags |=
WindowManager.LayoutParams.PRIVATE_FLAG_FORCE_DECOR_VIEW_VISIBILITY;
- Configuration appConfiguration = Utilities.getAppConfiguration(this);
- mLastDeviceOrientation = appConfiguration.orientation;
- mLastDisplayDensity = appConfiguration.densityDpi;
+ mLastConfig = Utilities.getAppConfiguration(this);
mFocusTimerDuration = getResources().getInteger(R.integer.recents_auto_advance_duration);
mIterateTrigger = new DozeTrigger(mFocusTimerDuration, new Runnable() {
@Override
@@ -485,10 +480,15 @@
Configuration newDeviceConfiguration = Utilities.getAppConfiguration(this);
int numStackTasks = mRecentsView.getStack().getStackTaskCount();
EventBus.getDefault().send(new ConfigurationChangedEvent(false /* fromMultiWindow */,
- mLastDeviceOrientation != newDeviceConfiguration.orientation,
- mLastDisplayDensity != newDeviceConfiguration.densityDpi, numStackTasks > 0));
- mLastDeviceOrientation = newDeviceConfiguration.orientation;
- mLastDisplayDensity = newDeviceConfiguration.densityDpi;
+ mLastConfig.orientation != newDeviceConfiguration.orientation,
+ mLastConfig.densityDpi != newDeviceConfiguration.densityDpi, numStackTasks > 0));
+
+ int configDiff = mLastConfig.updateFrom(newDeviceConfiguration);
+
+ // Recreate activity if an overlay was enabled/disabled
+ if ((configDiff & ActivityInfo.CONFIG_ASSETS_PATHS) != 0) {
+ recreate();
+ }
}
@Override
diff --git a/packages/SystemUI/src/com/android/systemui/recents/ScreenPinningRequest.java b/packages/SystemUI/src/com/android/systemui/recents/ScreenPinningRequest.java
index afc4c6a..316ad16 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/ScreenPinningRequest.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/ScreenPinningRequest.java
@@ -43,14 +43,14 @@
import android.widget.TextView;
import com.android.systemui.R;
+import com.android.systemui.util.leak.RotationUtils;
import java.util.ArrayList;
-public class ScreenPinningRequest implements View.OnClickListener {
+import static com.android.systemui.util.leak.RotationUtils.ROTATION_LANDSCAPE;
+import static com.android.systemui.util.leak.RotationUtils.ROTATION_SEASCAPE;
- private static final int ROTATION_NONE = 0;
- private static final int ROTATION_LANDSCAPE = 1;
- private static final int ROTATION_SEASCAPE = 2;
+public class ScreenPinningRequest implements View.OnClickListener {
private final Context mContext;
@@ -157,7 +157,7 @@
DisplayMetrics metrics = new DisplayMetrics();
mWindowManager.getDefaultDisplay().getMetrics(metrics);
float density = metrics.density;
- int rotation = getRotation(mContext);
+ int rotation = RotationUtils.getRotation(mContext);
inflateView(rotation);
int bgColor = mContext.getColor(
@@ -199,19 +199,6 @@
mContext.registerReceiver(mReceiver, filter);
}
- private int getRotation(Context context) {
- Configuration config = mContext.getResources().getConfiguration();
- int rot = context.getDisplay().getRotation();
- if (config.smallestScreenWidthDp < 600) {
- if (rot == Surface.ROTATION_90) {
- return ROTATION_LANDSCAPE;
- } else if (rot == Surface.ROTATION_270) {
- return ROTATION_SEASCAPE;
- }
- }
- return ROTATION_NONE;
- }
-
private void inflateView(int rotation) {
// We only want this landscape orientation on <600dp, so rather than handle
// resource overlay for -land and -sw600dp-land, just inflate this
@@ -284,14 +271,14 @@
protected void onConfigurationChanged() {
removeAllViews();
- inflateView(getRotation(mContext));
+ inflateView(RotationUtils.getRotation(mContext));
}
private final Runnable mUpdateLayoutRunnable = new Runnable() {
@Override
public void run() {
if (mLayout != null && mLayout.getParent() != null) {
- mLayout.setLayoutParams(getRequestLayoutParams(getRotation(mContext)));
+ mLayout.setLayoutParams(getRequestLayoutParams(RotationUtils.getRotation(mContext)));
}
}
};
diff --git a/packages/SystemUI/src/com/android/systemui/recents/views/RecentsTransitionHelper.java b/packages/SystemUI/src/com/android/systemui/recents/views/RecentsTransitionHelper.java
index 21dfe8c..968b77f 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/views/RecentsTransitionHelper.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/views/RecentsTransitionHelper.java
@@ -400,8 +400,8 @@
view.draw(c);
}
node.end(c);
- return ThreadedRenderer.createHardwareBitmap(node, bufferWidth, bufferHeight)
- .createGraphicBufferHandle();
+ Bitmap hwBitmap = ThreadedRenderer.createHardwareBitmap(node, bufferWidth, bufferHeight);
+ return hwBitmap.createGraphicBufferHandle();
}
/**
diff --git a/packages/SystemUI/src/com/android/systemui/recents/views/RecentsView.java b/packages/SystemUI/src/com/android/systemui/recents/views/RecentsView.java
index 9ca756c..c1c41be0 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/views/RecentsView.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/views/RecentsView.java
@@ -151,6 +151,12 @@
mColorExtractor = Dependency.get(SysuiColorExtractor.class);
LayoutInflater inflater = LayoutInflater.from(context);
+
+ mEmptyView = (TextView) inflater.inflate(R.layout.recents_empty, this, false);
+ addView(mEmptyView);
+
+ boolean usingDarkText =
+ Color.luminance(mEmptyView.getTextColors().getDefaultColor()) < 0.5f;
if (RecentsDebugFlags.Static.EnableStackActionButton) {
mStackActionButton = (TextView) inflater.inflate(R.layout.recents_stack_action_button,
this, false);
@@ -160,10 +166,21 @@
EventBus.getDefault().send(new DismissAllTaskViewsEvent());
}
});
+ // Disable black shadow if text color is already dark.
+ if (usingDarkText) {
+ mStackActionButton.setShadowLayer(0, 0, 0, 0);
+ }
addView(mStackActionButton);
}
- mEmptyView = (TextView) inflater.inflate(R.layout.recents_empty, this, false);
- addView(mEmptyView);
+
+ // Let's also require dark status and nav bars if the text is dark
+ int systemBarsStyle = usingDarkText ? View.SYSTEM_UI_FLAG_LIGHT_NAVIGATION_BAR |
+ View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR : 0;
+
+ setSystemUiVisibility(View.SYSTEM_UI_FLAG_LAYOUT_STABLE |
+ View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN |
+ View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION |
+ systemBarsStyle);
}
/**
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/ImageTransformState.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/ImageTransformState.java
index c891418..92f26d6 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/ImageTransformState.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/ImageTransformState.java
@@ -116,7 +116,7 @@
}
@Override
- protected boolean transformScale() {
+ protected boolean transformScale(TransformState otherState) {
return true;
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/TextViewTransformState.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/TextViewTransformState.java
index fb4e2ec..c4aabe4 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/TextViewTransformState.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/TextViewTransformState.java
@@ -17,6 +17,7 @@
package com.android.systemui.statusbar.notification;
import android.text.Layout;
+import android.text.Spanned;
import android.text.TextUtils;
import android.util.Pools;
import android.view.View;
@@ -50,12 +51,69 @@
int ownEllipsized = getEllipsisCount();
int otherEllipsized = otherTvs.getEllipsisCount();
return ownEllipsized == otherEllipsized
- && getInnerHeight(mText) == getInnerHeight(otherTvs.mText);
+ && mText.getLineCount() == otherTvs.mText.getLineCount()
+ && hasSameSpans(otherTvs);
}
}
return false;
}
+ private boolean hasSameSpans(TextViewTransformState otherTvs) {
+ boolean hasSpans = mText instanceof Spanned;
+ boolean otherHasSpans = otherTvs.mText instanceof Spanned;
+ if (hasSpans != otherHasSpans) {
+ return false;
+ } else if (!hasSpans) {
+ return true;
+ }
+ // Actually both have spans, let's try to compare them
+ Spanned ownSpanned = (Spanned) mText;
+ Object[] spans = ownSpanned.getSpans(0, ownSpanned.length(), Object.class);
+ Spanned otherSpanned = (Spanned) otherTvs.mText;
+ Object[] otherSpans = otherSpanned.getSpans(0, otherSpanned.length(), Object.class);
+ if (spans.length != otherSpans.length) {
+ return false;
+ }
+ for (int i = 0; i < spans.length; i++) {
+ Object span = spans[i];
+ Object otherSpan = otherSpans[i];
+ if (!span.getClass().equals(otherSpan.getClass())) {
+ return false;
+ }
+ if (ownSpanned.getSpanStart(span) != otherSpanned.getSpanStart(otherSpan)
+ || ownSpanned.getSpanEnd(span) != otherSpanned.getSpanEnd(otherSpan)) {
+ return false;
+ }
+ }
+ return true;
+ }
+
+ @Override
+ protected boolean transformScale(TransformState otherState) {
+ if (!(otherState instanceof TextViewTransformState)) {
+ return false;
+ }
+ TextViewTransformState otherTvs = (TextViewTransformState) otherState;
+ int lineCount = mText.getLineCount();
+ return lineCount == 1 && lineCount == otherTvs.mText.getLineCount()
+ && getEllipsisCount() == otherTvs.getEllipsisCount()
+ && getViewHeight() != otherTvs.getViewHeight();
+ }
+
+ @Override
+ protected int getViewWidth() {
+ Layout l = mText.getLayout();
+ if (l != null) {
+ return (int) l.getLineWidth(0);
+ }
+ return super.getViewWidth();
+ }
+
+ @Override
+ protected int getViewHeight() {
+ return mText.getLineHeight();
+ }
+
private int getInnerHeight(TextView text) {
return text.getHeight() - text.getPaddingTop() - text.getPaddingBottom();
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/TransformState.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/TransformState.java
index a77dd4e..bafedff 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/TransformState.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/TransformState.java
@@ -108,7 +108,7 @@
final View transformedView = mTransformedView;
boolean transformX = (transformationFlags & TRANSFORM_X) != 0;
boolean transformY = (transformationFlags & TRANSFORM_Y) != 0;
- boolean transformScale = transformScale();
+ boolean transformScale = transformScale(otherState);
// lets animate the positions correctly
if (transformationAmount == 0.0f
|| transformX && getTransformationStartX() == UNDEFINED
@@ -132,16 +132,16 @@
}
// we also want to animate the scale if we're the same
View otherView = otherState.getTransformedView();
- if (transformScale && otherView.getWidth() != transformedView.getWidth()) {
- setTransformationStartScaleX(otherView.getWidth() * otherView.getScaleX()
- / (float) transformedView.getWidth());
+ if (transformScale && otherState.getViewWidth() != getViewWidth()) {
+ setTransformationStartScaleX(otherState.getViewWidth() * otherView.getScaleX()
+ / (float) getViewWidth());
transformedView.setPivotX(0);
} else {
setTransformationStartScaleX(UNDEFINED);
}
- if (transformScale && otherView.getHeight() != transformedView.getHeight()) {
- setTransformationStartScaleY(otherView.getHeight() * otherView.getScaleY()
- / (float) transformedView.getHeight());
+ if (transformScale && otherState.getViewHeight() != getViewHeight()) {
+ setTransformationStartScaleY(otherState.getViewHeight() * otherView.getScaleY()
+ / (float) getViewHeight());
transformedView.setPivotY(0);
} else {
setTransformationStartScaleY(UNDEFINED);
@@ -205,7 +205,15 @@
}
}
- protected boolean transformScale() {
+ protected int getViewWidth() {
+ return mTransformedView.getWidth();
+ }
+
+ protected int getViewHeight() {
+ return mTransformedView.getHeight();
+ }
+
+ protected boolean transformScale(TransformState otherState) {
return false;
}
@@ -259,7 +267,7 @@
final View transformedView = mTransformedView;
boolean transformX = (transformationFlags & TRANSFORM_X) != 0;
boolean transformY = (transformationFlags & TRANSFORM_Y) != 0;
- boolean transformScale = transformScale();
+ boolean transformScale = transformScale(otherState);
// lets animate the positions correctly
if (transformationAmount == 0.0f) {
if (transformX) {
@@ -275,13 +283,13 @@
setTransformationStartY(start);
}
View otherView = otherState.getTransformedView();
- if (transformScale && otherView.getWidth() != transformedView.getWidth()) {
+ if (transformScale && otherState.getViewWidth() != getViewWidth()) {
setTransformationStartScaleX(transformedView.getScaleX());
transformedView.setPivotX(0);
} else {
setTransformationStartScaleX(UNDEFINED);
}
- if (transformScale && otherView.getHeight() != transformedView.getHeight()) {
+ if (transformScale && otherState.getViewHeight() != getViewHeight()) {
setTransformationStartScaleY(transformedView.getScaleY());
transformedView.setPivotY(0);
} else {
@@ -333,14 +341,14 @@
if (transformationStartScaleX != UNDEFINED) {
transformedView.setScaleX(
NotificationUtils.interpolate(transformationStartScaleX,
- (otherView.getWidth() / (float) transformedView.getWidth()),
+ (otherState.getViewWidth() / (float) getViewWidth()),
interpolatedValue));
}
float transformationStartScaleY = getTransformationStartScaleY();
if (transformationStartScaleY != UNDEFINED) {
transformedView.setScaleY(
NotificationUtils.interpolate(transformationStartScaleY,
- (otherView.getHeight() / (float) transformedView.getHeight()),
+ (otherState.getViewHeight() / (float) getViewHeight()),
interpolatedValue));
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/AutoTileManager.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/AutoTileManager.java
index 7512efa..1bd90fa 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/AutoTileManager.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/AutoTileManager.java
@@ -24,6 +24,7 @@
import com.android.systemui.Dependency;
import com.android.systemui.Prefs;
import com.android.systemui.Prefs.Key;
+import com.android.systemui.qs.AutoAddTracker;
import com.android.systemui.qs.QSTileHost;
import com.android.systemui.qs.SecureSetting;
import com.android.systemui.statusbar.policy.DataSaverController;
@@ -36,39 +37,47 @@
*/
public class AutoTileManager {
+ public static final String HOTSPOT = "hotspot";
+ public static final String SAVER = "saver";
+ public static final String INVERSION = "inversion";
+ public static final String WORK = "work";
+ public static final String NIGHT = "night";
private final Context mContext;
private final QSTileHost mHost;
private final Handler mHandler;
+ private final AutoAddTracker mAutoTracker;
public AutoTileManager(Context context, QSTileHost host) {
+ mAutoTracker = new AutoAddTracker(context);
mContext = context;
mHost = host;
mHandler = new Handler((Looper) Dependency.get(Dependency.BG_LOOPER));
- if (!Prefs.getBoolean(context, Key.QS_HOTSPOT_ADDED, false)) {
+ if (!mAutoTracker.isAdded(HOTSPOT)) {
Dependency.get(HotspotController.class).addCallback(mHotspotCallback);
}
- if (!Prefs.getBoolean(context, Key.QS_DATA_SAVER_ADDED, false)) {
+ if (!mAutoTracker.isAdded(SAVER)) {
Dependency.get(DataSaverController.class).addCallback(mDataSaverListener);
}
- if (!Prefs.getBoolean(context, Key.QS_INVERT_COLORS_ADDED, false)) {
+ if (!mAutoTracker.isAdded(INVERSION)) {
mColorsSetting = new SecureSetting(mContext, mHandler,
Secure.ACCESSIBILITY_DISPLAY_INVERSION_ENABLED) {
@Override
protected void handleValueChanged(int value, boolean observedChange) {
+ if (mAutoTracker.isAdded(INVERSION)) return;
if (value != 0) {
- mHost.addTile("inversion");
- Prefs.putBoolean(mContext, Key.QS_INVERT_COLORS_ADDED, true);
+ mHost.addTile(INVERSION);
+ mAutoTracker.setTileAdded(INVERSION);
mHandler.post(() -> mColorsSetting.setListening(false));
}
}
};
mColorsSetting.setListening(true);
}
- if (!Prefs.getBoolean(context, Key.QS_WORK_ADDED, false)) {
+ if (!mAutoTracker.isAdded(WORK)) {
Dependency.get(ManagedProfileController.class).addCallback(mProfileCallback);
}
- if (!Prefs.getBoolean(context, Key.QS_NIGHTDISPLAY_ADDED, false)
+ if (!mAutoTracker.isAdded(NIGHT)
&& NightDisplayController.isAvailable(mContext)) {
Dependency.get(NightDisplayController.class).setListener(mNightDisplayCallback);
}
@@ -76,6 +85,7 @@
public void destroy() {
mColorsSetting.setListening(false);
+ mAutoTracker.destroy();
Dependency.get(HotspotController.class).removeCallback(mHotspotCallback);
Dependency.get(DataSaverController.class).removeCallback(mDataSaverListener);
Dependency.get(ManagedProfileController.class).removeCallback(mProfileCallback);
@@ -86,9 +96,10 @@
new ManagedProfileController.Callback() {
@Override
public void onManagedProfileChanged() {
+ if (mAutoTracker.isAdded(WORK)) return;
if (Dependency.get(ManagedProfileController.class).hasActiveProfile()) {
- mHost.addTile("work");
- Prefs.putBoolean(mContext, Key.QS_WORK_ADDED, true);
+ mHost.addTile(WORK);
+ mAutoTracker.setTileAdded(WORK);
mHandler.post(() -> Dependency.get(ManagedProfileController.class)
.removeCallback(mProfileCallback));
}
@@ -104,9 +115,10 @@
private final DataSaverController.Listener mDataSaverListener = new Listener() {
@Override
public void onDataSaverChanged(boolean isDataSaving) {
+ if (mAutoTracker.isAdded(SAVER)) return;
if (isDataSaving) {
- mHost.addTile("saver");
- Prefs.putBoolean(mContext, Key.QS_DATA_SAVER_ADDED, true);
+ mHost.addTile(SAVER);
+ mAutoTracker.setTileAdded(SAVER);
mHandler.post(() -> Dependency.get(DataSaverController.class).removeCallback(
mDataSaverListener));
}
@@ -116,9 +128,10 @@
private final HotspotController.Callback mHotspotCallback = new Callback() {
@Override
public void onHotspotChanged(boolean enabled) {
+ if (mAutoTracker.isAdded(HOTSPOT)) return;
if (enabled) {
- mHost.addTile("hotspot");
- Prefs.putBoolean(mContext, Key.QS_HOTSPOT_ADDED, true);
+ mHost.addTile(HOTSPOT);
+ mAutoTracker.setTileAdded(HOTSPOT);
mHandler.post(() -> Dependency.get(HotspotController.class)
.removeCallback(mHotspotCallback));
}
@@ -144,8 +157,9 @@
}
private void addNightTile() {
- mHost.addTile("night");
- Prefs.putBoolean(mContext, Key.QS_NIGHTDISPLAY_ADDED, true);
+ if (mAutoTracker.isAdded(NIGHT)) return;
+ mHost.addTile(NIGHT);
+ mAutoTracker.setTileAdded(NIGHT);
mHandler.post(() -> Dependency.get(NightDisplayController.class)
.setListener(null));
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardAffordanceHelper.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardAffordanceHelper.java
index 674a61c..df1ffda 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardAffordanceHelper.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardAffordanceHelper.java
@@ -168,8 +168,7 @@
distance = mTranslationOnDown + distance;
distance = Math.max(0, distance);
}
- setTranslation(distance, false /* isReset */, false /* animateReset */,
- false /* force */);
+ setTranslation(distance, false /* isReset */, false /* animateReset */);
}
break;
@@ -374,12 +373,11 @@
targetView.finishAnimation(velocity, mAnimationEndRunnable);
}
- private void setTranslation(float translation, boolean isReset, boolean animateReset,
- boolean force) {
+ private void setTranslation(float translation, boolean isReset, boolean animateReset) {
translation = rightSwipePossible() ? translation : Math.max(0, translation);
translation = leftSwipePossible() ? translation : Math.min(0, translation);
float absTranslation = Math.abs(translation);
- if (translation != mTranslation || isReset || force) {
+ if (translation != mTranslation || isReset) {
KeyguardAffordanceView targetView = translation > 0 ? mLeftIcon : mRightIcon;
KeyguardAffordanceView otherView = translation > 0 ? mRightIcon : mLeftIcon;
float alpha = absTranslation / getMinTranslationAmount();
@@ -394,15 +392,15 @@
boolean slowAnimation = isReset && isBelowFalsingThreshold();
if (!isReset) {
updateIcon(targetView, radius, alpha + fadeOutAlpha * targetView.getRestingAlpha(),
- false, false, force, false);
+ false, false, false, false);
} else {
updateIcon(targetView, 0.0f, fadeOutAlpha * targetView.getRestingAlpha(),
- animateIcons, slowAnimation, force, forceNoCircleAnimation);
+ animateIcons, slowAnimation, true /* isReset */, forceNoCircleAnimation);
}
updateIcon(otherView, 0.0f, fadeOutAlpha * otherView.getRestingAlpha(),
- animateIcons, slowAnimation, force, forceNoCircleAnimation);
+ animateIcons, slowAnimation, isReset, forceNoCircleAnimation);
updateIcon(mCenterIcon, 0.0f, fadeOutAlpha * mCenterIcon.getRestingAlpha(),
- animateIcons, slowAnimation, force, forceNoCircleAnimation);
+ animateIcons, slowAnimation, isReset, forceNoCircleAnimation);
mTranslation = translation;
}
@@ -510,12 +508,8 @@
}
public void reset(boolean animate) {
- reset(animate, false /* force */);
- }
-
- public void reset(boolean animate, boolean force) {
cancelAnimation();
- setTranslation(0.0f, true, animate, force);
+ setTranslation(0.0f, true /* isReset */, animate);
mMotionCancelled = true;
if (mSwipingInProgress) {
mCallback.onSwipingAborted();
@@ -523,10 +517,6 @@
}
}
- public void resetImmediately() {
- reset(false /* animate */, true /* force */);
- }
-
public boolean isSwipingInProgress() {
return mSwipingInProgress;
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBottomAreaView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBottomAreaView.java
index a4dfcd8..e9aa6d2 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBottomAreaView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBottomAreaView.java
@@ -254,6 +254,7 @@
mFlashlightController = Dependency.get(FlashlightController.class);
mAccessibilityController = Dependency.get(AccessibilityController.class);
mAssistManager = Dependency.get(AssistManager.class);
+ mLockIcon.setAccessibilityController(mAccessibilityController);
updateLeftAffordance();
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/MultiUserSwitch.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/MultiUserSwitch.java
index c30bb9a..f393dcd 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/MultiUserSwitch.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/MultiUserSwitch.java
@@ -30,6 +30,8 @@
import android.widget.FrameLayout;
import com.android.systemui.Dependency;
+import com.android.systemui.Prefs;
+import com.android.systemui.Prefs.Key;
import com.android.systemui.R;
import com.android.systemui.plugins.ActivityStarter;
import com.android.systemui.plugins.qs.DetailAdapter;
@@ -74,7 +76,8 @@
if (mUserListener == null) {
return false;
}
- return mUserListener.getUserCount() != 0;
+ return mUserListener.getUserCount() != 0
+ && Prefs.getBoolean(getContext(), Key.SEEN_MULTI_USER, false);
}
public void setUserSwitcherController(UserSwitcherController userSwitcherController) {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarInflaterView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarInflaterView.java
index 09ae521..6f2c6e0 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarInflaterView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarInflaterView.java
@@ -131,9 +131,6 @@
mRot90.setId(R.id.rot90);
addView(mRot90);
updateAlternativeOrder();
- if (getParent() instanceof NavigationBarView) {
- ((NavigationBarView) getParent()).updateRotatedViews();
- }
}
protected String getDefaultLayout() {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarView.java
index 4264441..03dd41f 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarView.java
@@ -558,7 +558,6 @@
public void onFinishInflate() {
mNavigationInflaterView = (NavigationBarInflaterView) findViewById(
R.id.navigation_inflater);
- updateRotatedViews();
mNavigationInflaterView.setButtonDispatchers(mButtonDispatchers);
getImeSwitchButton().setOnClickListener(mImeSwitcherClickListener);
@@ -567,16 +566,14 @@
mDockedStackExists = exists;
updateRecentsIcon();
}));
+ updateRotatedViews();
}
- void updateRotatedViews() {
+ private void updateRotatedViews() {
mRotatedViews[Surface.ROTATION_0] =
mRotatedViews[Surface.ROTATION_180] = findViewById(R.id.rot0);
mRotatedViews[Surface.ROTATION_270] =
mRotatedViews[Surface.ROTATION_90] = findViewById(R.id.rot90);
-
- mCurrentRotation = -1;
- reorient();
}
public boolean needsReorient(int rotation) {
@@ -615,9 +612,9 @@
}
mDeadZone = (DeadZone) mCurrentView.findViewById(R.id.deadzone);
- if (getRootView() instanceof NavigationBarFrame) {
- ((NavigationBarFrame) getRootView()).setDeadZone(mDeadZone);
- }
+
+ ((NavigationBarFrame) getRootView()).setDeadZone(mDeadZone);
+
mDeadZone.setDisplayRotation(mCurrentRotation);
// force the low profile & disabled states into compliance
@@ -757,6 +754,7 @@
@Override
protected void onAttachedToWindow() {
super.onAttachedToWindow();
+ reorient();
onPluginDisconnected(null); // Create default gesture helper
Dependency.get(PluginManager.class).addPluginListener(this,
NavGesture.class, false /* Only one */);
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java
index a773172..b8ac6b9 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java
@@ -345,6 +345,7 @@
false);
addView(mKeyguardBottomArea, index);
initBottomArea();
+ setDarkAmount(mDarkAmount);
}
private void initBottomArea() {
@@ -2560,7 +2561,7 @@
public void setTouchDisabled(boolean disabled) {
super.setTouchDisabled(disabled);
if (disabled && mAffordanceHelper.isSwipingInProgress() && !mIsLaunchTransitionRunning) {
- mAffordanceHelper.resetImmediately();
+ mAffordanceHelper.reset(false /* animate */);
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java
index 04bf10e..63b405d 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java
@@ -1319,6 +1319,9 @@
.setStatusBarKeyguardViewManager(mStatusBarKeyguardViewManager);
mKeyguardIndicationController.setVisible(mState == StatusBarState.KEYGUARD);
mKeyguardIndicationController.setDozing(mDozing);
+ if (mBrightnessMirrorController != null) {
+ mBrightnessMirrorController.onOverlayChanged();
+ }
}
protected void reevaluateStyles() {
@@ -3497,6 +3500,11 @@
pw.print (" ");
mNotificationPanel.dump(fd, pw, args);
}
+ pw.println(" mStackScroller: ");
+ if (mStackScroller != null) {
+ pw.print (" ");
+ mStackScroller.dump(fd, pw, args);
+ }
DozeLog.dump(pw);
@@ -3762,7 +3770,7 @@
// SystemUIService notifies SystemBars of configuration changes, which then calls down here
@Override
- protected void onConfigurationChanged(Configuration newConfig) {
+ public void onConfigChanged(Configuration newConfig) {
updateResources();
updateDisplaySize(); // populates mDisplayMetrics
@@ -4212,7 +4220,7 @@
}
if (shouldBeKeyguard) {
showKeyguardImpl();
- } else if (!shouldBeKeyguard && mIsKeyguard) {
+ } else {
return hideKeyguardImpl();
}
return false;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java
index 9b0307d..2833ff1 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java
@@ -152,7 +152,7 @@
* {@link KeyguardBouncer#needsFullscreenBouncer()}.
*/
protected void showBouncerOrKeyguard(boolean hideBouncerWhenShowing) {
- if (mBouncer.needsFullscreenBouncer()) {
+ if (mBouncer.needsFullscreenBouncer() && !mDozing) {
// The keyguard might be showing (already). So we need to hide it.
mStatusBar.hideKeyguard();
@@ -258,8 +258,11 @@
}
public void setDozing(boolean dozing) {
- mDozing = dozing;
- updateStates();
+ if (mDozing != dozing) {
+ mDozing = dozing;
+ reset(dozing /* hideBouncerWhenShowing */);
+ updateStates();
+ }
}
public void onScreenTurnedOff() {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowManager.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowManager.java
index e78a113..0566361 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowManager.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowManager.java
@@ -137,7 +137,7 @@
}
private void adjustScreenOrientation(State state) {
- if (state.isKeyguardShowingAndNotOccluded()) {
+ if (state.isKeyguardShowingAndNotOccluded() || state.dozing) {
if (mKeyguardScreenRotation) {
mLpChanged.screenOrientation = ActivityInfo.SCREEN_ORIENTATION_USER;
} else {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/BrightnessMirrorController.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/BrightnessMirrorController.java
index ad406c7..ab55b23 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/BrightnessMirrorController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/BrightnessMirrorController.java
@@ -84,7 +84,6 @@
.setInterpolator(Interpolators.ALPHA_IN);
}
-
public void setLocation(View original) {
original.getLocationInWindow(mInt2Cache);
@@ -115,7 +114,15 @@
mBrightnessMirror.setLayoutParams(lp);
}
+ public void onOverlayChanged() {
+ reinflate();
+ }
+
public void onDensityOrFontScaleChanged() {
+ reinflate();
+ }
+
+ private void reinflate() {
int index = mStatusBarWindow.indexOfChild(mBrightnessMirror);
mStatusBarWindow.removeView(mBrightnessMirror);
mBrightnessMirror = LayoutInflater.from(mBrightnessMirror.getContext()).inflate(
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 e0f4429..700c01a 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/UserSwitcherController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/UserSwitcherController.java
@@ -57,6 +57,8 @@
import com.android.settingslib.Utils;
import com.android.systemui.Dependency;
import com.android.systemui.GuestResumeSessionReceiver;
+import com.android.systemui.Prefs;
+import com.android.systemui.Prefs.Key;
import com.android.systemui.R;
import com.android.systemui.SystemUI;
import com.android.systemui.SystemUISecondaryUserService;
@@ -235,6 +237,9 @@
}
}
}
+ if (records.size() > 1 || guestRecord != null) {
+ Prefs.putBoolean(mContext, Key.SEEN_MULTI_USER, true);
+ }
boolean systemCanCreateUsers = !mUserManager.hasBaseUserRestriction(
UserManager.DISALLOW_ADD_USER, UserHandle.SYSTEM);
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/stack/NotificationStackScrollLayout.java b/packages/SystemUI/src/com/android/systemui/statusbar/stack/NotificationStackScrollLayout.java
index 41cde9c..74523e2 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/stack/NotificationStackScrollLayout.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/stack/NotificationStackScrollLayout.java
@@ -91,6 +91,8 @@
import android.support.v4.graphics.ColorUtils;
+import java.io.FileDescriptor;
+import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
@@ -2587,9 +2589,6 @@
}
updateAnimationState(false, child);
- // Make sure the clipRect we might have set is removed
- expandableView.setClipTopAmount(0);
-
focusNextViewIfFocused(child);
}
@@ -3036,10 +3035,6 @@
private void generateChildRemovalEvents() {
for (View child : mChildrenToRemoveAnimated) {
boolean childWasSwipedOut = mSwipedOutViews.contains(child);
- int animationType = childWasSwipedOut
- ? AnimationEvent.ANIMATION_TYPE_REMOVE_SWIPED_OUT
- : AnimationEvent.ANIMATION_TYPE_REMOVE;
- AnimationEvent event = new AnimationEvent(child, animationType);
// we need to know the view after this one
float removedTranslation = child.getTranslationY();
@@ -3050,7 +3045,16 @@
removedTranslation = row.getTranslationWhenRemoved();
ignoreChildren = false;
}
+ childWasSwipedOut |= Math.abs(row.getTranslation()) == row.getWidth();
}
+ if (!childWasSwipedOut) {
+ Rect clipBounds = child.getClipBounds();
+ childWasSwipedOut = clipBounds.height() == 0;
+ }
+ int animationType = childWasSwipedOut
+ ? AnimationEvent.ANIMATION_TYPE_REMOVE_SWIPED_OUT
+ : AnimationEvent.ANIMATION_TYPE_REMOVE;
+ AnimationEvent event = new AnimationEvent(child, animationType);
event.viewAfterChangingView = getFirstChildBelowTranlsationY(removedTranslation,
ignoreChildren);
mAnimationEvents.add(event);
@@ -3358,15 +3362,29 @@
if (!mIsExpanded) {
setOwnScrollY(0);
mStatusBar.resetUserExpandedStates();
+ clearTemporaryViews();
+ clearUserLockedViews();
+ }
+ }
- // lets make sure nothing is in the overlay / transient anymore
- clearTemporaryViews(this);
- for (int i = 0; i < getChildCount(); i++) {
- ExpandableView child = (ExpandableView) getChildAt(i);
- if (child instanceof ExpandableNotificationRow) {
- ExpandableNotificationRow row = (ExpandableNotificationRow) child;
- clearTemporaryViews(row.getChildrenContainer());
- }
+ private void clearUserLockedViews() {
+ for (int i = 0; i < getChildCount(); i++) {
+ ExpandableView child = (ExpandableView) getChildAt(i);
+ if (child instanceof ExpandableNotificationRow) {
+ ExpandableNotificationRow row = (ExpandableNotificationRow) child;
+ row.setUserLocked(false);
+ }
+ }
+ }
+
+ private void clearTemporaryViews() {
+ // lets make sure nothing is in the overlay / transient anymore
+ clearTemporaryViews(this);
+ for (int i = 0; i < getChildCount(); i++) {
+ ExpandableView child = (ExpandableView) getChildAt(i);
+ if (child instanceof ExpandableNotificationRow) {
+ ExpandableNotificationRow row = (ExpandableNotificationRow) child;
+ clearTemporaryViews(row.getChildrenContainer());
}
}
}
@@ -3401,6 +3419,7 @@
if (changed) {
if (!mIsExpanded) {
mGroupManager.collapseAllGroups();
+ mExpandHelper.cancelImmediately();
}
updateNotificationAnimationStates();
updateChronometers();
@@ -4257,6 +4276,19 @@
mShelf.setDarkOffsetX(shelfOffsetX);
}
+ public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
+ pw.println(String.format("[%s: pulsing=%s qsCustomizerShowing=%s visibility=%s"
+ + " alpha:%f scrollY:%d]",
+ this.getClass().getSimpleName(),
+ mPulsing != null ?"T":"f",
+ mAmbientState.isQsCustomizerShowing() ? "T":"f",
+ getVisibility() == View.VISIBLE ? "visible"
+ : getVisibility() == View.GONE ? "gone"
+ : "invisible",
+ getAlpha(),
+ mAmbientState.getScrollY()));
+ }
+
/**
* A listener that is notified when some child locations might have changed.
*/
diff --git a/packages/SystemUI/src/com/android/systemui/util/AlarmTimeout.java b/packages/SystemUI/src/com/android/systemui/util/AlarmTimeout.java
new file mode 100644
index 0000000..f7f61af
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/util/AlarmTimeout.java
@@ -0,0 +1,93 @@
+/*
+ * 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.util;
+
+import android.app.AlarmManager;
+import android.os.Handler;
+import android.os.SystemClock;
+
+/**
+ * Schedules a timeout through AlarmManager. Ensures that the timeout is called even when
+ * the device is asleep.
+ */
+public class AlarmTimeout implements AlarmManager.OnAlarmListener {
+
+ public static final int MODE_CRASH_IF_SCHEDULED = 0;
+ public static final int MODE_IGNORE_IF_SCHEDULED = 1;
+ public static final int MODE_RESCHEDULE_IF_SCHEDULED = 2;
+
+ private final AlarmManager mAlarmManager;
+ private final AlarmManager.OnAlarmListener mListener;
+ private final String mTag;
+ private final Handler mHandler;
+ private boolean mScheduled;
+
+ public AlarmTimeout(AlarmManager alarmManager, AlarmManager.OnAlarmListener listener,
+ String tag, Handler handler) {
+ mAlarmManager = alarmManager;
+ mListener = listener;
+ mTag = tag;
+ mHandler = handler;
+ }
+
+ public void schedule(long timeout, int mode) {
+ switch (mode) {
+ case MODE_CRASH_IF_SCHEDULED:
+ if (mScheduled) {
+ throw new IllegalStateException(mTag + " timeout is already scheduled");
+ }
+ break;
+ case MODE_IGNORE_IF_SCHEDULED:
+ if (mScheduled) {
+ return;
+ }
+ break;
+ case MODE_RESCHEDULE_IF_SCHEDULED:
+ if (mScheduled) {
+ cancel();
+ }
+ break;
+ default:
+ throw new IllegalArgumentException("Illegal mode: " + mode);
+ }
+
+ mAlarmManager.setExact(AlarmManager.ELAPSED_REALTIME_WAKEUP,
+ SystemClock.elapsedRealtime() + timeout, mTag, this, mHandler);
+ mScheduled = true;
+ }
+
+ public boolean isScheduled() {
+ return mScheduled;
+ }
+
+ public void cancel() {
+ if (mScheduled) {
+ mAlarmManager.cancel(this);
+ mScheduled = false;
+ }
+ }
+
+ @Override
+ public void onAlarm() {
+ if (!mScheduled) {
+ // We canceled the alarm, but it still fired. Ignore.
+ return;
+ }
+ mScheduled = false;
+ mListener.onAlarm();
+ }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/util/leak/RotationUtils.java b/packages/SystemUI/src/com/android/systemui/util/leak/RotationUtils.java
new file mode 100644
index 0000000..ad20900
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/util/leak/RotationUtils.java
@@ -0,0 +1,39 @@
+/*
+ * 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.util.leak;
+
+import android.content.Context;
+import android.content.res.Configuration;
+import android.view.Surface;
+
+public class RotationUtils {
+
+ public static final int ROTATION_NONE = 0;
+ public static final int ROTATION_LANDSCAPE = 1;
+ public static final int ROTATION_SEASCAPE = 2;
+
+ public static int getRotation(Context context) {
+ Configuration config = context.getResources().getConfiguration();
+ int rot = context.getDisplay().getRotation();
+ if (config.smallestScreenWidthDp < 600) {
+ if (rot == Surface.ROTATION_90) {
+ return ROTATION_LANDSCAPE;
+ } else if (rot == Surface.ROTATION_270) {
+ return ROTATION_SEASCAPE;
+ }
+ }
+ return ROTATION_NONE;
+ }
+}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/doze/DozeMachineTest.java b/packages/SystemUI/tests/src/com/android/systemui/doze/DozeMachineTest.java
index 3a09ce0..368c814f 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/doze/DozeMachineTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/doze/DozeMachineTest.java
@@ -215,54 +215,6 @@
}
@Test
- public void testScreen_offInDoze() {
- mMachine.requestState(INITIALIZED);
-
- mMachine.requestState(DOZE);
-
- assertEquals(Display.STATE_OFF, mServiceFake.screenState);
- }
-
- @Test
- public void testScreen_onInAod() {
- mMachine.requestState(INITIALIZED);
-
- mMachine.requestState(DOZE_AOD);
-
- assertEquals(Display.STATE_DOZE_SUSPEND, mServiceFake.screenState);
- }
-
- @Test
- public void testScreen_onInPulse() {
- mMachine.requestState(INITIALIZED);
-
- mMachine.requestPulse(DozeLog.PULSE_REASON_NOTIFICATION);
- mMachine.requestState(DOZE_PULSING);
-
- assertEquals(Display.STATE_ON, mServiceFake.screenState);
- }
-
- @Test
- public void testScreen_offInRequestPulseWithoutAoD() {
- mMachine.requestState(INITIALIZED);
-
- mMachine.requestState(DOZE);
- mMachine.requestPulse(DozeLog.PULSE_REASON_NOTIFICATION);
-
- assertEquals(Display.STATE_OFF, mServiceFake.screenState);
- }
-
- @Test
- public void testScreen_onInRequestPulseWithoutAoD() {
- mMachine.requestState(INITIALIZED);
-
- mMachine.requestState(DOZE_AOD);
- mMachine.requestPulse(DozeLog.PULSE_REASON_NOTIFICATION);
-
- assertEquals(Display.STATE_DOZE_SUSPEND, mServiceFake.screenState);
- }
-
- @Test
public void testTransitions_canRequestTransitions() {
mMachine.requestState(INITIALIZED);
mMachine.requestState(DOZE);
diff --git a/packages/SystemUI/tests/src/com/android/systemui/doze/DozeScreenBrightnessTest.java b/packages/SystemUI/tests/src/com/android/systemui/doze/DozeScreenBrightnessTest.java
new file mode 100644
index 0000000..514dc8b
--- /dev/null
+++ b/packages/SystemUI/tests/src/com/android/systemui/doze/DozeScreenBrightnessTest.java
@@ -0,0 +1,162 @@
+/*
+ * 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.doze;
+
+import static com.android.systemui.doze.DozeMachine.State.DOZE;
+import static com.android.systemui.doze.DozeMachine.State.DOZE_AOD;
+import static com.android.systemui.doze.DozeMachine.State.DOZE_AOD_PAUSED;
+import static com.android.systemui.doze.DozeMachine.State.DOZE_PULSE_DONE;
+import static com.android.systemui.doze.DozeMachine.State.DOZE_PULSING;
+import static com.android.systemui.doze.DozeMachine.State.DOZE_REQUEST_PULSE;
+import static com.android.systemui.doze.DozeMachine.State.FINISH;
+import static com.android.systemui.doze.DozeMachine.State.INITIALIZED;
+import static com.android.systemui.doze.DozeMachine.State.UNINITIALIZED;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotEquals;
+import static org.junit.Assert.assertTrue;
+
+import android.os.PowerManager;
+import android.support.test.filters.SmallTest;
+import android.support.test.runner.AndroidJUnit4;
+
+import com.android.systemui.SysuiTestCase;
+import com.android.systemui.utils.hardware.FakeSensorManager;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+@RunWith(AndroidJUnit4.class)
+@SmallTest
+public class DozeScreenBrightnessTest extends SysuiTestCase {
+
+ DozeServiceFake mServiceFake;
+ DozeScreenBrightness mScreen;
+ FakeSensorManager.FakeGenericSensor mSensor;
+ FakeSensorManager mSensorManager;
+
+ @Before
+ public void setUp() throws Exception {
+ mServiceFake = new DozeServiceFake();
+ mSensorManager = new FakeSensorManager(mContext);
+ mSensor = mSensorManager.getFakeLightSensor();
+ mScreen = new DozeScreenBrightness(mContext, mServiceFake, mSensorManager,
+ mSensor.getSensor(), null /* handler */);
+ }
+
+ @Test
+ public void testInitialize_setsScreenBrightnessToValidValue() throws Exception {
+ mScreen.transitionTo(UNINITIALIZED, INITIALIZED);
+
+ assertNotEquals(PowerManager.BRIGHTNESS_DEFAULT, mServiceFake.screenBrightness);
+ assertTrue(mServiceFake.screenBrightness <= PowerManager.BRIGHTNESS_ON);
+ }
+
+ @Test
+ public void testAod_usesLightSensor() throws Exception {
+ mScreen.transitionTo(UNINITIALIZED, INITIALIZED);
+ mScreen.transitionTo(INITIALIZED, DOZE_AOD);
+
+ mSensor.sendSensorEvent(1000);
+
+ assertEquals(1000, mServiceFake.screenBrightness);
+ }
+
+ @Test
+ public void testPausingAod_pausesLightSensor() throws Exception {
+ mScreen.transitionTo(UNINITIALIZED, INITIALIZED);
+ mScreen.transitionTo(INITIALIZED, DOZE_AOD);
+
+ mSensor.sendSensorEvent(1000);
+
+ mScreen.transitionTo(DOZE_AOD, DOZE_AOD_PAUSED);
+
+ mSensor.sendSensorEvent(1001);
+
+ assertNotEquals(1001, mServiceFake.screenBrightness);
+ }
+
+ @Test
+ public void testPausingAod_resetsBrightness() throws Exception {
+ mScreen.transitionTo(UNINITIALIZED, INITIALIZED);
+ mScreen.transitionTo(INITIALIZED, DOZE_AOD);
+
+ mSensor.sendSensorEvent(1000);
+
+ mScreen.transitionTo(DOZE_AOD, DOZE_AOD_PAUSED);
+
+ assertNotEquals(1000, mServiceFake.screenBrightness);
+ }
+
+ @Test
+ public void testPulsing_usesLightSensor() throws Exception {
+ mScreen.transitionTo(UNINITIALIZED, INITIALIZED);
+ mScreen.transitionTo(INITIALIZED, DOZE);
+ mScreen.transitionTo(DOZE, DOZE_REQUEST_PULSE);
+
+ mSensor.sendSensorEvent(1000);
+
+ assertEquals(1000, mServiceFake.screenBrightness);
+ }
+
+ @Test
+ public void testDozingAfterPulsing_pausesLightSensor() throws Exception {
+ mScreen.transitionTo(UNINITIALIZED, INITIALIZED);
+ mScreen.transitionTo(INITIALIZED, DOZE);
+ mScreen.transitionTo(DOZE, DOZE_REQUEST_PULSE);
+ mScreen.transitionTo(DOZE_REQUEST_PULSE, DOZE_PULSING);
+ mScreen.transitionTo(DOZE_PULSING, DOZE_PULSE_DONE);
+ mScreen.transitionTo(DOZE_PULSE_DONE, DOZE);
+
+ mSensor.sendSensorEvent(1000);
+
+ assertNotEquals(1000, mServiceFake.screenBrightness);
+ }
+
+ @Test
+ public void testNullSensor() throws Exception {
+ mScreen = new DozeScreenBrightness(mContext, mServiceFake, mSensorManager,
+ null /* sensor */, null /* handler */);
+
+ mScreen.transitionTo(UNINITIALIZED, INITIALIZED);
+ mScreen.transitionTo(INITIALIZED, DOZE_AOD);
+ mScreen.transitionTo(DOZE_AOD, DOZE_AOD_PAUSED);
+ }
+
+ @Test
+ public void testNoBrightnessDeliveredAfterFinish() throws Exception {
+ mScreen.transitionTo(UNINITIALIZED, INITIALIZED);
+ mScreen.transitionTo(INITIALIZED, DOZE_AOD);
+ mScreen.transitionTo(DOZE_AOD, FINISH);
+
+ mSensor.sendSensorEvent(1000);
+
+ assertNotEquals(1000, mServiceFake.screenBrightness);
+ }
+
+ @Test
+ public void testBrightness_atLeastOne() throws Exception {
+ mScreen.transitionTo(UNINITIALIZED, INITIALIZED);
+ mScreen.transitionTo(INITIALIZED, DOZE_AOD);
+
+ mSensor.sendSensorEvent(0);
+
+ assertTrue("Brightness must be at least 1, but was " + mServiceFake.screenBrightness,
+ mServiceFake.screenBrightness >= 1);
+ }
+}
\ No newline at end of file
diff --git a/packages/SystemUI/tests/src/com/android/systemui/doze/DozeScreenStateTest.java b/packages/SystemUI/tests/src/com/android/systemui/doze/DozeScreenStateTest.java
new file mode 100644
index 0000000..203876b
--- /dev/null
+++ b/packages/SystemUI/tests/src/com/android/systemui/doze/DozeScreenStateTest.java
@@ -0,0 +1,98 @@
+/*
+ * 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.doze;
+
+import static com.android.systemui.doze.DozeMachine.State.DOZE;
+import static com.android.systemui.doze.DozeMachine.State.DOZE_AOD;
+import static com.android.systemui.doze.DozeMachine.State.DOZE_PULSING;
+import static com.android.systemui.doze.DozeMachine.State.DOZE_REQUEST_PULSE;
+import static com.android.systemui.doze.DozeMachine.State.INITIALIZED;
+import static com.android.systemui.doze.DozeMachine.State.UNINITIALIZED;
+
+import static org.junit.Assert.assertEquals;
+
+import android.support.test.filters.SmallTest;
+import android.support.test.runner.AndroidJUnit4;
+import android.view.Display;
+
+import com.android.systemui.SysuiTestCase;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+@RunWith(AndroidJUnit4.class)
+@SmallTest
+public class DozeScreenStateTest extends SysuiTestCase {
+
+ DozeServiceFake mServiceFake;
+ DozeScreenState mScreen;
+
+ @Before
+ public void setUp() throws Exception {
+ mServiceFake = new DozeServiceFake();
+ mScreen = new DozeScreenState(mServiceFake);
+ }
+
+ @Test
+ public void testScreen_offInDoze() {
+ mScreen.transitionTo(UNINITIALIZED, INITIALIZED);
+ mScreen.transitionTo(INITIALIZED, DOZE);
+
+ assertEquals(Display.STATE_OFF, mServiceFake.screenState);
+ }
+
+ @Test
+ public void testScreen_onInAod() {
+ mScreen.transitionTo(UNINITIALIZED, INITIALIZED);
+ mScreen.transitionTo(INITIALIZED, DOZE_AOD);
+
+ assertEquals(Display.STATE_DOZE_SUSPEND, mServiceFake.screenState);
+ }
+
+ @Test
+ public void testScreen_onInPulse() {
+ mScreen.transitionTo(UNINITIALIZED, INITIALIZED);
+ mScreen.transitionTo(INITIALIZED, DOZE);
+
+ mScreen.transitionTo(DOZE, DOZE_REQUEST_PULSE);
+ mScreen.transitionTo(DOZE_REQUEST_PULSE, DOZE_PULSING);
+
+ assertEquals(Display.STATE_ON, mServiceFake.screenState);
+ }
+
+ @Test
+ public void testScreen_offInRequestPulseWithoutAoD() {
+ mScreen.transitionTo(UNINITIALIZED, INITIALIZED);
+ mScreen.transitionTo(INITIALIZED, DOZE);
+
+ mScreen.transitionTo(DOZE, DOZE_REQUEST_PULSE);
+
+ assertEquals(Display.STATE_OFF, mServiceFake.screenState);
+ }
+
+ @Test
+ public void testScreen_onInRequestPulseWithAoD() {
+ mScreen.transitionTo(UNINITIALIZED, INITIALIZED);
+ mScreen.transitionTo(INITIALIZED, DOZE_AOD);
+
+ mScreen.transitionTo(DOZE, DOZE_REQUEST_PULSE);
+
+ assertEquals(Display.STATE_DOZE_SUSPEND, mServiceFake.screenState);
+ }
+
+}
\ No newline at end of file
diff --git a/packages/SystemUI/tests/src/com/android/systemui/doze/DozeServiceFake.java b/packages/SystemUI/tests/src/com/android/systemui/doze/DozeServiceFake.java
index c1e7fe4..34026b0 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/doze/DozeServiceFake.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/doze/DozeServiceFake.java
@@ -16,6 +16,7 @@
package com.android.systemui.doze;
+import android.os.PowerManager;
import android.view.Display;
public class DozeServiceFake implements DozeMachine.Service {
@@ -23,6 +24,7 @@
public boolean finished;
public int screenState;
public boolean requestedWakeup;
+ public int screenBrightness;
public DozeServiceFake() {
reset();
@@ -38,13 +40,19 @@
screenState = state;
}
- public void reset() {
- finished = false;
- screenState = Display.STATE_UNKNOWN;
- }
-
@Override
public void requestWakeUp() {
requestedWakeup = true;
}
+
+ @Override
+ public void setDozeScreenBrightness(int brightness) {
+ screenBrightness = brightness;
+ }
+
+ public void reset() {
+ finished = false;
+ screenState = Display.STATE_UNKNOWN;
+ screenBrightness = PowerManager.BRIGHTNESS_DEFAULT;
+ }
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/doze/DozeTriggersTest.java b/packages/SystemUI/tests/src/com/android/systemui/doze/DozeTriggersTest.java
index 8641fac..a8ea1c0 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/doze/DozeTriggersTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/doze/DozeTriggersTest.java
@@ -23,6 +23,7 @@
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
+import android.app.AlarmManager;
import android.app.Instrumentation;
import android.os.Handler;
import android.os.Looper;
@@ -56,6 +57,7 @@
private Handler mHandler;
private WakeLock mWakeLock;
private Instrumentation mInstrumentation;
+ private AlarmManager mAlarmManager;
@BeforeClass
public static void setupSuite() {
@@ -67,6 +69,7 @@
public void setUp() throws Exception {
mInstrumentation = InstrumentationRegistry.getInstrumentation();
mMachine = mock(DozeMachine.class);
+ mAlarmManager = mock(AlarmManager.class);
mHost = new DozeHostFake();
mConfig = DozeConfigurationUtil.createMockConfig();
mParameters = DozeConfigurationUtil.createMockParameters();
@@ -75,7 +78,7 @@
mWakeLock = new WakeLockFake();
mInstrumentation.runOnMainSync(() -> {
- mTriggers = new DozeTriggers(mContext, mMachine, mHost,
+ mTriggers = new DozeTriggers(mContext, mMachine, mHost, mAlarmManager,
mConfig, mParameters, mSensors, mHandler, mWakeLock, true);
});
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/AutoAddTrackerTest.java b/packages/SystemUI/tests/src/com/android/systemui/qs/AutoAddTrackerTest.java
new file mode 100644
index 0000000..40f8059
--- /dev/null
+++ b/packages/SystemUI/tests/src/com/android/systemui/qs/AutoAddTrackerTest.java
@@ -0,0 +1,100 @@
+/*
+ * 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.qs;
+
+import static com.android.systemui.statusbar.phone.AutoTileManager.INVERSION;
+import static com.android.systemui.statusbar.phone.AutoTileManager.SAVER;
+import static com.android.systemui.statusbar.phone.AutoTileManager.WORK;
+
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+
+import android.provider.Settings.Secure;
+import android.support.test.filters.SmallTest;
+import android.testing.AndroidTestingRunner;
+import android.testing.TestableLooper.RunWithLooper;
+
+import com.android.systemui.Prefs;
+import com.android.systemui.Prefs.Key;
+import com.android.systemui.SysuiTestCase;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+@RunWith(AndroidTestingRunner.class)
+@RunWithLooper
+@SmallTest
+public class AutoAddTrackerTest extends SysuiTestCase {
+
+ private AutoAddTracker mAutoTracker;
+
+ @Test
+ public void testMigration() {
+ Prefs.putBoolean(mContext, Key.QS_DATA_SAVER_ADDED, true);
+ Prefs.putBoolean(mContext, Key.QS_WORK_ADDED, true);
+ mAutoTracker = new AutoAddTracker(mContext);
+
+ assertTrue(mAutoTracker.isAdded(SAVER));
+ assertTrue(mAutoTracker.isAdded(WORK));
+ assertFalse(mAutoTracker.isAdded(INVERSION));
+
+ assertFalse(Prefs.getBoolean(mContext, Key.QS_DATA_SAVER_ADDED, false));
+ assertFalse(Prefs.getBoolean(mContext, Key.QS_WORK_ADDED, false));
+
+ mAutoTracker.destroy();
+ }
+
+ @Test
+ public void testChangeFromBackup() {
+ mAutoTracker = new AutoAddTracker(mContext);
+
+ assertFalse(mAutoTracker.isAdded(SAVER));
+
+ Secure.putString(mContext.getContentResolver(), Secure.QS_AUTO_ADDED_TILES, SAVER);
+ mAutoTracker.mObserver.onChange(false);
+
+ assertTrue(mAutoTracker.isAdded(SAVER));
+
+ mAutoTracker.destroy();
+ }
+
+ @Test
+ public void testSetAdded() {
+ mAutoTracker = new AutoAddTracker(mContext);
+
+ assertFalse(mAutoTracker.isAdded(SAVER));
+ mAutoTracker.setTileAdded(SAVER);
+
+ assertTrue(mAutoTracker.isAdded(SAVER));
+
+ mAutoTracker.destroy();
+ }
+
+ @Test
+ public void testPersist() {
+ mAutoTracker = new AutoAddTracker(mContext);
+
+ assertFalse(mAutoTracker.isAdded(SAVER));
+ mAutoTracker.setTileAdded(SAVER);
+
+ mAutoTracker.destroy();
+ mAutoTracker = new AutoAddTracker(mContext);
+
+ assertTrue(mAutoTracker.isAdded(SAVER));
+
+ mAutoTracker.destroy();
+ }
+
+}
\ No newline at end of file
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/AutoTileManagerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/AutoTileManagerTest.java
index 0937ce2..c0de004 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/AutoTileManagerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/AutoTileManagerTest.java
@@ -19,12 +19,13 @@
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.verify;
+import android.support.test.filters.SmallTest;
+import android.testing.AndroidTestingRunner;
+import android.testing.TestableLooper.RunWithLooper;
+
import com.android.internal.app.NightDisplayController;
import com.android.systemui.Prefs;
import com.android.systemui.Prefs.Key;
-
-import android.support.test.filters.SmallTest;
-import android.testing.AndroidTestingRunner;
import com.android.systemui.SysuiTestCase;
import com.android.systemui.qs.QSTileHost;
@@ -35,6 +36,7 @@
import org.mockito.Mockito;
@RunWith(AndroidTestingRunner.class)
+@RunWithLooper
@SmallTest
public class AutoTileManagerTest extends SysuiTestCase {
diff --git a/packages/SystemUI/tests/src/com/android/systemui/utils/hardware/FakeSensorManager.java b/packages/SystemUI/tests/src/com/android/systemui/utils/hardware/FakeSensorManager.java
index 30be665..a4ae166 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/utils/hardware/FakeSensorManager.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/utils/hardware/FakeSensorManager.java
@@ -30,13 +30,15 @@
import android.os.SystemClock;
import android.util.ArraySet;
-import com.google.android.collect.Lists;
+import com.android.internal.util.Preconditions;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.ArrayList;
+import java.util.Arrays;
import java.util.List;
+import java.util.stream.Collectors;
/**
* Rudimentary fake for SensorManager
@@ -49,6 +51,8 @@
public class FakeSensorManager extends SensorManager {
private final MockProximitySensor mMockProximitySensor;
+ private final FakeGenericSensor mFakeLightSensor;
+ private final FakeGenericSensor[] mSensors;
public FakeSensorManager(Context context) throws Exception {
Sensor proxSensor = context.getSystemService(SensorManager.class)
@@ -57,13 +61,21 @@
// No prox? Let's create a fake one!
proxSensor = createSensor(Sensor.TYPE_PROXIMITY);
}
- mMockProximitySensor = new MockProximitySensor(proxSensor);
+
+ mSensors = new FakeGenericSensor[]{
+ mMockProximitySensor = new MockProximitySensor(proxSensor),
+ mFakeLightSensor = new FakeGenericSensor(createSensor(Sensor.TYPE_LIGHT)),
+ };
}
public MockProximitySensor getMockProximitySensor() {
return mMockProximitySensor;
}
+ public FakeGenericSensor getFakeLightSensor() {
+ return mFakeLightSensor;
+ }
+
@Override
public Sensor getDefaultSensor(int type) {
Sensor s = super.getDefaultSensor(type);
@@ -77,7 +89,10 @@
@Override
protected List<Sensor> getFullSensorList() {
- return Lists.newArrayList(mMockProximitySensor.sensor);
+ return Arrays
+ .stream(mSensors)
+ .map(i -> i.mSensor)
+ .collect(Collectors.toList());
}
@Override
@@ -87,8 +102,11 @@
@Override
protected void unregisterListenerImpl(SensorEventListener listener, Sensor sensor) {
- if (sensor == mMockProximitySensor.sensor || sensor == null) {
- mMockProximitySensor.listeners.remove(listener);
+ Preconditions.checkNotNull(listener);
+ for (FakeGenericSensor s : mSensors) {
+ if (sensor == null || s.mSensor == sensor) {
+ s.mListeners.remove(listener);
+ }
}
}
@@ -96,9 +114,13 @@
protected boolean registerListenerImpl(SensorEventListener listener, Sensor sensor,
int delayUs,
Handler handler, int maxReportLatencyUs, int reservedFlags) {
- if (sensor == mMockProximitySensor.sensor) {
- mMockProximitySensor.listeners.add(listener);
- return true;
+ Preconditions.checkNotNull(sensor);
+ Preconditions.checkNotNull(listener);
+ for (FakeGenericSensor s : mSensors) {
+ if (s.mSensor == sensor) {
+ s.mListeners.add(listener);
+ return true;
+ }
}
return false;
}
@@ -196,18 +218,35 @@
setter.invoke(sensor, type);
}
- public class MockProximitySensor {
- final Sensor sensor;
- final ArraySet<SensorEventListener> listeners = new ArraySet<>();
+ public class MockProximitySensor extends FakeGenericSensor {
private MockProximitySensor(Sensor sensor) {
- this.sensor = sensor;
+ super(sensor);
}
public void sendProximityResult(boolean far) {
- SensorEvent event = createSensorEvent(1);
- event.values[0] = far ? sensor.getMaximumRange() : 0;
- for (SensorEventListener listener : listeners) {
+ sendSensorEvent(far ? getSensor().getMaximumRange() : 0);
+ }
+ }
+
+ public class FakeGenericSensor {
+
+ private final Sensor mSensor;
+ private final ArraySet<SensorEventListener> mListeners = new ArraySet<>();
+
+ public FakeGenericSensor(
+ Sensor sensor) {
+ this.mSensor = sensor;
+ }
+
+ public Sensor getSensor() {
+ return mSensor;
+ }
+
+ public void sendSensorEvent(float... values) {
+ SensorEvent event = createSensorEvent(values.length);
+ System.arraycopy(values, 0, event.values, 0, values.length);
+ for (SensorEventListener listener : mListeners) {
listener.onSensorChanged(event);
}
}
@@ -222,7 +261,7 @@
} catch (Exception e) {
throw new RuntimeException(e);
}
- event.sensor = sensor;
+ event.sensor = mSensor;
event.timestamp = SystemClock.elapsedRealtimeNanos();
return event;
diff --git a/packages/VpnDialogs/res/values-ar/strings.xml b/packages/VpnDialogs/res/values-ar/strings.xml
index d29c407..e36eef4 100644
--- a/packages/VpnDialogs/res/values-ar/strings.xml
+++ b/packages/VpnDialogs/res/values-ar/strings.xml
@@ -17,7 +17,7 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="prompt" msgid="3183836924226407828">"طلب الاتصال"</string>
- <string name="warning" msgid="809658604548412033">"يريد <xliff:g id="APP">%s</xliff:g> إعداد الاتصال بالشبكة الظاهرية الخاصة التي تتيح له مراقبة حركة المرور على الشبكة. فلا توافق إلا إذا كنت تثق في المصدر. <br /> <br /> <img src=vpn_icon /> يظهر في الجزء العلوي من الشاشة عندما تكون الشبكة الظاهرية الخاصة نشطة."</string>
+ <string name="warning" msgid="809658604548412033">"يريد <xliff:g id="APP">%s</xliff:g> إعداد الاتصال بالشبكة الافتراضية الخاصة التي تتيح له مراقبة حركة المرور على الشبكة. فلا توافق إلا إذا كنت تثق في المصدر. <br /> <br /> <img src=vpn_icon /> يظهر في الجزء العلوي من الشاشة عندما تكون الشبكة الافتراضية الخاصة نشطة."</string>
<string name="legacy_title" msgid="192936250066580964">"VPN متصلة"</string>
<string name="configure" msgid="4905518375574791375">"تهيئة"</string>
<string name="disconnect" msgid="971412338304200056">"قطع الاتصال"</string>
diff --git a/packages/overlays/SysuiDarkThemeOverlay/AndroidManifest.xml b/packages/overlays/SysuiDarkThemeOverlay/AndroidManifest.xml
index ba1c91c..8b6ee2b 100644
--- a/packages/overlays/SysuiDarkThemeOverlay/AndroidManifest.xml
+++ b/packages/overlays/SysuiDarkThemeOverlay/AndroidManifest.xml
@@ -2,7 +2,7 @@
package="com.android.systemui.theme.dark"
android:versionCode="1"
android:versionName="1.0">
- <overlay android:targetPackage="android" android:priority="1"/>
+ <overlay android:targetPackage="com.android.systemui" android:priority="1"/>
<application android:label="@string/sysui_overlay_dark" android:hasCode="false"/>
</manifest>
diff --git a/packages/overlays/SysuiDarkThemeOverlay/res/values/styles.xml b/packages/overlays/SysuiDarkThemeOverlay/res/values/styles.xml
new file mode 100644
index 0000000..0c1b0ef
--- /dev/null
+++ b/packages/overlays/SysuiDarkThemeOverlay/res/values/styles.xml
@@ -0,0 +1,11 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <style name="qs_base" parent="android:Theme.DeviceDefault">
+ <item name="android:colorPrimary">@*android:color/primary_device_default_settings</item>
+ <item name="android:colorPrimaryDark">@*android:color/primary_dark_device_default_settings</item>
+ <item name="android:colorSecondary">@*android:color/secondary_device_default_settings</item>
+ <item name="android:colorAccent">@*android:color/accent_device_default_dark</item>
+ <item name="android:colorControlNormal">?android:attr/textColorPrimary</item>
+ <item name="android:colorBackgroundFloating">#000</item>
+ </style>
+</resources>
\ No newline at end of file
diff --git a/packages/overlays/SysuiDarkThemeOverlay/res/values/themes_device_defaults.xml b/packages/overlays/SysuiDarkThemeOverlay/res/values/themes_device_defaults.xml
deleted file mode 100644
index 7e2b955..0000000
--- a/packages/overlays/SysuiDarkThemeOverlay/res/values/themes_device_defaults.xml
+++ /dev/null
@@ -1,16 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<resources>
- <style name="Theme.DeviceDefault.QuickSettings" parent="android:Theme.DeviceDefault">
- <item name="android:colorPrimary">@*android:color/primary_device_default_settings</item>
- <item name="android:colorPrimaryDark">@*android:color/primary_dark_device_default_settings</item>
- <!-- textColorPrimaryInverse is used on the lock screen and this means that we can't just
- invert text colors otherwise we won't have contrast on the keyguard -->
- <item name="android:textColorPrimaryInverse">@*android:color/primary_text_material_dark</item>
- <!-- same for textColorSecondaryInverse -->
- <item name="android:textColorSecondaryInverse">@*android:color/secondary_text_material_dark</item>
- <item name="android:colorSecondary">@*android:color/secondary_device_default_settings</item>
- <item name="android:colorAccent">@*android:color/accent_device_default_dark</item>
- <item name="android:colorControlNormal">?android:attr/textColorPrimary</item>
- <item name="android:colorBackgroundFloating">#000</item>
- </style>
-</resources>
\ No newline at end of file
diff --git a/packages/overlays/SysuiLightWallpaperThemeOverlay/AndroidManifest.xml b/packages/overlays/SysuiLightWallpaperThemeOverlay/AndroidManifest.xml
index 1745b4c..0a8749c 100644
--- a/packages/overlays/SysuiLightWallpaperThemeOverlay/AndroidManifest.xml
+++ b/packages/overlays/SysuiLightWallpaperThemeOverlay/AndroidManifest.xml
@@ -2,7 +2,7 @@
package="com.android.systemui.theme.lightwallpaper"
android:versionCode="1"
android:versionName="1.0">
- <overlay android:targetPackage="android" android:priority="2"/>
+ <overlay android:targetPackage="com.android.systemui" android:priority="2"/>
<application android:label="@string/sysui_overlay_light" android:hasCode="false"/>
</manifest>
diff --git a/packages/overlays/SysuiLightWallpaperThemeOverlay/res/values/styles.xml b/packages/overlays/SysuiLightWallpaperThemeOverlay/res/values/styles.xml
new file mode 100644
index 0000000..53912b5
--- /dev/null
+++ b/packages/overlays/SysuiLightWallpaperThemeOverlay/res/values/styles.xml
@@ -0,0 +1,12 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <style name="systemui_base" parent="@*android:style/Theme.DeviceDefault.QuickSettings">
+ <item name="android:textColorPrimaryInverse">@*android:color/primary_text_material_light</item>
+ <item name="android:textColorSecondaryInverse">@*android:color/secondary_text_material_light</item>
+ </style>
+
+ <style name="RecentsBase" parent="@android:style/Theme.Material">
+ <item name="android:textColorPrimaryInverse">@*android:color/primary_text_material_light</item>
+ <item name="android:textColorSecondaryInverse">@*android:color/secondary_text_material_light</item>
+ </style>
+</resources>
\ No newline at end of file
diff --git a/packages/overlays/SysuiLightWallpaperThemeOverlay/res/values/themes_device_defaults.xml b/packages/overlays/SysuiLightWallpaperThemeOverlay/res/values/themes_device_defaults.xml
deleted file mode 100644
index 877ebf8..0000000
--- a/packages/overlays/SysuiLightWallpaperThemeOverlay/res/values/themes_device_defaults.xml
+++ /dev/null
@@ -1,7 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<resources>
- <style name="Theme.DeviceDefault.QuickSettings" parent="android:Theme.DeviceDefault.Light">
- <item name="android:textColorPrimaryInverse">@*android:color/primary_text_material_light</item>
- <item name="android:textColorSecondaryInverse">@*android:color/secondary_text_material_light</item>
- </style>
-</resources>
\ No newline at end of file
diff --git a/proto/src/metrics_constants.proto b/proto/src/metrics_constants.proto
index c1a1901..0a0fa18 100644
--- a/proto/src/metrics_constants.proto
+++ b/proto/src/metrics_constants.proto
@@ -4192,6 +4192,16 @@
// ---- End O-DR1 Constants, all O-DR1 constants go above this line ----
+ // ACTION: Settings > Network & Internet > Mobile network > Mobile data
+ // CATEGORY: SETTINGS
+ // OS: O MR
+ ACTION_MOBILE_NETWORK_MOBILE_DATA_TOGGLE = 1081;
+
+ // ACTION: Settings > Network & Internet > Mobile network > Data usage
+ // CATEGORY: SETTINGS
+ // OS: O MR
+ ACTION_MOBILE_NETWORK_DATA_USAGE = 1082;
+
// Add new aosp constants above this line.
// END OF AOSP CONSTANTS
}
diff --git a/services/core/java/com/android/server/BluetoothManagerService.java b/services/core/java/com/android/server/BluetoothManagerService.java
index 61057dd..75206e4 100644
--- a/services/core/java/com/android/server/BluetoothManagerService.java
+++ b/services/core/java/com/android/server/BluetoothManagerService.java
@@ -86,6 +86,8 @@
private static final int ACTIVE_LOG_MAX_SIZE = 20;
private static final int CRASH_LOG_MAX_SIZE = 100;
private static final String REASON_AIRPLANE_MODE = "airplane mode";
+ private static final String REASON_DISALLOWED = "disallowed by system";
+ private static final String REASON_SHARING_DISALLOWED = "sharing disallowed by system";
private static final String REASON_RESTARTED = "automatic restart";
private static final String REASON_START_CRASH = "turn-on crash";
private static final String REASON_SYSTEM_BOOT = "system boot";
@@ -227,25 +229,26 @@
@Override
public void onUserRestrictionsChanged(int userId, Bundle newRestrictions,
Bundle prevRestrictions) {
- if (!UserRestrictionsUtils.restrictionsChanged(prevRestrictions, newRestrictions,
- UserManager.DISALLOW_BLUETOOTH, UserManager.DISALLOW_BLUETOOTH_SHARING)) {
- return; // No relevant changes, nothing to do.
+
+ if (UserRestrictionsUtils.restrictionsChanged(prevRestrictions, newRestrictions,
+ UserManager.DISALLOW_BLUETOOTH_SHARING)) {
+ updateOppLauncherComponentState(userId, newRestrictions.getBoolean(
+ UserManager.DISALLOW_BLUETOOTH_SHARING));
}
- final boolean disallowed = newRestrictions.getBoolean(UserManager.DISALLOW_BLUETOOTH);
-
- // DISALLOW_BLUETOOTH is a global restriction that can only be set by DO or PO on the
- // system user, so we only look at the system user.
- if (userId == UserHandle.USER_SYSTEM && disallowed && (mEnable || mEnableExternal)) {
- try {
- disable(null /* packageName */, true /* persist */);
- } catch (RemoteException e) {
- Slog.w(TAG, "Exception when disabling Bluetooth", e);
+ // DISALLOW_BLUETOOTH can only be set by DO or PO on the system user.
+ if (userId == UserHandle.USER_SYSTEM &&
+ UserRestrictionsUtils.restrictionsChanged(
+ prevRestrictions, newRestrictions, UserManager.DISALLOW_BLUETOOTH)) {
+ if (userId == UserHandle.USER_SYSTEM && newRestrictions.getBoolean(
+ UserManager.DISALLOW_BLUETOOTH)) {
+ updateOppLauncherComponentState(userId, true); // Sharing disallowed
+ sendDisableMsg(REASON_DISALLOWED);
+ } else {
+ updateOppLauncherComponentState(userId, newRestrictions.getBoolean(
+ UserManager.DISALLOW_BLUETOOTH_SHARING));
}
}
- final boolean sharingDisallowed = disallowed
- || newRestrictions.getBoolean(UserManager.DISALLOW_BLUETOOTH_SHARING);
- updateOppLauncherComponentState(userId, sharingDisallowed);
}
};
@@ -2118,7 +2121,8 @@
: PackageManager.COMPONENT_ENABLED_STATE_DEFAULT;
try {
final IPackageManager imp = AppGlobals.getPackageManager();
- imp.setComponentEnabledSetting(oppLauncherComponent, newState, 0 /* flags */, userId);
+ imp.setComponentEnabledSetting(oppLauncherComponent, newState,
+ PackageManager.DONT_KILL_APP, userId);
} catch (Exception e) {
// The component was not found, do nothing.
}
diff --git a/services/core/java/com/android/server/ConnectivityService.java b/services/core/java/com/android/server/ConnectivityService.java
index 98389a6..a2ba7af 100644
--- a/services/core/java/com/android/server/ConnectivityService.java
+++ b/services/core/java/com/android/server/ConnectivityService.java
@@ -210,13 +210,6 @@
// See Settings.Secure.CONNECTIVITY_RELEASE_PENDING_INTENT_DELAY_MS
private final int mReleasePendingIntentDelayMs;
- // Driver specific constants used to select packets received via
- // WiFi that caused the phone to exit sleep state. Currently there
- // is only one kernel implementation so we can get away with
- // constants.
- private static final int mWakeupPacketMark = 0x80000000;
- private static final int mWakeupPacketMask = 0x80000000;
-
private MockableSystemProperties mSystemProperties;
private Tethering mTethering;
@@ -2282,6 +2275,10 @@
notifyNetworkCallbacks(nai, ConnectivityManager.CALLBACK_LOST);
mKeepaliveTracker.handleStopAllKeepalives(nai,
ConnectivityManager.PacketKeepalive.ERROR_INVALID_NETWORK);
+ for (String iface : nai.linkProperties.getAllInterfaceNames()) {
+ // Disable wakeup packet monitoring for each interface.
+ wakeupModifyInterface(iface, nai.networkCapabilities, false);
+ }
nai.networkMonitor.sendMessage(NetworkMonitor.CMD_NETWORK_DISCONNECTED);
mNetworkAgentInfos.remove(msg.replyTo);
updateClat(null, nai.linkProperties, nai);
@@ -3791,6 +3788,9 @@
public void setProvisioningNotificationVisible(boolean visible, int networkType,
String action) {
enforceConnectivityInternalPermission();
+ if (!ConnectivityManager.isNetworkTypeValid(networkType)) {
+ return;
+ }
final long ident = Binder.clearCallingIdentity();
try {
// Concatenate the range of types onto the range of NetIDs.
@@ -4405,22 +4405,35 @@
}
}
- private void wakeupAddInterface(String iface, NetworkCapabilities caps) throws RemoteException {
+ private void wakeupModifyInterface(String iface, NetworkCapabilities caps, boolean add) {
// Marks are only available on WiFi interaces. Checking for
// marks on unsupported interfaces is harmless.
if (!caps.hasTransport(NetworkCapabilities.TRANSPORT_WIFI)) {
return;
}
- mNetd.getNetdService().wakeupAddInterface(
- iface, "iface:" + iface, mWakeupPacketMark, mWakeupPacketMask);
- }
- private void wakeupDelInterface(String iface, NetworkCapabilities caps) throws RemoteException {
- if (!caps.hasTransport(NetworkCapabilities.TRANSPORT_WIFI)) {
+ int mark = mContext.getResources().getInteger(
+ com.android.internal.R.integer.config_networkWakeupPacketMark);
+ int mask = mContext.getResources().getInteger(
+ com.android.internal.R.integer.config_networkWakeupPacketMask);
+
+ // Mask/mark of zero will not detect anything interesting.
+ // Don't install rules unless both values are nonzero.
+ if (mark == 0 || mask == 0) {
return;
}
- mNetd.getNetdService().wakeupDelInterface(
- iface, "iface:" + iface, mWakeupPacketMark, mWakeupPacketMask);
+
+ final String prefix = "iface:" + iface;
+ try {
+ if (add) {
+ mNetd.getNetdService().wakeupAddInterface(iface, prefix, mark, mask);
+ } else {
+ mNetd.getNetdService().wakeupDelInterface(iface, prefix, mark, mask);
+ }
+ } catch (Exception e) {
+ loge("Exception modifying wakeup packet monitoring: " + e);
+ }
+
}
private void updateInterfaces(LinkProperties newLp, LinkProperties oldLp, int netId,
@@ -4435,7 +4448,7 @@
try {
if (DBG) log("Adding iface " + iface + " to network " + netId);
mNetd.addInterfaceToNetwork(iface, netId);
- wakeupAddInterface(iface, caps);
+ wakeupModifyInterface(iface, caps, true);
} catch (Exception e) {
loge("Exception adding interface: " + e);
}
@@ -4443,8 +4456,8 @@
for (String iface : interfaceDiff.removed) {
try {
if (DBG) log("Removing iface " + iface + " from network " + netId);
+ wakeupModifyInterface(iface, caps, false);
mNetd.removeInterfaceFromNetwork(iface, netId);
- wakeupDelInterface(iface, caps);
} catch (Exception e) {
loge("Exception removing interface: " + e);
}
@@ -4941,7 +4954,7 @@
if (newNetwork.getCurrentScore() != score) {
Slog.wtf(TAG, String.format(
"BUG: %s changed score during rematch: %d -> %d",
- score, newNetwork.getCurrentScore()));
+ newNetwork.name(), score, newNetwork.getCurrentScore()));
}
// Second pass: process all listens.
diff --git a/services/core/java/com/android/server/PersistentDataBlockService.java b/services/core/java/com/android/server/PersistentDataBlockService.java
index 1d4c3db..c32a2d1 100644
--- a/services/core/java/com/android/server/PersistentDataBlockService.java
+++ b/services/core/java/com/android/server/PersistentDataBlockService.java
@@ -380,6 +380,12 @@
}
}
+ private long doGetMaximumDataBlockSize() {
+ long actualSize = getBlockDeviceSize() - HEADER_SIZE - DIGEST_SIZE_BYTES
+ - FRP_CREDENTIAL_RESERVED_SIZE - 1;
+ return actualSize <= MAX_DATA_BLOCK_SIZE ? actualSize : MAX_DATA_BLOCK_SIZE;
+ }
+
private native long nativeGetBlockDeviceSize(String path);
private native int nativeWipe(String path);
@@ -389,7 +395,7 @@
enforceUid(Binder.getCallingUid());
// Need to ensure we don't write over the last byte
- long maxBlockSize = getMaximumDataBlockSize();
+ long maxBlockSize = doGetMaximumDataBlockSize();
if (data.length > maxBlockSize) {
// partition is ~500k so shouldn't be a problem to downcast
return (int) -maxBlockSize;
@@ -569,9 +575,8 @@
@Override
public long getMaximumDataBlockSize() {
- long actualSize = getBlockDeviceSize() - HEADER_SIZE - DIGEST_SIZE_BYTES
- - FRP_CREDENTIAL_RESERVED_SIZE - 1;
- return actualSize <= MAX_DATA_BLOCK_SIZE ? actualSize : MAX_DATA_BLOCK_SIZE;
+ enforceUid(Binder.getCallingUid());
+ return doGetMaximumDataBlockSize();
}
@Override
diff --git a/services/core/java/com/android/server/TextServicesManagerService.java b/services/core/java/com/android/server/TextServicesManagerService.java
index 098b43c..7a9bf21 100644
--- a/services/core/java/com/android/server/TextServicesManagerService.java
+++ b/services/core/java/com/android/server/TextServicesManagerService.java
@@ -642,57 +642,6 @@
}
}
- @Override
- public void setCurrentSpellChecker(String locale, String sciId) {
- if (!calledFromValidUser()) {
- return;
- }
- synchronized(mSpellCheckerMap) {
- if (mContext.checkCallingOrSelfPermission(
- android.Manifest.permission.WRITE_SECURE_SETTINGS)
- != PackageManager.PERMISSION_GRANTED) {
- throw new SecurityException(
- "Requires permission "
- + android.Manifest.permission.WRITE_SECURE_SETTINGS);
- }
- setCurrentSpellCheckerLocked(sciId);
- }
- }
-
- @Override
- public void setCurrentSpellCheckerSubtype(String locale, int hashCode) {
- if (!calledFromValidUser()) {
- return;
- }
- synchronized(mSpellCheckerMap) {
- if (mContext.checkCallingOrSelfPermission(
- android.Manifest.permission.WRITE_SECURE_SETTINGS)
- != PackageManager.PERMISSION_GRANTED) {
- throw new SecurityException(
- "Requires permission "
- + android.Manifest.permission.WRITE_SECURE_SETTINGS);
- }
- setCurrentSpellCheckerSubtypeLocked(hashCode);
- }
- }
-
- @Override
- public void setSpellCheckerEnabled(boolean enabled) {
- if (!calledFromValidUser()) {
- return;
- }
- synchronized(mSpellCheckerMap) {
- if (mContext.checkCallingOrSelfPermission(
- android.Manifest.permission.WRITE_SECURE_SETTINGS)
- != PackageManager.PERMISSION_GRANTED) {
- throw new SecurityException(
- "Requires permission "
- + android.Manifest.permission.WRITE_SECURE_SETTINGS);
- }
- setSpellCheckerEnabledLocked(enabled);
- }
- }
-
private void setCurrentSpellCheckerLocked(String sciId) {
if (DBG) {
Slog.w(TAG, "setCurrentSpellChecker: " + sciId);
@@ -732,18 +681,6 @@
}
}
- private void setSpellCheckerEnabledLocked(boolean enabled) {
- if (DBG) {
- Slog.w(TAG, "setSpellCheckerEnabled: " + enabled);
- }
- final long ident = Binder.clearCallingIdentity();
- try {
- mSettings.setSpellCheckerEnabled(enabled);
- } finally {
- Binder.restoreCallingIdentity(ident);
- }
- }
-
private boolean isSpellCheckerEnabledLocked() {
final long ident = Binder.clearCallingIdentity();
try {
@@ -1135,10 +1072,6 @@
return Settings.Secure.getIntForUser(mResolver, key, defaultValue, mCurrentUserId);
}
- private void putBoolean(final String key, final boolean value) {
- putInt(key, value ? 1 : 0);
- }
-
private boolean getBoolean(final String key, final boolean defaultValue) {
return getInt(key, defaultValue ? 1 : 0) == 1;
}
@@ -1178,10 +1111,6 @@
putInt(Settings.Secure.SELECTED_SPELL_CHECKER_SUBTYPE, hashCode);
}
- public void setSpellCheckerEnabled(boolean enabled) {
- putBoolean(Settings.Secure.SPELL_CHECKER_ENABLED, enabled);
- }
-
@NonNull
public String getSelectedSpellChecker() {
return getString(Settings.Secure.SELECTED_SPELL_CHECKER, "");
diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java
index 3566c29..ec1709a 100644
--- a/services/core/java/com/android/server/am/ActivityManagerService.java
+++ b/services/core/java/com/android/server/am/ActivityManagerService.java
@@ -414,6 +414,7 @@
import com.android.server.wm.PinnedStackWindowController;
import com.android.server.wm.WindowManagerService;
+import java.text.SimpleDateFormat;
import org.xmlpull.v1.XmlPullParser;
import org.xmlpull.v1.XmlPullParserException;
import org.xmlpull.v1.XmlSerializer;
@@ -2648,6 +2649,11 @@
mService.start();
}
+ @Override
+ public void onCleanupUser(int userId) {
+ mService.mBatteryStatsService.onCleanupUser(userId);
+ }
+
public ActivityManagerService getService() {
return mService;
}
@@ -5502,11 +5508,8 @@
// NOTE: We should consider creating the file in native code atomically once we've
// gotten rid of the old scheme of dumping and lot of the code that deals with paths
// can be removed.
- try {
- tracesFile = File.createTempFile("anr_", "", tracesDir);
- FileUtils.setPermissions(tracesFile.getAbsolutePath(), 0600, -1, -1); // -rw-------
- } catch (IOException ioe) {
- Slog.w(TAG, "Unable to create ANR traces file: ", ioe);
+ tracesFile = createAnrDumpFile(tracesDir);
+ if (tracesFile == null) {
return null;
}
@@ -5518,6 +5521,31 @@
return tracesFile;
}
+ @GuardedBy("ActivityManagerService.class")
+ private static SimpleDateFormat sAnrFileDateFormat;
+
+ private static synchronized File createAnrDumpFile(File tracesDir) {
+ if (sAnrFileDateFormat == null) {
+ sAnrFileDateFormat = new SimpleDateFormat("yyyy-MM-dd-HH-mm-ss-SSS");
+ }
+
+ final String formattedDate = sAnrFileDateFormat.format(new Date());
+ final File anrFile = new File(tracesDir, "anr_" + formattedDate);
+
+ try {
+ if (anrFile.createNewFile()) {
+ FileUtils.setPermissions(anrFile.getAbsolutePath(), 0600, -1, -1); // -rw-------
+ return anrFile;
+ } else {
+ Slog.w(TAG, "Unable to create ANR dump file: createNewFile failed");
+ }
+ } catch (IOException ioe) {
+ Slog.w(TAG, "Exception creating ANR dump file:", ioe);
+ }
+
+ return null;
+ }
+
/**
* Prune all trace files that are more than a day old.
*
@@ -17189,12 +17217,12 @@
}
} catch (IOException e) {
if (!isCheckinRequest) {
- pw.println("Got IoException!");
+ pw.println("Got IoException! " + e);
pw.flush();
}
} catch (RemoteException e) {
if (!isCheckinRequest) {
- pw.println("Got RemoteException!");
+ pw.println("Got RemoteException! " + e);
pw.flush();
}
}
@@ -23740,6 +23768,7 @@
synchronized (ActivityManagerService.this) {
ActivityManagerService.this.onUserStoppedLocked(userId);
}
+ mBatteryStatsService.onUserRemoved(userId);
}
@Override
diff --git a/services/core/java/com/android/server/am/ActivityStack.java b/services/core/java/com/android/server/am/ActivityStack.java
index 77e438a..5b461a1 100644
--- a/services/core/java/com/android/server/am/ActivityStack.java
+++ b/services/core/java/com/android/server/am/ActivityStack.java
@@ -2848,8 +2848,9 @@
} else {
// If a new task is being launched, then mark the existing top activity as
// supporting picture-in-picture while pausing
- if (focusedTopActivity != null &&
- focusedTopActivity.getStack().getStackId() != PINNED_STACK_ID) {
+ if (focusedTopActivity != null
+ && focusedTopActivity.getStackId() != PINNED_STACK_ID
+ && r.getStackId() != ASSISTANT_STACK_ID) {
focusedTopActivity.supportsPictureInPictureWhilePausing = true;
}
transit = TRANSIT_TASK_OPEN;
@@ -4461,7 +4462,8 @@
}
// If a new task is moved to the front, then mark the existing top activity as supporting
// picture-in-picture while paused
- if (topActivity != null && topActivity.getStack().getStackId() != PINNED_STACK_ID) {
+ if (topActivity != null && topActivity.getStackId() != PINNED_STACK_ID
+ && tr.getStackId() != ASSISTANT_STACK_ID) {
topActivity.supportsPictureInPictureWhilePausing = true;
}
diff --git a/services/core/java/com/android/server/am/BatteryStatsService.java b/services/core/java/com/android/server/am/BatteryStatsService.java
index cf322d7..4836bc3 100644
--- a/services/core/java/com/android/server/am/BatteryStatsService.java
+++ b/services/core/java/com/android/server/am/BatteryStatsService.java
@@ -34,6 +34,7 @@
import android.os.ServiceManager;
import android.os.SystemClock;
import android.os.UserHandle;
+import android.os.UserManagerInternal;
import android.os.WorkSource;
import android.os.health.HealthStatsParceler;
import android.os.health.HealthStatsWriter;
@@ -79,6 +80,7 @@
private static IBatteryStats sService;
final BatteryStatsImpl mStats;
+ private final BatteryStatsImpl.UserInfoProvider mUserManagerUserInfoProvider;
private final Context mContext;
private final BatteryExternalStatsWorker mWorker;
@@ -140,7 +142,17 @@
BatteryStatsService(Context context, File systemDir, Handler handler) {
// BatteryStatsImpl expects the ActivityManagerService handler, so pass that one through.
mContext = context;
- mStats = new BatteryStatsImpl(systemDir, handler, this);
+ mUserManagerUserInfoProvider = new BatteryStatsImpl.UserInfoProvider() {
+ private UserManagerInternal umi;
+ @Override
+ public int[] getUserIds() {
+ if (umi == null) {
+ umi = LocalServices.getService(UserManagerInternal.class);
+ }
+ return (umi != null) ? umi.getUserIds() : null;
+ }
+ };
+ mStats = new BatteryStatsImpl(systemDir, handler, this, mUserManagerUserInfoProvider);
mWorker = new BatteryExternalStatsWorker(context, mStats);
mStats.setExternalStatsSyncLocked(mWorker);
mStats.setRadioScanningTimeoutLocked(mContext.getResources().getInteger(
@@ -242,6 +254,18 @@
}
}
+ void onCleanupUser(int userId) {
+ synchronized (mStats) {
+ mStats.onCleanupUserLocked(userId);
+ }
+ }
+
+ void onUserRemoved(int userId) {
+ synchronized (mStats) {
+ mStats.onUserRemovedLocked(userId);
+ }
+ }
+
void addIsolatedUid(int isolatedUid, int appUid) {
synchronized (mStats) {
mStats.addIsolatedUidLocked(isolatedUid, appUid);
@@ -369,10 +393,10 @@
}
}
- public void noteJobFinish(String name, int uid) {
+ public void noteJobFinish(String name, int uid, int stopReason) {
enforceCallingPermission();
synchronized (mStats) {
- mStats.noteJobFinishLocked(name, uid);
+ mStats.noteJobFinishLocked(name, uid, stopReason);
}
}
@@ -1260,7 +1284,7 @@
in.unmarshall(raw, 0, raw.length);
in.setDataPosition(0);
BatteryStatsImpl checkinStats = new BatteryStatsImpl(
- null, mStats.mHandler, null);
+ null, mStats.mHandler, null, mUserManagerUserInfoProvider);
checkinStats.readSummaryFromParcel(in);
in.recycle();
checkinStats.dumpCheckinLocked(mContext, pw, apps, flags,
diff --git a/services/core/java/com/android/server/connectivity/NetworkMonitor.java b/services/core/java/com/android/server/connectivity/NetworkMonitor.java
index 0ee2a41..d3a9354 100644
--- a/services/core/java/com/android/server/connectivity/NetworkMonitor.java
+++ b/services/core/java/com/android/server/connectivity/NetworkMonitor.java
@@ -29,6 +29,7 @@
import android.net.CaptivePortal;
import android.net.ConnectivityManager;
import android.net.ICaptivePortal;
+import android.net.Network;
import android.net.NetworkRequest;
import android.net.ProxyInfo;
import android.net.TrafficStats;
@@ -71,6 +72,9 @@
import java.net.URL;
import java.net.UnknownHostException;
import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.LinkedHashMap;
import java.util.List;
import java.util.Random;
import java.util.concurrent.CountDownLatch;
@@ -95,7 +99,7 @@
"http://play.googleapis.com/generate_204";
private static final String DEFAULT_USER_AGENT = "Mozilla/5.0 (X11; Linux x86_64) "
+ "AppleWebKit/537.36 (KHTML, like Gecko) "
- + "Chrome/52.0.2743.82 Safari/537.36";
+ + "Chrome/60.0.3112.32 Safari/537.36";
private static final int SOCKET_TIMEOUT_MS = 10000;
private static final int PROBE_TIMEOUT_MS = 3000;
@@ -228,6 +232,7 @@
private final Context mContext;
private final Handler mConnectivityServiceHandler;
private final NetworkAgentInfo mNetworkAgentInfo;
+ private final Network mNetwork;
private final int mNetId;
private final TelephonyManager mTelephonyManager;
private final WifiManager mWifiManager;
@@ -286,7 +291,8 @@
mMetricsLog = logger;
mConnectivityServiceHandler = handler;
mNetworkAgentInfo = networkAgentInfo;
- mNetId = mNetworkAgentInfo.network.netId;
+ mNetwork = new OneAddressPerFamilyNetwork(networkAgentInfo.network);
+ mNetId = mNetwork.netId;
mTelephonyManager = (TelephonyManager) context.getSystemService(Context.TELEPHONY_SERVICE);
mWifiManager = (WifiManager) context.getSystemService(Context.WIFI_SERVICE);
mAlarmManager = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE);
@@ -415,7 +421,7 @@
maybeLogEvaluationResult(
networkEventType(validationStage(), EvaluationResult.VALIDATED));
mConnectivityServiceHandler.sendMessage(obtainMessage(EVENT_NETWORK_TESTED,
- NETWORK_TEST_RESULT_VALID, mNetworkAgentInfo.network.netId, null));
+ NETWORK_TEST_RESULT_VALID, mNetId, null));
mValidations++;
}
@@ -440,7 +446,8 @@
case CMD_LAUNCH_CAPTIVE_PORTAL_APP:
final Intent intent = new Intent(
ConnectivityManager.ACTION_CAPTIVE_PORTAL_SIGN_IN);
- intent.putExtra(ConnectivityManager.EXTRA_NETWORK, mNetworkAgentInfo.network);
+ // OneAddressPerFamilyNetwork is not parcelable across processes.
+ intent.putExtra(ConnectivityManager.EXTRA_NETWORK, new Network(mNetwork));
intent.putExtra(ConnectivityManager.EXTRA_CAPTIVE_PORTAL,
new CaptivePortal(new ICaptivePortal.Stub() {
@Override
@@ -468,8 +475,7 @@
@Override
public void exit() {
- Message message = obtainMessage(EVENT_PROVISIONING_NOTIFICATION, 0,
- mNetworkAgentInfo.network.netId, null);
+ Message message = obtainMessage(EVENT_PROVISIONING_NOTIFICATION, 0, mNetId, null);
mConnectivityServiceHandler.sendMessage(message);
}
}
@@ -623,7 +629,7 @@
CustomIntentReceiver(String action, int token, int what) {
mToken = token;
mWhat = what;
- mAction = action + "_" + mNetworkAgentInfo.network.netId + "_" + token;
+ mAction = action + "_" + mNetId + "_" + token;
mContext.registerReceiver(this, new IntentFilter(mAction));
}
public PendingIntent getPendingIntent() {
@@ -659,8 +665,7 @@
CMD_LAUNCH_CAPTIVE_PORTAL_APP);
}
// Display the sign in notification.
- Message message = obtainMessage(EVENT_PROVISIONING_NOTIFICATION, 1,
- mNetworkAgentInfo.network.netId,
+ Message message = obtainMessage(EVENT_PROVISIONING_NOTIFICATION, 1, mNetId,
mLaunchCaptivePortalAppBroadcastReceiver.getPendingIntent());
mConnectivityServiceHandler.sendMessage(message);
// Retest for captive portal occasionally.
@@ -675,6 +680,31 @@
}
}
+ // Limits the list of IP addresses returned by getAllByName or tried by openConnection to at
+ // most one per address family. This ensures we only wait up to 20 seconds for TCP connections
+ // to complete, regardless of how many IP addresses a host has.
+ private static class OneAddressPerFamilyNetwork extends Network {
+ public OneAddressPerFamilyNetwork(Network network) {
+ super(network);
+ }
+
+ @Override
+ public InetAddress[] getAllByName(String host) throws UnknownHostException {
+ List<InetAddress> addrs = Arrays.asList(super.getAllByName(host));
+
+ // Ensure the address family of the first address is tried first.
+ LinkedHashMap<Class, InetAddress> addressByFamily = new LinkedHashMap<>();
+ addressByFamily.put(addrs.get(0).getClass(), addrs.get(0));
+ Collections.shuffle(addrs);
+
+ for (InetAddress addr : addrs) {
+ addressByFamily.put(addr.getClass(), addr);
+ }
+
+ return addressByFamily.values().toArray(new InetAddress[addressByFamily.size()]);
+ }
+ }
+
private static String getCaptivePortalServerHttpsUrl(Context context) {
return getSetting(context, Settings.Global.CAPTIVE_PORTAL_HTTPS_URL, DEFAULT_HTTPS_URL);
}
@@ -805,7 +835,7 @@
int result;
String connectInfo;
try {
- InetAddress[] addresses = mNetworkAgentInfo.network.getAllByName(host);
+ InetAddress[] addresses = mNetwork.getAllByName(host);
StringBuffer buffer = new StringBuffer();
for (InetAddress address : addresses) {
buffer.append(',').append(address.getHostAddress());
@@ -834,7 +864,7 @@
final Stopwatch probeTimer = new Stopwatch().start();
final int oldTag = TrafficStats.getAndSetThreadStatsTag(TrafficStats.TAG_SYSTEM_PROBE);
try {
- urlConnection = (HttpURLConnection) mNetworkAgentInfo.network.openConnection(url);
+ urlConnection = (HttpURLConnection) mNetwork.openConnection(url);
urlConnection.setInstanceFollowRedirects(probeType == ValidationProbeEvent.PROBE_PAC);
urlConnection.setConnectTimeout(SOCKET_TIMEOUT_MS);
urlConnection.setReadTimeout(SOCKET_TIMEOUT_MS);
diff --git a/services/core/java/com/android/server/connectivity/Tethering.java b/services/core/java/com/android/server/connectivity/Tethering.java
index e5fc4b1..b657335 100644
--- a/services/core/java/com/android/server/connectivity/Tethering.java
+++ b/services/core/java/com/android/server/connectivity/Tethering.java
@@ -16,6 +16,7 @@
package com.android.server.connectivity;
+import static android.hardware.usb.UsbManager.USB_CONFIGURED;
import static android.hardware.usb.UsbManager.USB_CONNECTED;
import static android.hardware.usb.UsbManager.USB_FUNCTION_RNDIS;
import static android.net.ConnectivityManager.getNetworkTypeName;
@@ -47,6 +48,7 @@
import android.net.ConnectivityManager;
import android.net.INetworkPolicyManager;
import android.net.INetworkStatsService;
+import android.net.IpPrefix;
import android.net.LinkProperties;
import android.net.Network;
import android.net.NetworkCapabilities;
@@ -107,6 +109,7 @@
import java.util.HashSet;
import java.util.Iterator;
import java.util.Map;
+import java.util.Set;
import java.util.concurrent.atomic.AtomicInteger;
@@ -213,7 +216,7 @@
mContext.getContentResolver(),
mLog);
mUpstreamNetworkMonitor = new UpstreamNetworkMonitor(
- mContext, mTetherMasterSM, TetherMasterSM.EVENT_UPSTREAM_CALLBACK, mLog);
+ mContext, mTetherMasterSM, mLog, TetherMasterSM.EVENT_UPSTREAM_CALLBACK );
mForwardedDownstreams = new HashSet<>();
mSimChange = new SimChangeListener(
mContext, mTetherMasterSM.getHandler(), () -> reevaluateSimCardProvisioning());
@@ -701,7 +704,7 @@
private void showTetheredNotification(int id) {
NotificationManager notificationManager =
- (NotificationManager)mContext.getSystemService(Context.NOTIFICATION_SERVICE);
+ (NotificationManager) mContext.getSystemService(Context.NOTIFICATION_SERVICE);
if (notificationManager == null) {
return;
}
@@ -762,7 +765,7 @@
private void clearTetheredNotification() {
NotificationManager notificationManager =
- (NotificationManager)mContext.getSystemService(Context.NOTIFICATION_SERVICE);
+ (NotificationManager) mContext.getSystemService(Context.NOTIFICATION_SERVICE);
if (notificationManager != null && mLastNotificationId != 0) {
notificationManager.cancelAsUser(null, mLastNotificationId,
UserHandle.ALL);
@@ -801,11 +804,37 @@
private void handleUsbAction(Intent intent) {
final boolean usbConnected = intent.getBooleanExtra(USB_CONNECTED, false);
+ final boolean usbConfigured = intent.getBooleanExtra(USB_CONFIGURED, false);
final boolean rndisEnabled = intent.getBooleanExtra(USB_FUNCTION_RNDIS, false);
+
+ mLog.log(String.format("USB bcast connected:%s configured:%s rndis:%s",
+ usbConnected, usbConfigured, rndisEnabled));
+
+ // There are three types of ACTION_USB_STATE:
+ //
+ // - DISCONNECTED (USB_CONNECTED and USB_CONFIGURED are 0)
+ // Meaning: USB connection has ended either because of
+ // software reset or hard unplug.
+ //
+ // - CONNECTED (USB_CONNECTED is 1, USB_CONFIGURED is 0)
+ // Meaning: the first stage of USB protocol handshake has
+ // occurred but it is not complete.
+ //
+ // - CONFIGURED (USB_CONNECTED and USB_CONFIGURED are 1)
+ // Meaning: the USB handshake is completely done and all the
+ // functions are ready to use.
+ //
+ // For more explanation, see b/62552150 .
+ if (usbConnected && !usbConfigured) {
+ // Nothing for us to do here.
+ // TODO: consider ignoring DISCONNECTED broadcasts as well.
+ return;
+ }
+
synchronized (Tethering.this.mPublicSync) {
mRndisEnabled = rndisEnabled;
// start tethering if we have a request pending
- if (usbConnected && mRndisEnabled && mUsbTetherRequested) {
+ if (usbConfigured && mRndisEnabled && mUsbTetherRequested) {
tetherMatchingInterfaces(
IControlsTethering.STATE_TETHERED,
ConnectivityManager.TETHERING_USB);
@@ -981,7 +1010,7 @@
public int setUsbTethering(boolean enable) {
if (VDBG) Log.d(TAG, "setUsbTethering(" + enable + ")");
- UsbManager usbManager = mContext.getSystemService(UsbManager.class);
+ UsbManager usbManager = (UsbManager) mContext.getSystemService(Context.USB_SERVICE);
synchronized (mPublicSync) {
if (enable) {
@@ -1076,7 +1105,7 @@
// Needed because the canonical source of upstream truth is just the
// upstream interface name, |mCurrentUpstreamIface|. This is ripe for
// future simplification, once the upstream Network is canonical.
- boolean pertainsToCurrentUpstream(NetworkState ns) {
+ private boolean pertainsToCurrentUpstream(NetworkState ns) {
if (ns != null && ns.linkProperties != null && mCurrentUpstreamIface != null) {
for (String ifname : ns.linkProperties.getAllInterfaceNames()) {
if (mCurrentUpstreamIface.equals(ifname)) {
@@ -1110,6 +1139,12 @@
}
}
+ private void startOffloadController() {
+ mOffloadController.start();
+ mOffloadController.updateExemptPrefixes(
+ mUpstreamNetworkMonitor.getOffloadExemptPrefixes());
+ }
+
class TetherMasterSM extends StateMachine {
private static final int BASE_MASTER = Protocol.BASE_TETHERING;
// an interface SM has requested Tethering/Local Hotspot
@@ -1203,146 +1238,138 @@
}
}
- class TetherMasterUtilState extends State {
- @Override
- public boolean processMessage(Message m) {
+ protected boolean turnOnMasterTetherSettings() {
+ final TetheringConfiguration cfg = mConfig;
+ try {
+ mNMService.setIpForwardingEnabled(true);
+ } catch (Exception e) {
+ mLog.e(e);
+ transitionTo(mSetIpForwardingEnabledErrorState);
return false;
}
-
- protected boolean turnOnMasterTetherSettings() {
- final TetheringConfiguration cfg = mConfig;
- try {
- mNMService.setIpForwardingEnabled(true);
- } catch (Exception e) {
- mLog.e(e);
- transitionTo(mSetIpForwardingEnabledErrorState);
- return false;
- }
- // TODO: Randomize DHCPv4 ranges, especially in hotspot mode.
- try {
- // TODO: Find a more accurate method name (startDHCPv4()?).
- mNMService.startTethering(cfg.dhcpRanges);
- } catch (Exception e) {
- try {
- mNMService.stopTethering();
- mNMService.startTethering(cfg.dhcpRanges);
- } catch (Exception ee) {
- mLog.e(ee);
- transitionTo(mStartTetheringErrorState);
- return false;
- }
- }
- mLog.log("SET master tether settings: ON");
- return true;
- }
-
- protected boolean turnOffMasterTetherSettings() {
+ // TODO: Randomize DHCPv4 ranges, especially in hotspot mode.
+ try {
+ // TODO: Find a more accurate method name (startDHCPv4()?).
+ mNMService.startTethering(cfg.dhcpRanges);
+ } catch (Exception e) {
try {
mNMService.stopTethering();
- } catch (Exception e) {
- mLog.e(e);
- transitionTo(mStopTetheringErrorState);
+ mNMService.startTethering(cfg.dhcpRanges);
+ } catch (Exception ee) {
+ mLog.e(ee);
+ transitionTo(mStartTetheringErrorState);
return false;
}
- try {
- mNMService.setIpForwardingEnabled(false);
- } catch (Exception e) {
- mLog.e(e);
- transitionTo(mSetIpForwardingDisabledErrorState);
- return false;
- }
- transitionTo(mInitialState);
- mLog.log("SET master tether settings: OFF");
- return true;
}
+ mLog.log("SET master tether settings: ON");
+ return true;
+ }
- protected void chooseUpstreamType(boolean tryCell) {
- updateConfiguration(); // TODO - remove?
-
- final NetworkState ns = mUpstreamNetworkMonitor.selectPreferredUpstreamType(
- mConfig.preferredUpstreamIfaceTypes);
- if (ns == null) {
- if (tryCell) {
- mUpstreamNetworkMonitor.registerMobileNetworkRequest();
- // We think mobile should be coming up; don't set a retry.
- } else {
- sendMessageDelayed(CMD_RETRY_UPSTREAM, UPSTREAM_SETTLE_TIME_MS);
- }
- }
- setUpstreamNetwork(ns);
+ protected boolean turnOffMasterTetherSettings() {
+ try {
+ mNMService.stopTethering();
+ } catch (Exception e) {
+ mLog.e(e);
+ transitionTo(mStopTetheringErrorState);
+ return false;
}
+ try {
+ mNMService.setIpForwardingEnabled(false);
+ } catch (Exception e) {
+ mLog.e(e);
+ transitionTo(mSetIpForwardingDisabledErrorState);
+ return false;
+ }
+ transitionTo(mInitialState);
+ mLog.log("SET master tether settings: OFF");
+ return true;
+ }
- protected void setUpstreamNetwork(NetworkState ns) {
- String iface = null;
- if (ns != null && ns.linkProperties != null) {
- // Find the interface with the default IPv4 route. It may be the
- // interface described by linkProperties, or one of the interfaces
- // stacked on top of it.
- Log.i(TAG, "Finding IPv4 upstream interface on: " + ns.linkProperties);
- RouteInfo ipv4Default = RouteInfo.selectBestRoute(
- ns.linkProperties.getAllRoutes(), Inet4Address.ANY);
- if (ipv4Default != null) {
- iface = ipv4Default.getInterface();
- Log.i(TAG, "Found interface " + ipv4Default.getInterface());
- } else {
- Log.i(TAG, "No IPv4 upstream interface, giving up.");
- }
- }
+ protected void chooseUpstreamType(boolean tryCell) {
+ updateConfiguration(); // TODO - remove?
- if (iface != null) {
- setDnsForwarders(ns.network, ns.linkProperties);
+ final NetworkState ns = mUpstreamNetworkMonitor.selectPreferredUpstreamType(
+ mConfig.preferredUpstreamIfaceTypes);
+ if (ns == null) {
+ if (tryCell) {
+ mUpstreamNetworkMonitor.registerMobileNetworkRequest();
+ // We think mobile should be coming up; don't set a retry.
+ } else {
+ sendMessageDelayed(CMD_RETRY_UPSTREAM, UPSTREAM_SETTLE_TIME_MS);
}
- notifyTetheredOfNewUpstreamIface(iface);
- if (ns != null && pertainsToCurrentUpstream(ns)) {
- // If we already have NetworkState for this network examine
- // it immediately, because there likely will be no second
- // EVENT_ON_AVAILABLE (it was already received).
- handleNewUpstreamNetworkState(ns);
- } else if (mCurrentUpstreamIface == null) {
- // There are no available upstream networks, or none that
- // have an IPv4 default route (current metric for success).
- handleNewUpstreamNetworkState(null);
+ }
+ setUpstreamNetwork(ns);
+ }
+
+ protected void setUpstreamNetwork(NetworkState ns) {
+ String iface = null;
+ if (ns != null && ns.linkProperties != null) {
+ // Find the interface with the default IPv4 route. It may be the
+ // interface described by linkProperties, or one of the interfaces
+ // stacked on top of it.
+ Log.i(TAG, "Finding IPv4 upstream interface on: " + ns.linkProperties);
+ RouteInfo ipv4Default = RouteInfo.selectBestRoute(
+ ns.linkProperties.getAllRoutes(), Inet4Address.ANY);
+ if (ipv4Default != null) {
+ iface = ipv4Default.getInterface();
+ Log.i(TAG, "Found interface " + ipv4Default.getInterface());
+ } else {
+ Log.i(TAG, "No IPv4 upstream interface, giving up.");
}
}
- protected void setDnsForwarders(final Network network, final LinkProperties lp) {
- // TODO: Set v4 and/or v6 DNS per available connectivity.
- String[] dnsServers = mConfig.defaultIPv4DNS;
- final Collection<InetAddress> dnses = lp.getDnsServers();
- // TODO: Properly support the absence of DNS servers.
- if (dnses != null && !dnses.isEmpty()) {
- // TODO: remove this invocation of NetworkUtils.makeStrings().
- dnsServers = NetworkUtils.makeStrings(dnses);
- }
- try {
- mNMService.setDnsForwarders(network, dnsServers);
- mLog.log(String.format(
- "SET DNS forwarders: network=%s dnsServers=%s",
- network, Arrays.toString(dnsServers)));
- } catch (Exception e) {
- // TODO: Investigate how this can fail and what exactly
- // happens if/when such failures occur.
- mLog.e("setting DNS forwarders failed, " + e);
- transitionTo(mSetDnsForwardersErrorState);
- }
+ if (iface != null) {
+ setDnsForwarders(ns.network, ns.linkProperties);
}
+ notifyTetheredOfNewUpstreamIface(iface);
+ if (ns != null && pertainsToCurrentUpstream(ns)) {
+ // If we already have NetworkState for this network examine
+ // it immediately, because there likely will be no second
+ // EVENT_ON_AVAILABLE (it was already received).
+ handleNewUpstreamNetworkState(ns);
+ } else if (mCurrentUpstreamIface == null) {
+ // There are no available upstream networks, or none that
+ // have an IPv4 default route (current metric for success).
+ handleNewUpstreamNetworkState(null);
+ }
+ }
- protected void notifyTetheredOfNewUpstreamIface(String ifaceName) {
- if (DBG) Log.d(TAG, "Notifying tethered with upstream=" + ifaceName);
- mCurrentUpstreamIface = ifaceName;
- for (TetherInterfaceStateMachine sm : mNotifyList) {
- sm.sendMessage(TetherInterfaceStateMachine.CMD_TETHER_CONNECTION_CHANGED,
- ifaceName);
- }
+ protected void setDnsForwarders(final Network network, final LinkProperties lp) {
+ // TODO: Set v4 and/or v6 DNS per available connectivity.
+ String[] dnsServers = mConfig.defaultIPv4DNS;
+ final Collection<InetAddress> dnses = lp.getDnsServers();
+ // TODO: Properly support the absence of DNS servers.
+ if (dnses != null && !dnses.isEmpty()) {
+ // TODO: remove this invocation of NetworkUtils.makeStrings().
+ dnsServers = NetworkUtils.makeStrings(dnses);
}
+ try {
+ mNMService.setDnsForwarders(network, dnsServers);
+ mLog.log(String.format(
+ "SET DNS forwarders: network=%s dnsServers=%s",
+ network, Arrays.toString(dnsServers)));
+ } catch (Exception e) {
+ // TODO: Investigate how this can fail and what exactly
+ // happens if/when such failures occur.
+ mLog.e("setting DNS forwarders failed, " + e);
+ transitionTo(mSetDnsForwardersErrorState);
+ }
+ }
- protected void handleNewUpstreamNetworkState(NetworkState ns) {
- mIPv6TetheringCoordinator.updateUpstreamNetworkState(ns);
- mOffloadController.setUpstreamLinkProperties(
- (ns != null) ? ns.linkProperties : null);
+ protected void notifyTetheredOfNewUpstreamIface(String ifaceName) {
+ if (DBG) Log.d(TAG, "Notifying tethered with upstream=" + ifaceName);
+ mCurrentUpstreamIface = ifaceName;
+ for (TetherInterfaceStateMachine sm : mNotifyList) {
+ sm.sendMessage(TetherInterfaceStateMachine.CMD_TETHER_CONNECTION_CHANGED,
+ ifaceName);
}
}
+ protected void handleNewUpstreamNetworkState(NetworkState ns) {
+ mIPv6TetheringCoordinator.updateUpstreamNetworkState(ns);
+ mOffloadController.setUpstreamLinkProperties((ns != null) ? ns.linkProperties : null);
+ }
+
private void handleInterfaceServingStateActive(int mode, TetherInterfaceStateMachine who) {
if (mNotifyList.indexOf(who) < 0) {
mNotifyList.add(who);
@@ -1389,7 +1416,61 @@
}
}
- class TetherModeAliveState extends TetherMasterUtilState {
+ private void handleUpstreamNetworkMonitorCallback(int arg1, Object o) {
+ if (arg1 == UpstreamNetworkMonitor.NOTIFY_EXEMPT_PREFIXES) {
+ mOffloadController.updateExemptPrefixes((Set<IpPrefix>) o);
+ return;
+ }
+
+ final NetworkState ns = (NetworkState) o;
+
+ if (ns == null || !pertainsToCurrentUpstream(ns)) {
+ // TODO: In future, this is where upstream evaluation and selection
+ // could be handled for notifications which include sufficient data.
+ // For example, after CONNECTIVITY_ACTION listening is removed, here
+ // is where we could observe a Wi-Fi network becoming available and
+ // passing validation.
+ if (mCurrentUpstreamIface == null) {
+ // If we have no upstream interface, try to run through upstream
+ // selection again. If, for example, IPv4 connectivity has shown up
+ // after IPv6 (e.g., 464xlat became available) we want the chance to
+ // notice and act accordingly.
+ chooseUpstreamType(false);
+ }
+ return;
+ }
+
+ switch (arg1) {
+ case UpstreamNetworkMonitor.EVENT_ON_AVAILABLE:
+ // The default network changed, or DUN connected
+ // before this callback was processed. Updates
+ // for the current NetworkCapabilities and
+ // LinkProperties have been requested (default
+ // request) or are being sent shortly (DUN). Do
+ // nothing until they arrive; if no updates
+ // arrive there's nothing to do.
+ break;
+ case UpstreamNetworkMonitor.EVENT_ON_CAPABILITIES:
+ handleNewUpstreamNetworkState(ns);
+ break;
+ case UpstreamNetworkMonitor.EVENT_ON_LINKPROPERTIES:
+ setDnsForwarders(ns.network, ns.linkProperties);
+ handleNewUpstreamNetworkState(ns);
+ break;
+ case UpstreamNetworkMonitor.EVENT_ON_LOST:
+ // TODO: Re-evaluate possible upstreams. Currently upstream
+ // reevaluation is triggered via received CONNECTIVITY_ACTION
+ // broadcasts that result in being passed a
+ // TetherMasterSM.CMD_UPSTREAM_CHANGED.
+ handleNewUpstreamNetworkState(null);
+ break;
+ default:
+ mLog.e("Unknown arg1 value: " + arg1);
+ break;
+ }
+ }
+
+ class TetherModeAliveState extends State {
boolean mUpstreamWanted = false;
boolean mTryCell = true;
@@ -1407,7 +1488,7 @@
// TODO: De-duplicate with updateUpstreamWanted() below.
if (upstreamWanted()) {
mUpstreamWanted = true;
- mOffloadController.start();
+ startOffloadController();
chooseUpstreamType(true);
mTryCell = false;
}
@@ -1427,7 +1508,7 @@
mUpstreamWanted = upstreamWanted();
if (mUpstreamWanted != previousUpstreamWanted) {
if (mUpstreamWanted) {
- mOffloadController.start();
+ startOffloadController();
} else {
mOffloadController.stop();
}
@@ -1507,52 +1588,8 @@
break;
case EVENT_UPSTREAM_CALLBACK: {
updateUpstreamWanted();
- if (!mUpstreamWanted) break;
-
- final NetworkState ns = (NetworkState) message.obj;
-
- if (ns == null || !pertainsToCurrentUpstream(ns)) {
- // TODO: In future, this is where upstream evaluation and selection
- // could be handled for notifications which include sufficient data.
- // For example, after CONNECTIVITY_ACTION listening is removed, here
- // is where we could observe a Wi-Fi network becoming available and
- // passing validation.
- if (mCurrentUpstreamIface == null) {
- // If we have no upstream interface, try to run through upstream
- // selection again. If, for example, IPv4 connectivity has shown up
- // after IPv6 (e.g., 464xlat became available) we want the chance to
- // notice and act accordingly.
- chooseUpstreamType(false);
- }
- break;
- }
-
- switch (message.arg1) {
- case UpstreamNetworkMonitor.EVENT_ON_AVAILABLE:
- // The default network changed, or DUN connected
- // before this callback was processed. Updates
- // for the current NetworkCapabilities and
- // LinkProperties have been requested (default
- // request) or are being sent shortly (DUN). Do
- // nothing until they arrive; if no updates
- // arrive there's nothing to do.
- break;
- case UpstreamNetworkMonitor.EVENT_ON_CAPABILITIES:
- handleNewUpstreamNetworkState(ns);
- break;
- case UpstreamNetworkMonitor.EVENT_ON_LINKPROPERTIES:
- setDnsForwarders(ns.network, ns.linkProperties);
- handleNewUpstreamNetworkState(ns);
- break;
- case UpstreamNetworkMonitor.EVENT_ON_LOST:
- // TODO: Re-evaluate possible upstreams. Currently upstream
- // reevaluation is triggered via received CONNECTIVITY_ACTION
- // broadcasts that result in being passed a
- // TetherMasterSM.CMD_UPSTREAM_CHANGED.
- handleNewUpstreamNetworkState(null);
- break;
- default:
- break;
+ if (mUpstreamWanted) {
+ handleUpstreamNetworkMonitorCallback(message.arg1, message.obj);
}
break;
}
diff --git a/services/core/java/com/android/server/connectivity/tethering/OffloadController.java b/services/core/java/com/android/server/connectivity/tethering/OffloadController.java
index 08deef8..20ec206 100644
--- a/services/core/java/com/android/server/connectivity/tethering/OffloadController.java
+++ b/services/core/java/com/android/server/connectivity/tethering/OffloadController.java
@@ -19,6 +19,7 @@
import static android.provider.Settings.Global.TETHER_OFFLOAD_DISABLED;
import android.content.ContentResolver;
+import android.net.IpPrefix;
import android.net.LinkProperties;
import android.net.RouteInfo;
import android.net.util.SharedLog;
@@ -28,6 +29,7 @@
import java.net.Inet4Address;
import java.net.InetAddress;
import java.util.ArrayList;
+import java.util.Set;
/**
* A class to encapsulate the business logic of programming the tethering
@@ -45,6 +47,7 @@
private boolean mConfigInitialized;
private boolean mControlInitialized;
private LinkProperties mUpstreamLinkProperties;
+ private Set<IpPrefix> mExemptPrefixes;
public OffloadController(Handler h, OffloadHardwareInterface hwi,
ContentResolver contentResolver, SharedLog log) {
@@ -55,7 +58,12 @@
}
public void start() {
- if (isOffloadDisabled() || started()) return;
+ if (started()) return;
+
+ if (isOffloadDisabled()) {
+ mLog.i("tethering offload disabled");
+ return;
+ }
if (!mConfigInitialized) {
mConfigInitialized = mHwInterface.initOffloadConfig();
@@ -108,6 +116,17 @@
pushUpstreamParameters();
}
+ public void updateExemptPrefixes(Set<IpPrefix> exemptPrefixes) {
+ if (!started()) return;
+
+ mExemptPrefixes = exemptPrefixes;
+ // TODO:
+ // - add IP addresses from all downstream link properties
+ // - add routes from all non-tethering downstream link properties
+ // - remove any 64share prefixes
+ // - push this to the HAL
+ }
+
public void notifyDownstreamLinkProperties(LinkProperties lp) {
if (!started()) return;
diff --git a/services/core/java/com/android/server/connectivity/tethering/OffloadHardwareInterface.java b/services/core/java/com/android/server/connectivity/tethering/OffloadHardwareInterface.java
index 1fc1684..09fd96b 100644
--- a/services/core/java/com/android/server/connectivity/tethering/OffloadHardwareInterface.java
+++ b/services/core/java/com/android/server/connectivity/tethering/OffloadHardwareInterface.java
@@ -76,6 +76,10 @@
}
}
+ final String logmsg = String.format("initOffloadControl(%s)",
+ (controlCb == null) ? "null"
+ : "0x" + Integer.toHexString(System.identityHashCode(controlCb)));
+
mTetheringOffloadCallback = new TetheringOffloadCallback(mHandler, mControlCallback);
final CbResults results = new CbResults();
try {
@@ -86,11 +90,11 @@
results.errMsg = errMsg;
});
} catch (RemoteException e) {
- mLog.e("failed to initOffload: " + e);
+ record(logmsg, e);
return false;
}
- if (!results.success) mLog.e("initOffload failed: " + results.errMsg);
+ record(logmsg, results);
return results.success;
}
@@ -108,14 +112,18 @@
mOffloadControl = null;
mTetheringOffloadCallback = null;
mControlCallback = null;
+ mLog.log("stopOffloadControl()");
}
public boolean setUpstreamParameters(
String iface, String v4addr, String v4gateway, ArrayList<String> v6gws) {
- iface = iface != null ? iface : NO_INTERFACE_NAME;
- v4addr = v4addr != null ? v4addr : NO_IPV4_ADDRESS;
- v4gateway = v4gateway != null ? v4gateway : NO_IPV4_GATEWAY;
- v6gws = v6gws != null ? v6gws : new ArrayList<>();
+ iface = (iface != null) ? iface : NO_INTERFACE_NAME;
+ v4addr = (v4addr != null) ? v4addr : NO_IPV4_ADDRESS;
+ v4gateway = (v4gateway != null) ? v4gateway : NO_IPV4_GATEWAY;
+ v6gws = (v6gws != null) ? v6gws : new ArrayList<>();
+
+ final String logmsg = String.format("setUpstreamParameters(%s, %s, %s, [%s])",
+ iface, v4addr, v4gateway, String.join(",", v6gws));
final CbResults results = new CbResults();
try {
@@ -126,14 +134,27 @@
results.errMsg = errMsg;
});
} catch (RemoteException e) {
- mLog.e("failed to setUpstreamParameters: " + e);
+ record(logmsg, e);
return false;
}
- if (!results.success) mLog.e("setUpstreamParameters failed: " + results.errMsg);
+ record(logmsg, results);
return results.success;
}
+ private void record(String msg, Throwable t) {
+ mLog.e(msg + " -> exception: " + t);
+ }
+
+ private void record(String msg, CbResults results) {
+ final String logmsg = msg + " -> " + results;
+ if (!results.success) {
+ mLog.e(logmsg);
+ } else {
+ mLog.log(logmsg);
+ }
+ }
+
private static class TetheringOffloadCallback extends ITetheringOffloadCallback.Stub {
public final Handler handler;
public final ControlCallback controlCb;
@@ -162,5 +183,13 @@
private static class CbResults {
boolean success;
String errMsg;
+
+ public String toString() {
+ if (success) {
+ return "ok";
+ } else {
+ return "fail: " + errMsg;
+ }
+ }
}
}
diff --git a/services/core/java/com/android/server/connectivity/tethering/UpstreamNetworkMonitor.java b/services/core/java/com/android/server/connectivity/tethering/UpstreamNetworkMonitor.java
index 9ebfaf7..eb66767 100644
--- a/services/core/java/com/android/server/connectivity/tethering/UpstreamNetworkMonitor.java
+++ b/services/core/java/com/android/server/connectivity/tethering/UpstreamNetworkMonitor.java
@@ -26,18 +26,24 @@
import android.os.Looper;
import android.net.ConnectivityManager;
import android.net.ConnectivityManager.NetworkCallback;
+import android.net.IpPrefix;
+import android.net.LinkAddress;
import android.net.LinkProperties;
import android.net.Network;
import android.net.NetworkCapabilities;
import android.net.NetworkRequest;
import android.net.NetworkState;
+import android.net.util.NetworkConstants;
import android.net.util.SharedLog;
import android.util.Log;
import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.util.StateMachine;
+import java.util.Collections;
import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Set;
/**
@@ -66,10 +72,16 @@
private static final boolean DBG = false;
private static final boolean VDBG = false;
+ private static final IpPrefix[] MINIMUM_LOCAL_PREFIXES_SET = {
+ prefix("127.0.0.0/8"), prefix("169.254.0.0/16"),
+ prefix("::/3"), prefix("fe80::/64"), prefix("fc00::/7"), prefix("ff00::/8"),
+ };
+
public static final int EVENT_ON_AVAILABLE = 1;
public static final int EVENT_ON_CAPABILITIES = 2;
public static final int EVENT_ON_LINKPROPERTIES = 3;
public static final int EVENT_ON_LOST = 4;
+ public static final int NOTIFY_EXEMPT_PREFIXES = 10;
private static final int CALLBACK_LISTEN_ALL = 1;
private static final int CALLBACK_TRACK_DEFAULT = 2;
@@ -81,6 +93,7 @@
private final Handler mHandler;
private final int mWhat;
private final HashMap<Network, NetworkState> mNetworkMap = new HashMap<>();
+ private HashSet<IpPrefix> mOffloadExemptPrefixes;
private ConnectivityManager mCM;
private NetworkCallback mListenAllCallback;
private NetworkCallback mDefaultNetworkCallback;
@@ -88,18 +101,19 @@
private boolean mDunRequired;
private Network mCurrentDefault;
- public UpstreamNetworkMonitor(Context ctx, StateMachine tgt, int what, SharedLog log) {
+ public UpstreamNetworkMonitor(Context ctx, StateMachine tgt, SharedLog log, int what) {
mContext = ctx;
mTarget = tgt;
mHandler = mTarget.getHandler();
- mWhat = what;
mLog = log.forSubComponent(TAG);
+ mWhat = what;
+ mOffloadExemptPrefixes = allOffloadExemptPrefixes(mNetworkMap.values());
}
@VisibleForTesting
public UpstreamNetworkMonitor(
- StateMachine tgt, int what, ConnectivityManager cm, SharedLog log) {
- this(null, tgt, what, log);
+ ConnectivityManager cm, StateMachine tgt, SharedLog log, int what) {
+ this((Context) null, tgt, log, what);
mCM = cm;
}
@@ -209,6 +223,10 @@
return typeStatePair.ns;
}
+ public Set<IpPrefix> getOffloadExemptPrefixes() {
+ return (Set<IpPrefix>) mOffloadExemptPrefixes.clone();
+ }
+
private void handleAvailable(int callbackType, Network network) {
if (VDBG) Log.d(TAG, "EVENT_ON_AVAILABLE for " + network);
@@ -342,6 +360,14 @@
notifyTarget(EVENT_ON_LOST, mNetworkMap.remove(network));
}
+ private void recomputeOffloadExemptPrefixes() {
+ final HashSet<IpPrefix> exemptPrefixes = allOffloadExemptPrefixes(mNetworkMap.values());
+ if (!mOffloadExemptPrefixes.equals(exemptPrefixes)) {
+ mOffloadExemptPrefixes = exemptPrefixes;
+ notifyTarget(NOTIFY_EXEMPT_PREFIXES, exemptPrefixes.clone());
+ }
+ }
+
// Fetch (and cache) a ConnectivityManager only if and when we need one.
private ConnectivityManager cm() {
if (mCM == null) {
@@ -376,6 +402,7 @@
@Override
public void onLinkPropertiesChanged(Network network, LinkProperties newLp) {
handleLinkProp(network, newLp);
+ recomputeOffloadExemptPrefixes();
}
// TODO: Handle onNetworkSuspended();
@@ -384,6 +411,7 @@
@Override
public void onLost(Network network) {
handleLost(mCallbackType, network);
+ recomputeOffloadExemptPrefixes();
}
}
@@ -395,16 +423,16 @@
notifyTarget(which, mNetworkMap.get(network));
}
- private void notifyTarget(int which, NetworkState netstate) {
- mTarget.sendMessage(mWhat, which, 0, netstate);
+ private void notifyTarget(int which, Object obj) {
+ mTarget.sendMessage(mWhat, which, 0, obj);
}
- static private class TypeStatePair {
+ private static class TypeStatePair {
public int type = TYPE_NONE;
public NetworkState ns = null;
}
- static private TypeStatePair findFirstAvailableUpstreamByType(
+ private static TypeStatePair findFirstAvailableUpstreamByType(
Iterable<NetworkState> netStates, Iterable<Integer> preferredTypes) {
final TypeStatePair result = new TypeStatePair();
@@ -431,4 +459,36 @@
return result;
}
+
+ private static HashSet<IpPrefix> allOffloadExemptPrefixes(Iterable<NetworkState> netStates) {
+ final HashSet<IpPrefix> prefixSet = new HashSet<>();
+
+ addDefaultLocalPrefixes(prefixSet);
+
+ for (NetworkState ns : netStates) {
+ addOffloadExemptPrefixes(prefixSet, ns.linkProperties);
+ }
+
+ return prefixSet;
+ }
+
+ private static void addDefaultLocalPrefixes(Set<IpPrefix> prefixSet) {
+ Collections.addAll(prefixSet, MINIMUM_LOCAL_PREFIXES_SET);
+ }
+
+ private static void addOffloadExemptPrefixes(Set<IpPrefix> prefixSet, LinkProperties lp) {
+ if (lp == null) return;
+
+ for (LinkAddress linkAddr : lp.getAllLinkAddresses()) {
+ prefixSet.add(new IpPrefix(linkAddr.getAddress(), linkAddr.getPrefixLength()));
+ }
+
+ // TODO: Consider adding other non-default routes associated with this
+ // network. Traffic to these destinations should perhaps not go through
+ // the Internet (upstream).
+ }
+
+ private static IpPrefix prefix(String prefixStr) {
+ return new IpPrefix(prefixStr);
+ }
}
diff --git a/services/core/java/com/android/server/display/DisplayManagerService.java b/services/core/java/com/android/server/display/DisplayManagerService.java
index ab3aff9..8269042 100644
--- a/services/core/java/com/android/server/display/DisplayManagerService.java
+++ b/services/core/java/com/android/server/display/DisplayManagerService.java
@@ -132,7 +132,7 @@
private static final long WAIT_FOR_DEFAULT_DISPLAY_TIMEOUT = 10000;
- private static final int MSG_REGISTER_DEFAULT_DISPLAY_ADAPTER = 1;
+ private static final int MSG_REGISTER_DEFAULT_DISPLAY_ADAPTERS = 1;
private static final int MSG_REGISTER_ADDITIONAL_DISPLAY_ADAPTERS = 2;
private static final int MSG_DELIVER_DISPLAY_EVENT = 3;
private static final int MSG_REQUEST_TRAVERSAL = 4;
@@ -266,7 +266,6 @@
PowerManager pm = (PowerManager) mContext.getSystemService(Context.POWER_SERVICE);
mGlobalDisplayBrightness = pm.getDefaultScreenBrightnessSetting();
-
}
public void setupSchedulerPolicies() {
@@ -284,9 +283,9 @@
// We need to pre-load the persistent data store so it's ready before the default display
// adapter is up so that we have it's configuration. We could load it lazily, but since
// we're going to have to read it in eventually we may as well do it here rather than after
- // we've waited for the diplay to register itself with us.
+ // we've waited for the display to register itself with us.
mPersistentDataStore.loadIfNeeded();
- mHandler.sendEmptyMessage(MSG_REGISTER_DEFAULT_DISPLAY_ADAPTER);
+ mHandler.sendEmptyMessage(MSG_REGISTER_DEFAULT_DISPLAY_ADAPTERS);
publishBinderService(Context.DISPLAY_SERVICE, new BinderService(),
true /*allowIsolated*/);
@@ -298,12 +297,16 @@
public void onBootPhase(int phase) {
if (phase == PHASE_WAIT_FOR_DEFAULT_DISPLAY) {
synchronized (mSyncRoot) {
- long timeout = SystemClock.uptimeMillis() + WAIT_FOR_DEFAULT_DISPLAY_TIMEOUT;
- while (mLogicalDisplays.get(Display.DEFAULT_DISPLAY) == null) {
+ long timeout = SystemClock.uptimeMillis()
+ + mInjector.getDefaultDisplayDelayTimeout();
+ while (mLogicalDisplays.get(Display.DEFAULT_DISPLAY) == null ||
+ mVirtualDisplayAdapter == null) {
long delay = timeout - SystemClock.uptimeMillis();
if (delay <= 0) {
throw new RuntimeException("Timeout waiting for default display "
- + "to be initialized.");
+ + "to be initialized. DefaultDisplay="
+ + mLogicalDisplays.get(Display.DEFAULT_DISPLAY)
+ + ", mVirtualDisplayAdapter=" + mVirtualDisplayAdapter);
}
if (DEBUG) {
Slog.d(TAG, "waitForDefaultDisplay: waiting, timeout=" + delay);
@@ -685,11 +688,23 @@
}
}
- private void registerDefaultDisplayAdapter() {
- // Register default display adapter.
+ private void registerDefaultDisplayAdapters() {
+ // Register default display adapters.
synchronized (mSyncRoot) {
+ // main display adapter
registerDisplayAdapterLocked(new LocalDisplayAdapter(
mSyncRoot, mContext, mHandler, mDisplayAdapterListener));
+
+ // Standalone VR devices rely on a virtual display as their primary display for
+ // 2D UI. We register virtual display adapter along side the main display adapter
+ // here so that it is ready by the time the system sends the home Intent for
+ // early apps like SetupWizard/Launcher. In particular, SUW is displayed using
+ // the virtual display inside VR before any VR-specific apps even run.
+ mVirtualDisplayAdapter = mInjector.getVirtualDisplayAdapter(mSyncRoot, mContext,
+ mHandler, mDisplayAdapterListener);
+ if (mVirtualDisplayAdapter != null) {
+ registerDisplayAdapterLocked(mVirtualDisplayAdapter);
+ }
}
}
@@ -698,7 +713,6 @@
if (shouldRegisterNonEssentialDisplayAdaptersLocked()) {
registerOverlayDisplayAdapterLocked();
registerWifiDisplayAdapterLocked();
- registerVirtualDisplayAdapterLocked();
}
}
}
@@ -719,12 +733,6 @@
}
}
- private void registerVirtualDisplayAdapterLocked() {
- mVirtualDisplayAdapter = mInjector.getVirtualDisplayAdapter(mSyncRoot, mContext, mHandler,
- mDisplayAdapterListener);
- registerDisplayAdapterLocked(mVirtualDisplayAdapter);
- }
-
private boolean shouldRegisterNonEssentialDisplayAdaptersLocked() {
// In safe mode, we disable non-essential display adapters to give the user
// an opportunity to fix broken settings or other problems that might affect
@@ -1219,6 +1227,10 @@
Handler handler, DisplayAdapter.Listener displayAdapterListener) {
return new VirtualDisplayAdapter(syncRoot, context, handler, displayAdapterListener);
}
+
+ long getDefaultDisplayDelayTimeout() {
+ return WAIT_FOR_DEFAULT_DISPLAY_TIMEOUT;
+ }
}
@VisibleForTesting
@@ -1241,8 +1253,8 @@
@Override
public void handleMessage(Message msg) {
switch (msg.what) {
- case MSG_REGISTER_DEFAULT_DISPLAY_ADAPTER:
- registerDefaultDisplayAdapter();
+ case MSG_REGISTER_DEFAULT_DISPLAY_ADAPTERS:
+ registerDefaultDisplayAdapters();
break;
case MSG_REGISTER_ADDITIONAL_DISPLAY_ADAPTERS:
diff --git a/services/core/java/com/android/server/job/JobPackageTracker.java b/services/core/java/com/android/server/job/JobPackageTracker.java
index ba92295..025ff0b 100644
--- a/services/core/java/com/android/server/job/JobPackageTracker.java
+++ b/services/core/java/com/android/server/job/JobPackageTracker.java
@@ -17,11 +17,13 @@
package com.android.server.job;
import android.app.job.JobInfo;
+import android.app.job.JobParameters;
import android.os.SystemClock;
import android.os.UserHandle;
import android.text.format.DateFormat;
import android.util.ArrayMap;
import android.util.SparseArray;
+import android.util.SparseIntArray;
import android.util.TimeUtils;
import com.android.internal.util.RingBufferIndices;
import com.android.server.job.controllers.JobStatus;
@@ -36,6 +38,9 @@
private static final int EVENT_BUFFER_SIZE = 100;
+ public static final int EVENT_CMD_MASK = 0xff;
+ public static final int EVENT_STOP_REASON_SHIFT = 8;
+ public static final int EVENT_STOP_REASON_MASK = 0xff << EVENT_STOP_REASON_SHIFT;
public static final int EVENT_NULL = 0;
public static final int EVENT_START_JOB = 1;
public static final int EVENT_STOP_JOB = 2;
@@ -49,9 +54,9 @@
private final String[] mEventTags = new String[EVENT_BUFFER_SIZE];
private final int[] mEventJobIds = new int[EVENT_BUFFER_SIZE];
- public void addEvent(int cmd, int uid, String tag, int jobId) {
+ public void addEvent(int cmd, int uid, String tag, int jobId, int stopReason) {
int index = mEventIndices.add();
- mEventCmds[index] = cmd;
+ mEventCmds[index] = cmd | ((stopReason<<EVENT_STOP_REASON_SHIFT) & EVENT_STOP_REASON_MASK);
mEventTimes[index] = SystemClock.elapsedRealtime();
mEventUids[index] = uid;
mEventTags[index] = tag;
@@ -77,6 +82,7 @@
int pendingNesting;
int pendingCount;
boolean hadPending;
+ final SparseIntArray stopReasons = new SparseIntArray();
public long getActiveTime(long now) {
long time = pastActiveTime;
@@ -179,12 +185,14 @@
pe.activeNesting++;
}
- void decActive(int uid, String pkg, long now) {
+ void decActive(int uid, String pkg, long now, int stopReason) {
PackageEntry pe = getOrCreateEntry(uid, pkg);
if (pe.activeNesting == 1) {
pe.pastActiveTime += now - pe.activeStartTime;
}
pe.activeNesting--;
+ int count = pe.stopReasons.get(stopReason, 0);
+ pe.stopReasons.put(stopReason, count+1);
}
void incActiveTop(int uid, String pkg, long now) {
@@ -196,12 +204,14 @@
pe.activeTopNesting++;
}
- void decActiveTop(int uid, String pkg, long now) {
+ void decActiveTop(int uid, String pkg, long now, int stopReason) {
PackageEntry pe = getOrCreateEntry(uid, pkg);
if (pe.activeTopNesting == 1) {
pe.pastActiveTopTime += now - pe.activeTopStartTime;
}
pe.activeTopNesting--;
+ int count = pe.stopReasons.get(stopReason, 0);
+ pe.stopReasons.put(stopReason, count+1);
}
void finish(DataSet next, long now) {
@@ -261,6 +271,11 @@
outPe.pastPendingTime += now - pe.pendingStartTime;
outPe.hadPending = true;
}
+ for (int k = pe.stopReasons.size()-1; k >= 0; k--) {
+ int type = pe.stopReasons.keyAt(k);
+ outPe.stopReasons.put(type, outPe.stopReasons.get(type, 0)
+ + pe.stopReasons.valueAt(k));
+ }
}
}
if (mMaxTotalActive > out.mMaxTotalActive) {
@@ -312,7 +327,8 @@
pw.print(prefix); pw.print(" ");
UserHandle.formatUid(pw, uid);
pw.print(" / "); pw.print(uidMap.keyAt(j));
- pw.print(":");
+ pw.println(":");
+ pw.print(prefix); pw.print(" ");
printDuration(pw, period, pe.getPendingTime(now), pe.pendingCount, "pending");
printDuration(pw, period, pe.getActiveTime(now), pe.activeCount, "active");
printDuration(pw, period, pe.getActiveTopTime(now), pe.activeTopCount,
@@ -327,6 +343,18 @@
pw.print(" (active-top)");
}
pw.println();
+ if (pe.stopReasons.size() > 0) {
+ pw.print(prefix); pw.print(" ");
+ for (int k = 0; k < pe.stopReasons.size(); k++) {
+ if (k > 0) {
+ pw.print(", ");
+ }
+ pw.print(pe.stopReasons.valueAt(k));
+ pw.print("x ");
+ pw.print(JobParameters.getReasonName(pe.stopReasons.keyAt(k)));
+ }
+ pw.println();
+ }
}
}
pw.print(prefix); pw.print(" Max concurrency: ");
@@ -370,19 +398,20 @@
mCurDataSet.incActive(job.getSourceUid(), job.getSourcePackageName(), now);
}
addEvent(job.getJob().isPeriodic() ? EVENT_START_PERIODIC_JOB : EVENT_START_JOB,
- job.getSourceUid(), job.getBatteryName(), job.getJobId());
+ job.getSourceUid(), job.getBatteryName(), job.getJobId(), 0);
}
- public void noteInactive(JobStatus job) {
+ public void noteInactive(JobStatus job, int stopReason) {
final long now = SystemClock.uptimeMillis();
if (job.lastEvaluatedPriority >= JobInfo.PRIORITY_TOP_APP) {
- mCurDataSet.decActiveTop(job.getSourceUid(), job.getSourcePackageName(), now);
+ mCurDataSet.decActiveTop(job.getSourceUid(), job.getSourcePackageName(), now,
+ stopReason);
} else {
- mCurDataSet.decActive(job.getSourceUid(), job.getSourcePackageName(), now);
+ mCurDataSet.decActive(job.getSourceUid(), job.getSourcePackageName(), now, stopReason);
}
rebatchIfNeeded(now);
addEvent(job.getJob().isPeriodic() ? EVENT_STOP_JOB : EVENT_STOP_PERIODIC_JOB,
- job.getSourceUid(), job.getBatteryName(), job.getJobId());
+ job.getSourceUid(), job.getBatteryName(), job.getJobId(), stopReason);
}
public void noteConcurrency(int totalActive, int fgActive) {
@@ -448,12 +477,12 @@
if (filterUid != -1 && filterUid != UserHandle.getAppId(uid)) {
continue;
}
- final int cmd = mEventCmds[index];
+ final int cmd = mEventCmds[index] & EVENT_CMD_MASK;
if (cmd == EVENT_NULL) {
continue;
}
final String label;
- switch (mEventCmds[index]) {
+ switch (cmd) {
case EVENT_START_JOB: label = " START"; break;
case EVENT_STOP_JOB: label = " STOP"; break;
case EVENT_START_PERIODIC_JOB: label = "START-P"; break;
@@ -469,7 +498,13 @@
pw.print("/");
pw.print(mEventJobIds[index]);
pw.print(" ");
- pw.println(mEventTags[index]);
+ pw.print(mEventTags[index]);
+ if (cmd == EVENT_STOP_JOB || cmd == EVENT_STOP_PERIODIC_JOB) {
+ pw.print(" ");
+ pw.print(JobParameters.getReasonName((mEventCmds[index] & EVENT_STOP_REASON_MASK)
+ >> EVENT_STOP_REASON_SHIFT));
+ }
+ pw.println();
}
return true;
}
diff --git a/services/core/java/com/android/server/job/JobSchedulerService.java b/services/core/java/com/android/server/job/JobSchedulerService.java
index 98c65fd..3fea51f 100644
--- a/services/core/java/com/android/server/job/JobSchedulerService.java
+++ b/services/core/java/com/android/server/job/JobSchedulerService.java
@@ -2052,7 +2052,15 @@
synchronized (mLock) {
boolean foundSome = false;
for (int i=0; i<mActiveServices.size(); i++) {
- mActiveServices.get(i).timeoutIfExecutingLocked(pkgName, userId, hasJobId, jobId);
+ final JobServiceContext jc = mActiveServices.get(i);
+ final JobStatus js = jc.getRunningJobLocked();
+ if (jc.timeoutIfExecutingLocked(pkgName, userId, hasJobId, jobId)) {
+ foundSome = true;
+ pw.print("Timing out: ");
+ js.printUniqueId(pw);
+ pw.print(" ");
+ pw.println(js.getServiceComponent().flattenToShortString());
+ }
}
if (!foundSome) {
pw.println("No matching executing jobs found.");
diff --git a/services/core/java/com/android/server/job/JobServiceContext.java b/services/core/java/com/android/server/job/JobServiceContext.java
index 107475f..a34e251 100644
--- a/services/core/java/com/android/server/job/JobServiceContext.java
+++ b/services/core/java/com/android/server/job/JobServiceContext.java
@@ -681,6 +681,7 @@
return;
}
try {
+ applyStoppedReasonLocked(reason);
mVerb = VERB_STOPPING;
scheduleOpTimeOutLocked();
service.stopJob(mParams);
@@ -704,10 +705,10 @@
}
applyStoppedReasonLocked(reason);
completedJob = mRunningJob;
- mJobPackageTracker.noteInactive(completedJob);
+ mJobPackageTracker.noteInactive(completedJob, mParams.getStopReason());
try {
mBatteryStats.noteJobFinish(mRunningJob.getBatteryName(),
- mRunningJob.getSourceUid());
+ mRunningJob.getSourceUid(), mParams.getStopReason());
} catch (RemoteException e) {
// Whatever.
}
diff --git a/services/core/java/com/android/server/policy/ImmersiveModeConfirmation.java b/services/core/java/com/android/server/policy/ImmersiveModeConfirmation.java
index ebb9450..c6ec287 100644
--- a/services/core/java/com/android/server/policy/ImmersiveModeConfirmation.java
+++ b/services/core/java/com/android/server/policy/ImmersiveModeConfirmation.java
@@ -19,6 +19,7 @@
import android.animation.ArgbEvaluator;
import android.animation.ValueAnimator;
import android.app.ActivityManager;
+import android.app.ActivityThread;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
@@ -79,7 +80,7 @@
boolean mVrModeEnabled = false;
public ImmersiveModeConfirmation(Context context) {
- mContext = context;
+ mContext = ActivityThread.currentActivityThread().getSystemUiContext();
mHandler = new H();
mShowDelayMs = getNavBarExitDuration() * 3;
mPanicThresholdMs = context.getResources()
diff --git a/services/core/java/com/android/server/power/ShutdownThread.java b/services/core/java/com/android/server/power/ShutdownThread.java
index 02f2afc..56612ad 100644
--- a/services/core/java/com/android/server/power/ShutdownThread.java
+++ b/services/core/java/com/android/server/power/ShutdownThread.java
@@ -23,14 +23,17 @@
import android.app.ProgressDialog;
import android.bluetooth.BluetoothAdapter;
import android.bluetooth.IBluetoothManager;
-import android.media.AudioAttributes;
-import android.nfc.NfcAdapter;
-import android.nfc.INfcAdapter;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.IntentFilter;
+import android.content.om.IOverlayManager;
+import android.graphics.Color;
+import android.graphics.drawable.ColorDrawable;
+import android.media.AudioAttributes;
+import android.nfc.INfcAdapter;
+import android.nfc.NfcAdapter;
import android.os.FileUtils;
import android.os.Handler;
import android.os.PowerManager;
@@ -39,24 +42,21 @@
import android.os.ServiceManager;
import android.os.SystemClock;
import android.os.SystemProperties;
+import android.os.SystemVibrator;
import android.os.UserHandle;
import android.os.UserManager;
import android.os.Vibrator;
-import android.os.SystemVibrator;
-import android.os.storage.IStorageShutdownObserver;
import android.os.storage.IStorageManager;
-import android.system.ErrnoException;
-import android.system.Os;
-
+import android.os.storage.IStorageShutdownObserver;
+import android.util.Log;
+import android.view.ViewGroup;
+import android.view.WindowManager;
+import android.widget.ProgressBar;
+import android.widget.TextView;
import com.android.internal.telephony.ITelephony;
import com.android.server.pm.PackageManagerService;
-import android.util.Log;
-import android.view.WindowManager;
-
-import java.io.BufferedReader;
import java.io.File;
-import java.io.FileReader;
import java.io.IOException;
public final class ShutdownThread extends Thread {
@@ -243,15 +243,7 @@
shutdownInner(context, confirm);
}
- private static void beginShutdownSequence(Context context) {
- synchronized (sIsStartedGuard) {
- if (sIsStarted) {
- Log.d(TAG, "Shutdown sequence already running, returning.");
- return;
- }
- sIsStarted = true;
- }
-
+ private static ProgressDialog showShutdownDialog(Context context) {
// Throw up a system dialog to indicate the device is rebooting / shutting down.
ProgressDialog pd = new ProgressDialog(context);
@@ -303,6 +295,32 @@
pd.setMessage(context.getText(
com.android.internal.R.string.reboot_to_reset_message));
pd.setIndeterminate(true);
+ } else if (mReason != null && mReason.equals(PowerManager.SHUTDOWN_USER_REQUESTED)) {
+ Dialog d = new Dialog(context);
+ d.setContentView(com.android.internal.R.layout.shutdown_dialog);
+ d.setCancelable(false);
+
+ int color = Color.WHITE;
+ try {
+ IOverlayManager service = IOverlayManager.Stub.asInterface(
+ ServiceManager.getService(Context.OVERLAY_SERVICE));
+ if (service.getOverlayInfo("com.android.systemui.theme.lightwallpaper", 0).isEnabled()) {
+ color = Color.BLACK;
+ }
+ } catch (Exception e) {
+ // Shutdown UI really shouldn't crash or have strict dependencies on other services.
+ Log.w(TAG, "Problem getting overlay state", e);
+ }
+ ProgressBar bar = d.findViewById(com.android.internal.R.id.progress);
+ bar.getIndeterminateDrawable().setTint(color);
+ ((TextView) d.findViewById(com.android.internal.R.id.text1)).setTextColor(color);
+ d.getWindow().getAttributes().width = ViewGroup.LayoutParams.MATCH_PARENT;
+ d.getWindow().getAttributes().height = ViewGroup.LayoutParams.MATCH_PARENT;
+ d.getWindow().setType(WindowManager.LayoutParams.TYPE_VOLUME_OVERLAY);
+ d.getWindow().clearFlags(WindowManager.LayoutParams.FLAG_DIM_BEHIND);
+ d.getWindow().setBackgroundDrawable(new ColorDrawable(Color.TRANSPARENT));
+ d.show();
+ return null;
} else {
pd.setTitle(context.getText(com.android.internal.R.string.power_off));
pd.setMessage(context.getText(com.android.internal.R.string.shutdown_progress));
@@ -312,8 +330,19 @@
pd.getWindow().setType(WindowManager.LayoutParams.TYPE_KEYGUARD_DIALOG);
pd.show();
+ return pd;
+ }
- sInstance.mProgressDialog = pd;
+ private static void beginShutdownSequence(Context context) {
+ synchronized (sIsStartedGuard) {
+ if (sIsStarted) {
+ Log.d(TAG, "Shutdown sequence already running, returning.");
+ return;
+ }
+ sIsStarted = true;
+ }
+
+ sInstance.mProgressDialog = showShutdownDialog(context);
sInstance.mContext = context;
sInstance.mPowerManager = (PowerManager)context.getSystemService(Context.POWER_SERVICE);
diff --git a/services/core/java/com/android/server/timezone/PackageStatusStorage.java b/services/core/java/com/android/server/timezone/PackageStatusStorage.java
index 05e97c7..fe82dc4 100644
--- a/services/core/java/com/android/server/timezone/PackageStatusStorage.java
+++ b/services/core/java/com/android/server/timezone/PackageStatusStorage.java
@@ -32,6 +32,7 @@
import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.text.ParseException;
+import java.io.PrintWriter;
import static com.android.server.timezone.PackageStatus.CHECK_COMPLETED_FAILURE;
import static com.android.server.timezone.PackageStatus.CHECK_COMPLETED_SUCCESS;
@@ -375,4 +376,8 @@
}
return value;
}
+
+ public void dump(PrintWriter printWriter) {
+ printWriter.println("Package status: " + getPackageStatus());
+ }
}
diff --git a/services/core/java/com/android/server/timezone/PackageTracker.java b/services/core/java/com/android/server/timezone/PackageTracker.java
index f9af2ea..e8dfd77 100644
--- a/services/core/java/com/android/server/timezone/PackageTracker.java
+++ b/services/core/java/com/android/server/timezone/PackageTracker.java
@@ -26,6 +26,7 @@
import android.util.Slog;
import java.io.File;
+import java.io.PrintWriter;
/**
* Monitors the installed applications associated with time zone updates. If the app packages are
@@ -510,4 +511,23 @@
Slog.wtf(TAG, message, cause);
throw new RuntimeException(message, cause);
}
+
+ public void dump(PrintWriter fout) {
+ fout.println("PackageTrackerState: " + toString());
+ mPackageStatusStorage.dump(fout);
+ }
+
+ @Override
+ public String toString() {
+ return "PackageTracker{" +
+ "mTrackingEnabled=" + mTrackingEnabled +
+ ", mUpdateAppPackageName='" + mUpdateAppPackageName + '\'' +
+ ", mDataAppPackageName='" + mDataAppPackageName + '\'' +
+ ", mCheckTimeAllowedMillis=" + mCheckTimeAllowedMillis +
+ ", mFailedCheckRetryCount=" + mFailedCheckRetryCount +
+ ", mLastTriggerTimestamp=" + mLastTriggerTimestamp +
+ ", mCheckTriggered=" + mCheckTriggered +
+ ", mCheckFailureCount=" + mCheckFailureCount +
+ '}';
+ }
}
diff --git a/services/core/java/com/android/server/timezone/PermissionHelper.java b/services/core/java/com/android/server/timezone/PermissionHelper.java
index ba91c7f..2ec31e2 100644
--- a/services/core/java/com/android/server/timezone/PermissionHelper.java
+++ b/services/core/java/com/android/server/timezone/PermissionHelper.java
@@ -16,10 +16,14 @@
package com.android.server.timezone;
+import java.io.PrintWriter;
+
/**
* An easy-to-mock interface around permission checks for use by {@link RulesManagerService}.
*/
public interface PermissionHelper {
void enforceCallerHasPermission(String requiredPermission) throws SecurityException;
+
+ boolean checkDumpPermission(String tag, PrintWriter printWriter);
}
diff --git a/services/core/java/com/android/server/timezone/RulesManagerService.java b/services/core/java/com/android/server/timezone/RulesManagerService.java
index 5724398..3d60dcf6 100644
--- a/services/core/java/com/android/server/timezone/RulesManagerService.java
+++ b/services/core/java/com/android/server/timezone/RulesManagerService.java
@@ -37,12 +37,24 @@
import android.util.Slog;
import java.io.File;
+import java.io.FileDescriptor;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
+import java.io.PrintWriter;
import java.util.Arrays;
import java.util.concurrent.Executor;
import java.util.concurrent.atomic.AtomicBoolean;
+import libcore.icu.ICU;
+import libcore.util.ZoneInfoDB;
+
+import static android.app.timezone.RulesState.DISTRO_STATUS_INSTALLED;
+import static android.app.timezone.RulesState.DISTRO_STATUS_NONE;
+import static android.app.timezone.RulesState.DISTRO_STATUS_UNKNOWN;
+import static android.app.timezone.RulesState.STAGED_OPERATION_INSTALL;
+import static android.app.timezone.RulesState.STAGED_OPERATION_NONE;
+import static android.app.timezone.RulesState.STAGED_OPERATION_UNINSTALL;
+import static android.app.timezone.RulesState.STAGED_OPERATION_UNKNOWN;
// TODO(nfuller) Add EventLog calls where useful in the system server.
// TODO(nfuller) Check logging best practices in the system server.
@@ -113,6 +125,11 @@
public RulesState getRulesState() {
mPermissionHelper.enforceCallerHasPermission(REQUIRED_UPDATER_PERMISSION);
+ return getRulesStateInternal();
+ }
+
+ /** Like {@link #getRulesState()} without the permission check. */
+ private RulesState getRulesStateInternal() {
synchronized(this) {
String systemRulesVersion;
try {
@@ -126,18 +143,18 @@
// Determine the staged operation status, if possible.
DistroRulesVersion stagedDistroRulesVersion = null;
- int stagedOperationStatus = RulesState.STAGED_OPERATION_UNKNOWN;
+ int stagedOperationStatus = STAGED_OPERATION_UNKNOWN;
if (!operationInProgress) {
StagedDistroOperation stagedDistroOperation;
try {
stagedDistroOperation = mInstaller.getStagedDistroOperation();
if (stagedDistroOperation == null) {
- stagedOperationStatus = RulesState.STAGED_OPERATION_NONE;
+ stagedOperationStatus = STAGED_OPERATION_NONE;
} else if (stagedDistroOperation.isUninstall) {
- stagedOperationStatus = RulesState.STAGED_OPERATION_UNINSTALL;
+ stagedOperationStatus = STAGED_OPERATION_UNINSTALL;
} else {
// Must be an install.
- stagedOperationStatus = RulesState.STAGED_OPERATION_INSTALL;
+ stagedOperationStatus = STAGED_OPERATION_INSTALL;
DistroVersion stagedDistroVersion = stagedDistroOperation.distroVersion;
stagedDistroRulesVersion = new DistroRulesVersion(
stagedDistroVersion.rulesVersion,
@@ -150,16 +167,16 @@
// Determine the installed distro state, if possible.
DistroVersion installedDistroVersion;
- int distroStatus = RulesState.DISTRO_STATUS_UNKNOWN;
+ int distroStatus = DISTRO_STATUS_UNKNOWN;
DistroRulesVersion installedDistroRulesVersion = null;
if (!operationInProgress) {
try {
installedDistroVersion = mInstaller.getInstalledDistroVersion();
if (installedDistroVersion == null) {
- distroStatus = RulesState.DISTRO_STATUS_NONE;
+ distroStatus = DISTRO_STATUS_NONE;
installedDistroRulesVersion = null;
} else {
- distroStatus = RulesState.DISTRO_STATUS_INSTALLED;
+ distroStatus = DISTRO_STATUS_INSTALLED;
installedDistroRulesVersion = new DistroRulesVersion(
installedDistroVersion.rulesVersion,
installedDistroVersion.revision);
@@ -358,6 +375,87 @@
mPackageTracker.recordCheckResult(checkToken, success);
}
+ @Override
+ protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
+ if (!mPermissionHelper.checkDumpPermission(TAG, pw)) {
+ return;
+ }
+
+ RulesState rulesState = getRulesStateInternal();
+ if (args != null && args.length == 2) {
+ // Formatting options used for automated tests. The format is less free-form than
+ // the -format options, which are intended to be easier to parse.
+ if ("-format_state".equals(args[0]) && args[1] != null) {
+ for (char c : args[1].toCharArray()) {
+ switch (c) {
+ case 'p': // Report operation in progress
+ pw.println("Operation in progress: "
+ + rulesState.isOperationInProgress());
+ break;
+ case 's': // Report system image rules version
+ pw.println("System rules version: "
+ + rulesState.getSystemRulesVersion());
+ break;
+ case 'c': // Report current installation state
+ pw.println("Current install state: "
+ + distroStatusToString(rulesState.getDistroStatus()));
+ break;
+ case 'i': // Report currently installed version
+ DistroRulesVersion installedRulesVersion =
+ rulesState.getInstalledDistroRulesVersion();
+ pw.print("Installed rules version: ");
+ if (installedRulesVersion == null) {
+ pw.println("<None>");
+ } else {
+ pw.println(installedRulesVersion.toDumpString());
+ }
+ break;
+ case 'o': // Report staged operation type
+ int stagedOperationType = rulesState.getStagedOperationType();
+ pw.println("Staged operation: "
+ + stagedOperationToString(stagedOperationType));
+ break;
+ case 't':
+ // Report staged version (i.e. the one that will be installed next boot
+ // if the staged operation is an install).
+ pw.print("Staged rules version: ");
+ DistroRulesVersion stagedDistroRulesVersion =
+ rulesState.getStagedDistroRulesVersion();
+ if (stagedDistroRulesVersion == null) {
+ pw.println("<None>");
+ } else {
+ pw.println("Staged install version: "
+ + stagedDistroRulesVersion.toDumpString());
+ }
+ break;
+ case 'a':
+ // Report the active rules version (i.e. the rules in use by the current
+ // process).
+ pw.println("Active rules version (ICU, libcore): "
+ + ICU.getTZDataVersion() + ","
+ + ZoneInfoDB.getInstance().getVersion());
+ break;
+ default:
+ pw.println("Unknown option: " + c);
+ }
+ }
+ return;
+ }
+ }
+
+ pw.println("RulesManagerService state: " + toString());
+ pw.println("Active rules version (ICU, libcore): " + ICU.getTZDataVersion() + ","
+ + ZoneInfoDB.getInstance().getVersion());
+ mPackageTracker.dump(pw);
+ }
+
+ @Override
+ public String toString() {
+ return "RulesManagerService{" +
+ "mOperationInProgress=" + mOperationInProgress +
+ '}';
+ }
+
private static CheckToken createCheckTokenOrThrow(byte[] checkTokenBytes) {
CheckToken checkToken;
try {
@@ -368,4 +466,30 @@
}
return checkToken;
}
+
+ private static String distroStatusToString(int distroStatus) {
+ switch(distroStatus) {
+ case DISTRO_STATUS_NONE:
+ return "None";
+ case DISTRO_STATUS_INSTALLED:
+ return "Installed";
+ case DISTRO_STATUS_UNKNOWN:
+ default:
+ return "Unknown";
+ }
+ }
+
+ private static String stagedOperationToString(int stagedOperationType) {
+ switch(stagedOperationType) {
+ case STAGED_OPERATION_NONE:
+ return "None";
+ case STAGED_OPERATION_UNINSTALL:
+ return "Uninstall";
+ case STAGED_OPERATION_INSTALL:
+ return "Install";
+ case STAGED_OPERATION_UNKNOWN:
+ default:
+ return "Unknown";
+ }
+ }
}
diff --git a/services/core/java/com/android/server/timezone/RulesManagerServiceHelperImpl.java b/services/core/java/com/android/server/timezone/RulesManagerServiceHelperImpl.java
index 482d8e2..767f0e0 100644
--- a/services/core/java/com/android/server/timezone/RulesManagerServiceHelperImpl.java
+++ b/services/core/java/com/android/server/timezone/RulesManagerServiceHelperImpl.java
@@ -17,10 +17,13 @@
package com.android.server.timezone;
import android.content.Context;
+import android.content.pm.PackageManager;
+import android.os.Binder;
import android.os.ParcelFileDescriptor;
import java.io.FileInputStream;
import java.io.IOException;
+import java.io.PrintWriter;
import java.util.concurrent.Executor;
import libcore.io.Streams;
@@ -40,6 +43,19 @@
mContext.enforceCallingPermission(requiredPermission, null /* message */);
}
+ @Override
+ public boolean checkDumpPermission(String tag, PrintWriter pw) {
+ // TODO(nfuller): Switch to DumpUtils.checkDumpPermission() when it is available in AOSP.
+ if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.DUMP)
+ != PackageManager.PERMISSION_GRANTED) {
+ pw.println("Permission Denial: can't dump LocationManagerService from from pid="
+ + Binder.getCallingPid()
+ + ", uid=" + Binder.getCallingUid());
+ return false;
+ }
+ return true;
+ }
+
// TODO Wake lock required?
@Override
public void execute(Runnable runnable) {
diff --git a/services/core/java/com/android/server/trust/TrustManagerService.java b/services/core/java/com/android/server/trust/TrustManagerService.java
index c07bd8e..a7cd962 100644
--- a/services/core/java/com/android/server/trust/TrustManagerService.java
+++ b/services/core/java/com/android/server/trust/TrustManagerService.java
@@ -67,7 +67,6 @@
import java.io.IOException;
import java.io.PrintWriter;
import java.util.ArrayList;
-import java.util.Collections;
import java.util.List;
import org.xmlpull.v1.XmlPullParser;
import org.xmlpull.v1.XmlPullParserException;
@@ -589,22 +588,20 @@
}
private void maybeEnableFactoryTrustAgents(LockPatternUtils utils, int userId) {
+ if (0 != Settings.Secure.getIntForUser(mContext.getContentResolver(),
+ Settings.Secure.TRUST_AGENTS_INITIALIZED, 0, userId)) {
+ return;
+ }
+ PackageManager pm = mContext.getPackageManager();
+ List<ResolveInfo> resolveInfos = resolveAllowedTrustAgents(pm, userId);
ComponentName defaultAgent = getDefaultFactoryTrustAgent(mContext);
boolean shouldUseDefaultAgent = defaultAgent != null;
+ ArraySet<ComponentName> discoveredAgents = new ArraySet<>();
if (shouldUseDefaultAgent) {
+ discoveredAgents.add(defaultAgent);
Log.i(TAG, "Enabling " + defaultAgent + " because it is a default agent.");
- utils.setEnabledTrustAgents(Collections.singleton(defaultAgent), userId);
} else { // A default agent is not set; perform regular trust agent discovery
- if (0 != Settings.Secure.getIntForUser(mContext.getContentResolver(),
- Settings.Secure.TRUST_AGENTS_INITIALIZED, 0, userId)) {
- return;
- }
- PackageManager pm = mContext.getPackageManager();
- List<ResolveInfo> resolveInfos = resolveAllowedTrustAgents(pm, userId);
-
- ArraySet<ComponentName> discoveredAgents = new ArraySet<>();
-
for (ResolveInfo resolveInfo : resolveInfos) {
ComponentName componentName = getComponentName(resolveInfo);
int applicationInfoFlags = resolveInfo.serviceInfo.applicationInfo.flags;
@@ -615,13 +612,13 @@
}
discoveredAgents.add(componentName);
}
-
- List<ComponentName> previouslyEnabledAgents = utils.getEnabledTrustAgents(userId);
- if (previouslyEnabledAgents != null) {
- discoveredAgents.addAll(previouslyEnabledAgents);
- }
- utils.setEnabledTrustAgents(discoveredAgents, userId);
}
+
+ List<ComponentName> previouslyEnabledAgents = utils.getEnabledTrustAgents(userId);
+ if (previouslyEnabledAgents != null) {
+ discoveredAgents.addAll(previouslyEnabledAgents);
+ }
+ utils.setEnabledTrustAgents(discoveredAgents, userId);
Settings.Secure.putIntForUser(mContext.getContentResolver(),
Settings.Secure.TRUST_AGENTS_INITIALIZED, 1, userId);
}
diff --git a/services/core/java/com/android/server/vr/Vr2dDisplay.java b/services/core/java/com/android/server/vr/Vr2dDisplay.java
index fa98f17..b1c1df1 100644
--- a/services/core/java/com/android/server/vr/Vr2dDisplay.java
+++ b/services/core/java/com/android/server/vr/Vr2dDisplay.java
@@ -35,7 +35,6 @@
private final static String TAG = "Vr2dDisplay";
private final static boolean DEBUG = false;
- // TODO: Go over these values and figure out what is best
private int mVirtualDisplayHeight;
private int mVirtualDisplayWidth;
private int mVirtualDisplayDpi;
@@ -55,17 +54,17 @@
/**
* The default width of the VR virtual display
*/
- public static final int DEFAULT_VR_DISPLAY_WIDTH = 1400;
+ public static final int DEFAULT_VIRTUAL_DISPLAY_WIDTH = 1400;
/**
* The default height of the VR virtual display
*/
- public static final int DEFAULT_VR_DISPLAY_HEIGHT = 1800;
+ public static final int DEFAULT_VIRTUAL_DISPLAY_HEIGHT = 1400;
/**
* The default height of the VR virtual dpi.
*/
- public static final int DEFAULT_VR_DISPLAY_DPI = 320;
+ public static final int DEFAULT_VIRTUAL_DISPLAY_DPI = 320;
/**
* The minimum height, width and dpi of VR virtual display.
@@ -87,8 +86,8 @@
new IPersistentVrStateCallbacks.Stub() {
@Override
public void onPersistentVrStateChanged(boolean enabled) {
- if (enabled != mIsVrModeEnabled) {
- mIsVrModeEnabled = enabled;
+ if (enabled != mIsPersistentVrModeEnabled) {
+ mIsPersistentVrModeEnabled = enabled;
updateVirtualDisplay();
}
}
@@ -98,26 +97,33 @@
private Surface mSurface;
private ImageReader mImageReader;
private Runnable mStopVDRunnable;
- private boolean mIsVrModeOverrideEnabled;
- private boolean mIsVrModeEnabled;
- private boolean mIsVirtualDisplayAllowed = true;
+ private boolean mIsVrModeOverrideEnabled; // debug override to set vr mode.
+ private boolean mIsVirtualDisplayAllowed = true; // Virtual-display feature toggle
+ private boolean mIsPersistentVrModeEnabled; // indicates we are in vr persistent mode.
+ private boolean mBootsToVr = false; // The device boots into VR (standalone VR device)
public Vr2dDisplay(DisplayManager displayManager,
ActivityManagerInternal activityManagerInternal, IVrManager vrManager) {
mDisplayManager = displayManager;
mActivityManagerInternal = activityManagerInternal;
mVrManager = vrManager;
- mVirtualDisplayWidth = DEFAULT_VR_DISPLAY_WIDTH;
- mVirtualDisplayHeight = DEFAULT_VR_DISPLAY_HEIGHT;
- mVirtualDisplayDpi = DEFAULT_VR_DISPLAY_DPI;
+ mVirtualDisplayWidth = DEFAULT_VIRTUAL_DISPLAY_WIDTH;
+ mVirtualDisplayHeight = DEFAULT_VIRTUAL_DISPLAY_HEIGHT;
+ mVirtualDisplayDpi = DEFAULT_VIRTUAL_DISPLAY_DPI;
}
/**
* Initializes the compabilitiy display by listening to VR mode changes.
*/
- public void init(Context context) {
+ public void init(Context context, boolean bootsToVr) {
startVrModeListener();
startDebugOnlyBroadcastReceiver(context);
+ mBootsToVr = bootsToVr;
+ if (mBootsToVr) {
+ // If we are booting into VR, we need to start the virtual display immediately. This
+ // ensures that the virtual display is up by the time Setup Wizard is started.
+ updateVirtualDisplay();
+ }
}
/**
@@ -125,11 +131,13 @@
*/
private void updateVirtualDisplay() {
if (DEBUG) {
- Log.i(TAG, "isVrMode: " + mIsVrModeEnabled + ", override: " + mIsVrModeOverrideEnabled
- + ", isAllowed: " + mIsVirtualDisplayAllowed);
+ Log.i(TAG, "isVrMode: " + mIsPersistentVrModeEnabled + ", override: "
+ + mIsVrModeOverrideEnabled + ", isAllowed: " + mIsVirtualDisplayAllowed
+ + ", bootsToVr: " + mBootsToVr);
}
if (shouldRunVirtualDisplay()) {
+ Log.i(TAG, "Attempting to start virtual display");
// TODO: Consider not creating the display until ActivityManager needs one on
// which to display a 2D application.
startVirtualDisplay();
@@ -383,6 +391,12 @@
}
private boolean shouldRunVirtualDisplay() {
- return mIsVirtualDisplayAllowed && (mIsVrModeEnabled || mIsVrModeOverrideEnabled);
+ // Virtual Display should run whenever:
+ // * Virtual Display is allowed/enabled AND
+ // (1) BootsToVr is set indicating the device never leaves VR
+ // (2) VR (persistent) mode is enabled
+ // (3) VR mode is overridden to be enabled.
+ return mIsVirtualDisplayAllowed &&
+ (mBootsToVr || mIsPersistentVrModeEnabled || mIsVrModeOverrideEnabled);
}
}
diff --git a/services/core/java/com/android/server/vr/VrManagerService.java b/services/core/java/com/android/server/vr/VrManagerService.java
index 3c53771..b10c9a3 100644
--- a/services/core/java/com/android/server/vr/VrManagerService.java
+++ b/services/core/java/com/android/server/vr/VrManagerService.java
@@ -625,7 +625,7 @@
(DisplayManager) getContext().getSystemService(Context.DISPLAY_SERVICE);
ActivityManagerInternal ami = LocalServices.getService(ActivityManagerInternal.class);
mVr2dDisplay = new Vr2dDisplay(dm, ami, mVrManager);
- mVr2dDisplay.init(getContext());
+ mVr2dDisplay.init(getContext(), mBootsToVr);
IntentFilter intentFilter = new IntentFilter();
intentFilter.addAction(Intent.ACTION_USER_UNLOCKED);
diff --git a/services/core/java/com/android/server/wallpaper/WallpaperManagerService.java b/services/core/java/com/android/server/wallpaper/WallpaperManagerService.java
index 929f28d..917f0b9 100644
--- a/services/core/java/com/android/server/wallpaper/WallpaperManagerService.java
+++ b/services/core/java/com/android/server/wallpaper/WallpaperManagerService.java
@@ -379,54 +379,31 @@
/**
* We can easily extract colors from an ImageWallpaper since it's only a bitmap.
- * In this case, using the crop is more than enough.
- *
- * In case of a live wallpaper, the best we can do is to extract colors from its
- * preview image. Anyway, the live wallpaper can also implement the wallpaper colors API
- * to report when colors change.
+ * In this case, using the crop is more than enough. Live wallpapers are just ignored.
*
* @param wallpaper a wallpaper representation
*/
private void extractColors(WallpaperData wallpaper) {
String cropFile = null;
- Drawable thumbnail = null;
- // This represents a maximum pixel count in an image.
- // It prevents color extraction on big bitmaps.
- int wallpaperId = -1;
+ int wallpaperId;
- boolean imageWallpaper = false;
synchronized (mLock) {
- imageWallpaper = mImageWallpaper.equals(wallpaper.wallpaperComponent)
+ // Not having a wallpaperComponent means it's a lock screen wallpaper.
+ final boolean imageWallpaper = mImageWallpaper.equals(wallpaper.wallpaperComponent)
|| wallpaper.wallpaperComponent == null;
- if (imageWallpaper) {
- if (wallpaper.cropFile != null && wallpaper.cropFile.exists()) {
- cropFile = wallpaper.cropFile.getAbsolutePath();
- }
- } else {
- if (wallpaper.connection == null) {
- Slog.w(TAG, "Can't extract colors, wallpaper not connected. " +
- wallpaper.wallpaperId);
- return;
- }
- WallpaperInfo info = wallpaper.connection.mInfo;
- if (info == null) {
- Slog.w(TAG, "Something is really wrong, live wallpaper doesn't have " +
- "a WallpaperInfo object! " + wallpaper.wallpaperId);
- return;
- }
- thumbnail = info.loadThumbnail(mContext.getPackageManager());
+ if (imageWallpaper && wallpaper.cropFile != null && wallpaper.cropFile.exists()) {
+ cropFile = wallpaper.cropFile.getAbsolutePath();
}
-
wallpaperId = wallpaper.wallpaperId;
}
WallpaperColors colors = null;
if (cropFile != null) {
Bitmap bitmap = BitmapFactory.decodeFile(cropFile);
- colors = WallpaperColors.fromBitmap(bitmap);
- bitmap.recycle();
- } else if (thumbnail != null) {
- colors = WallpaperColors.fromDrawable(thumbnail);
+ if (bitmap != null) {
+ colors = WallpaperColors.fromBitmap(bitmap);
+ bitmap.recycle();
+ }
}
if (colors == null) {
@@ -434,16 +411,6 @@
return;
}
- // Even though we can extract colors from live wallpaper thumbnails,
- // it's risky to assume that it might support dark text on top of it:
- // • Thumbnail might not be accurate.
- // • Colors might change over time.
- if (!imageWallpaper) {
- int colorHints = colors.getColorHints();
- colorHints &= ~WallpaperColors.HINT_SUPPORTS_DARK_TEXT;
- colors.setColorHints(colorHints);
- }
-
synchronized (mLock) {
if (wallpaper.wallpaperId == wallpaperId) {
wallpaper.primaryColors = colors;
@@ -1560,9 +1527,26 @@
}
}
+ private void enforceCallingOrSelfPermissionAndAppOp(String permission, final String callingPkg,
+ final int callingUid, String message) {
+ mContext.enforceCallingOrSelfPermission(permission, message);
+
+ final String opName = AppOpsManager.permissionToOp(permission);
+ if (opName != null) {
+ final int appOpMode = mAppOpsManager.noteOp(opName, callingUid, callingPkg);
+ if (appOpMode != AppOpsManager.MODE_ALLOWED) {
+ throw new SecurityException(
+ message + ": " + callingPkg + " is not allowed to " + permission);
+ }
+ }
+ }
+
@Override
- public ParcelFileDescriptor getWallpaper(IWallpaperManagerCallback cb, final int which,
- Bundle outParams, int wallpaperUserId) {
+ public ParcelFileDescriptor getWallpaper(String callingPkg, IWallpaperManagerCallback cb,
+ final int which, Bundle outParams, int wallpaperUserId) {
+ enforceCallingOrSelfPermissionAndAppOp(android.Manifest.permission.READ_EXTERNAL_STORAGE,
+ callingPkg, Binder.getCallingUid(), "read wallpaper");
+
wallpaperUserId = ActivityManager.handleIncomingUser(Binder.getCallingPid(),
Binder.getCallingUid(), wallpaperUserId, false, true, "getWallpaper", null);
diff --git a/services/core/java/com/android/server/wm/AppWindowToken.java b/services/core/java/com/android/server/wm/AppWindowToken.java
index 8afc4fd..ce44dab8 100644
--- a/services/core/java/com/android/server/wm/AppWindowToken.java
+++ b/services/core/java/com/android/server/wm/AppWindowToken.java
@@ -1343,15 +1343,38 @@
}
/**
+ * Returns whether the drawn window states of this {@link AppWindowToken} has considered every
+ * child {@link WindowState}. A child is considered if it has been passed into
+ * {@link #updateDrawnWindowStates(WindowState)} after being added. This is used to determine
+ * whether states, such as {@code allDrawn}, can be set, which relies on state variables such as
+ * {@code mNumInterestingWindows}, which depend on all {@link WindowState}s being considered.
+ *
+ * @return {@code true} If all children have been considered, {@code false}.
+ */
+ private boolean allDrawnStatesConsidered() {
+ for (WindowState child : mChildren) {
+ if (!child.getDrawnStatedEvaluated()) {
+ return false;
+ }
+ }
+ return true;
+ }
+
+ /**
* Determines if the token has finished drawing. This should only be called from
* {@link DisplayContent#applySurfaceChangesTransaction}
*/
void updateAllDrawn() {
if (!allDrawn) {
// Number of drawn windows can be less when a window is being relaunched, wait for
- // all windows to be launched and drawn for this token be considered all drawn
+ // all windows to be launched and drawn for this token be considered all drawn.
final int numInteresting = mNumInterestingWindows;
- if (numInteresting > 0 && mNumDrawnWindows >= numInteresting && !isRelaunching()) {
+
+ // We must make sure that all present children have been considered (determined by
+ // {@link #allDrawnStatesConsidered}) before evaluating whether everything has been
+ // drawn.
+ if (numInteresting > 0 && allDrawnStatesConsidered()
+ && mNumDrawnWindows >= numInteresting && !isRelaunching()) {
if (DEBUG_VISIBILITY) Slog.v(TAG, "allDrawn: " + this
+ " interesting=" + numInteresting + " drawn=" + mNumDrawnWindows);
allDrawn = true;
@@ -1396,6 +1419,8 @@
* windows in this app token where not considered drawn as of the last pass.
*/
boolean updateDrawnWindowStates(WindowState w) {
+ w.setDrawnStateEvaluated(true /*evaluated*/);
+
if (DEBUG_STARTING_WINDOW_VERBOSE && w == startingWindow) {
Slog.d(TAG, "updateWindows: starting " + w + " isOnScreen=" + w.isOnScreen()
+ " allDrawn=" + allDrawn + " freezingScreen=" + mAppAnimator.freezingScreen);
@@ -1573,6 +1598,17 @@
return null;
}
+ int getLowestAnimLayer() {
+ for (int i = 0; i < mChildren.size(); i++) {
+ final WindowState w = mChildren.get(i);
+ if (w.mRemoved) {
+ continue;
+ }
+ return w.mWinAnimator.mAnimLayer;
+ }
+ return Integer.MAX_VALUE;
+ }
+
WindowState getHighestAnimLayerWindow(WindowState currentTarget) {
WindowState candidate = null;
for (int i = mChildren.indexOf(currentTarget); i >= 0; i--) {
diff --git a/services/core/java/com/android/server/wm/DimLayer.java b/services/core/java/com/android/server/wm/DimLayer.java
index 015c084..708973d 100644
--- a/services/core/java/com/android/server/wm/DimLayer.java
+++ b/services/core/java/com/android/server/wm/DimLayer.java
@@ -81,6 +81,12 @@
boolean isAttachedToDisplay();
/** Gets the bounds of the dim layer user. */
void getDimBounds(Rect outBounds);
+ /** Returns the layer to place a dim layer. */
+ default int getLayerForDim(WindowStateAnimator animator, int layerOffset,
+ int defaultLayer) {
+ return defaultLayer;
+ }
+
String toShortString();
}
/** The user of this dim layer. */
diff --git a/services/core/java/com/android/server/wm/DimLayerController.java b/services/core/java/com/android/server/wm/DimLayerController.java
index d44cd13..49f5ee6 100644
--- a/services/core/java/com/android/server/wm/DimLayerController.java
+++ b/services/core/java/com/android/server/wm/DimLayerController.java
@@ -261,7 +261,8 @@
dimLayer = state.animator.mAnimLayer + LAYER_OFFSET_DIM;
dimAmount = DEFAULT_DIM_AMOUNT_DEAD_WINDOW;
} else {
- dimLayer = state.animator.mAnimLayer - LAYER_OFFSET_DIM;
+ dimLayer = dimLayerUser.getLayerForDim(state.animator, LAYER_OFFSET_DIM,
+ state.animator.mAnimLayer - LAYER_OFFSET_DIM);
dimAmount = state.animator.mWin.mAttrs.dimAmount;
}
}
diff --git a/services/core/java/com/android/server/wm/DisplayContent.java b/services/core/java/com/android/server/wm/DisplayContent.java
index c98d60d..05f4626 100644
--- a/services/core/java/com/android/server/wm/DisplayContent.java
+++ b/services/core/java/com/android/server/wm/DisplayContent.java
@@ -1073,7 +1073,7 @@
}
if (w.mHasSurface && !rotateSeamlessly) {
if (DEBUG_ORIENTATION) Slog.v(TAG_WM, "Set mOrientationChanging of " + w);
- w.mOrientationChanging = true;
+ w.setOrientationChanging(true);
mService.mRoot.mOrientationChangeComplete = false;
w.mLastFreezeDuration = 0;
}
@@ -1183,6 +1183,8 @@
final int dh = displayInfo.logicalHeight;
config.orientation = (dw <= dh) ? Configuration.ORIENTATION_PORTRAIT :
Configuration.ORIENTATION_LANDSCAPE;
+ config.setRotation(displayInfo.rotation);
+
config.screenWidthDp =
(int)(mService.mPolicy.getConfigDisplayWidth(dw, dh, displayInfo.rotation,
config.uiMode, mDisplayId) / mDisplayMetrics.density);
@@ -2677,10 +2679,10 @@
mService.mWindowsFreezingScreen = WINDOWS_FREEZING_SCREENS_TIMEOUT;
forAllWindows(w -> {
- if (!w.mOrientationChanging) {
+ if (!w.getOrientationChanging()) {
return;
}
- w.mOrientationChanging = false;
+ w.setOrientationChanging(false);
w.mLastFreezeDuration = (int)(SystemClock.elapsedRealtime()
- mService.mDisplayFreezeTime);
Slog.w(TAG_WM, "Force clearing orientation change: " + w);
diff --git a/services/core/java/com/android/server/wm/Session.java b/services/core/java/com/android/server/wm/Session.java
index 22b0f5b..7a8c2f9 100644
--- a/services/core/java/com/android/server/wm/Session.java
+++ b/services/core/java/com/android/server/wm/Session.java
@@ -16,6 +16,7 @@
package com.android.server.wm;
+import static android.Manifest.permission.HIDE_NON_SYSTEM_OVERLAY_WINDOWS;
import static android.Manifest.permission.INTERNAL_SYSTEM_WINDOW;
import static android.content.pm.PackageManager.PERMISSION_GRANTED;
import static android.os.Trace.TRACE_TAG_WINDOW_MANAGER;
@@ -82,6 +83,7 @@
// Set of visible alert window surfaces connected to this session.
private final Set<WindowSurfaceController> mAlertWindowSurfaces = new HashSet<>();
final boolean mCanAddInternalSystemWindow;
+ final boolean mCanHideNonSystemOverlayWindows;
private AlertWindowNotification mAlertWindowNotification;
private boolean mShowingAlertWindowNotificationAllowed;
private boolean mClientDead = false;
@@ -99,6 +101,8 @@
mLastReportedAnimatorScale = service.getCurrentAnimatorScale();
mCanAddInternalSystemWindow = service.mContext.checkCallingOrSelfPermission(
INTERNAL_SYSTEM_WINDOW) == PERMISSION_GRANTED;
+ mCanHideNonSystemOverlayWindows = service.mContext.checkCallingOrSelfPermission(
+ HIDE_NON_SYSTEM_OVERLAY_WINDOWS) == PERMISSION_GRANTED;
mShowingAlertWindowNotificationAllowed = mService.mShowAlertWindowNotifications;
StringBuilder sb = new StringBuilder();
sb.append("Session{");
diff --git a/services/core/java/com/android/server/wm/Task.java b/services/core/java/com/android/server/wm/Task.java
index bfebca8..cc3b146 100644
--- a/services/core/java/com/android/server/wm/Task.java
+++ b/services/core/java/com/android/server/wm/Task.java
@@ -23,6 +23,8 @@
import static android.content.pm.ActivityInfo.RESIZE_MODE_FORCE_RESIZABLE_PORTRAIT_ONLY;
import static android.content.pm.ActivityInfo.RESIZE_MODE_FORCE_RESIZABLE_PRESERVE_ORIENTATION;
import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_UNSET;
+import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_STARTING;
+
import static com.android.server.EventLogTags.WM_TASK_REMOVED;
import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_STACK;
import static com.android.server.wm.WindowManagerDebugConfig.TAG_WITH_CLASS_NAME;
@@ -39,6 +41,7 @@
import android.view.Surface;
import com.android.internal.annotations.VisibleForTesting;
+import com.android.server.wm.DimLayer.DimLayerUser;
import java.io.PrintWriter;
import java.util.function.Consumer;
@@ -637,6 +640,18 @@
return isFullscreen();
}
+ @Override
+ public int getLayerForDim(WindowStateAnimator animator, int layerOffset, int defaultLayer) {
+ // If the dim layer is for a starting window, move the dim layer back in the z-order behind
+ // the lowest activity window to ensure it does not occlude the main window if it is
+ // translucent
+ final AppWindowToken appToken = animator.mWin.mAppToken;
+ if (animator.mAttrType == TYPE_APPLICATION_STARTING && hasChild(appToken) ) {
+ return Math.min(defaultLayer, appToken.getLowestAnimLayer() - layerOffset);
+ }
+ return defaultLayer;
+ }
+
boolean isFullscreen() {
if (useCurrentBounds()) {
return mFillsParent;
diff --git a/services/core/java/com/android/server/wm/TaskSnapshotController.java b/services/core/java/com/android/server/wm/TaskSnapshotController.java
index edb8853..940ad33 100644
--- a/services/core/java/com/android/server/wm/TaskSnapshotController.java
+++ b/services/core/java/com/android/server/wm/TaskSnapshotController.java
@@ -18,6 +18,9 @@
import static android.app.ActivityManager.ENABLE_TASK_SNAPSHOTS;
+import static com.android.server.wm.WindowManagerDebugConfig.TAG_WITH_CLASS_NAME;
+import static com.android.server.wm.WindowManagerDebugConfig.TAG_WM;
+
import android.annotation.Nullable;
import android.app.ActivityManager;
import android.app.ActivityManager.StackId;
@@ -29,6 +32,7 @@
import android.os.Environment;
import android.os.Handler;
import android.util.ArraySet;
+import android.util.Slog;
import android.view.DisplayListCanvas;
import android.view.RenderNode;
import android.view.ThreadedRenderer;
@@ -57,6 +61,7 @@
* To access this class, acquire the global window manager lock.
*/
class TaskSnapshotController {
+ private static final String TAG = TAG_WITH_CLASS_NAME ? "TaskSnapshotController" : TAG_WM;
/**
* Return value for {@link #getSnapshotMode}: We are allowed to take a real screenshot to be
@@ -154,10 +159,17 @@
break;
}
if (snapshot != null) {
- mCache.putSnapshot(task, snapshot);
- mPersister.persistSnapshot(task.mTaskId, task.mUserId, snapshot);
- if (task.getController() != null) {
- task.getController().reportSnapshotChanged(snapshot);
+ final GraphicBuffer buffer = snapshot.getSnapshot();
+ if (buffer.getWidth() == 0 || buffer.getHeight() == 0) {
+ buffer.destroy();
+ Slog.e(TAG, "Invalid task snapshot dimensions " + buffer.getWidth() + "x"
+ + buffer.getHeight());
+ } else {
+ mCache.putSnapshot(task, snapshot);
+ mPersister.persistSnapshot(task.mTaskId, task.mUserId, snapshot);
+ if (task.getController() != null) {
+ task.getController().reportSnapshotChanged(snapshot);
+ }
}
}
}
diff --git a/services/core/java/com/android/server/wm/TaskSnapshotPersister.java b/services/core/java/com/android/server/wm/TaskSnapshotPersister.java
index b628869..f90b3fb 100644
--- a/services/core/java/com/android/server/wm/TaskSnapshotPersister.java
+++ b/services/core/java/com/android/server/wm/TaskSnapshotPersister.java
@@ -291,7 +291,6 @@
failed = true;
}
if (!writeBuffer()) {
- writeBuffer();
failed = true;
}
if (failed) {
@@ -327,11 +326,7 @@
final File reducedFile = getReducedResolutionBitmapFile(mTaskId, mUserId);
final Bitmap bitmap = Bitmap.createHardwareBitmap(mSnapshot.getSnapshot());
if (bitmap == null) {
- Slog.e(TAG, "Invalid task snapshot");
- return false;
- } else if (bitmap.getWidth() == 0 || bitmap.getHeight() == 0) {
- Slog.e(TAG, "Invalid task snapshot dimensions " + bitmap.getWidth() + "x"
- + bitmap.getHeight());
+ Slog.e(TAG, "Invalid task snapshot hw bitmap");
return false;
}
diff --git a/services/core/java/com/android/server/wm/TaskSnapshotSurface.java b/services/core/java/com/android/server/wm/TaskSnapshotSurface.java
index a96d224..802f9ed 100644
--- a/services/core/java/com/android/server/wm/TaskSnapshotSurface.java
+++ b/services/core/java/com/android/server/wm/TaskSnapshotSurface.java
@@ -20,6 +20,7 @@
import static android.graphics.Color.alpha;
import static android.view.SurfaceControl.HIDDEN;
import static android.view.WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM;
+import static android.view.WindowManager.LayoutParams.FLAG_DIM_BEHIND;
import static android.view.WindowManager.LayoutParams.FLAG_HARDWARE_ACCELERATED;
import static android.view.WindowManager.LayoutParams.FLAG_IGNORE_CHEEK_PRESSES;
import static android.view.WindowManager.LayoutParams.FLAG_LOCAL_FOCUS_MODE;
@@ -32,7 +33,6 @@
import static android.view.WindowManager.LayoutParams.FLAG_SPLIT_TOUCH;
import static android.view.WindowManager.LayoutParams.FLAG_WATCH_OUTSIDE_TOUCH;
import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_FORCE_DRAW_STATUS_BAR_BACKGROUND;
-import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_TASK_SNAPSHOT;
import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_STARTING;
import static com.android.internal.policy.DecorView.NAVIGATION_BAR_COLOR_VIEW_ATTRIBUTES;
import static com.android.internal.policy.DecorView.STATUS_BAR_COLOR_VIEW_ATTRIBUTES;
@@ -159,13 +159,13 @@
windowFlags = mainWindow.getAttrs().flags;
windowPrivateFlags = mainWindow.getAttrs().privateFlags;
+ layoutParams.dimAmount = mainWindow.getAttrs().dimAmount;
layoutParams.type = TYPE_APPLICATION_STARTING;
layoutParams.format = snapshot.getSnapshot().getFormat();
layoutParams.flags = (windowFlags & ~FLAG_INHERIT_EXCLUDES)
| FLAG_NOT_FOCUSABLE
| FLAG_NOT_TOUCHABLE;
- layoutParams.privateFlags = PRIVATE_FLAG_TASK_SNAPSHOT
- | (windowPrivateFlags & PRIVATE_FLAG_INHERITS);
+ layoutParams.privateFlags = windowPrivateFlags & PRIVATE_FLAG_INHERITS;
layoutParams.token = token.token;
layoutParams.width = LayoutParams.MATCH_PARENT;
layoutParams.height = LayoutParams.MATCH_PARENT;
diff --git a/services/core/java/com/android/server/wm/WindowManagerService.java b/services/core/java/com/android/server/wm/WindowManagerService.java
index ceddc4e..f9c21b3 100644
--- a/services/core/java/com/android/server/wm/WindowManagerService.java
+++ b/services/core/java/com/android/server/wm/WindowManagerService.java
@@ -30,7 +30,6 @@
import static android.os.Process.ROOT_UID;
import static android.os.Process.SHELL_UID;
import static android.os.Process.SYSTEM_UID;
-import static android.os.Process.THREAD_PRIORITY_DISPLAY;
import static android.os.Process.myPid;
import static android.os.Trace.TRACE_TAG_WINDOW_MANAGER;
import static android.os.UserHandle.USER_NULL;
@@ -50,7 +49,6 @@
import static android.view.WindowManager.LayoutParams.LAST_APPLICATION_WINDOW;
import static android.view.WindowManager.LayoutParams.LAST_SUB_WINDOW;
import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_COMPATIBLE_WINDOW;
-import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_TASK_SNAPSHOT;
import static android.view.WindowManager.LayoutParams.TYPE_ACCESSIBILITY_OVERLAY;
import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_STARTING;
import static android.view.WindowManager.LayoutParams.TYPE_DOCK_DIVIDER;
@@ -233,7 +231,6 @@
import com.android.server.EventLogTags;
import com.android.server.FgThread;
import com.android.server.LocalServices;
-import com.android.server.ThreadPriorityBooster;
import com.android.server.UiThread;
import com.android.server.Watchdog;
import com.android.server.input.InputManagerService;
@@ -498,12 +495,15 @@
*/
Runnable mWaitingForDrawnCallback;
+ /** List of window currently causing non-system overlay windows to be hidden. */
+ private ArrayList<WindowState> mHidingNonSystemOverlayWindows = new ArrayList<>();
+
/**
* Stores for each user whether screencapture is disabled
* This array is essentially a cache for all userId for
* {@link android.app.admin.DevicePolicyManager#getScreenCaptureDisabled}
*/
- SparseArray<Boolean> mScreenCaptureDisabled = new SparseArray<>();
+ private SparseArray<Boolean> mScreenCaptureDisabled = new SparseArray<>();
IInputMethodManager mInputMethodManager;
@@ -1718,6 +1718,7 @@
}
mPendingRemove.remove(win);
mResizingWindows.remove(win);
+ updateNonSystemOverlayWindowsVisibilityIfNeeded(win, false /* surfaceShown */);
mWindowsChanged = true;
if (DEBUG_WINDOW_MOVEMENT) Slog.v(TAG_WM, "Final remove of window: " + win);
@@ -2020,8 +2021,7 @@
win.setDisplayLayoutNeeded();
mWindowPlacerLocked.performSurfacePlacement(true);
}
- result = win.relayoutVisibleWindow(mergedConfiguration, result, attrChanges,
- oldVisibility);
+ result = win.relayoutVisibleWindow(result, attrChanges, oldVisibility);
try {
result = createSurfaceControl(outSurface, result, win, winAnimator);
@@ -2159,6 +2159,15 @@
if (!win.isGoneForLayoutLw()) {
win.mResizedWhileGone = false;
}
+
+ // We must always send the latest {@link MergedConfiguration}, regardless of whether we
+ // have already reported it. The client might not have processed the previous value yet
+ // and needs process it before handling the corresponding window frame. the variable
+ // {@code mergedConfiguration} is an out parameter that will be passed back to the
+ // client over IPC and checked there.
+ win.getMergedConfiguration(mergedConfiguration);
+ win.setReportedConfiguration(mergedConfiguration);
+
outFrame.set(win.mCompatFrame);
outOverscanInsets.set(win.mOverscanInsets);
outContentInsets.set(win.mContentInsets);
@@ -5780,7 +5789,7 @@
// orientation.
if (!okToDisplay() && mWindowsFreezingScreen != WINDOWS_FREEZING_SCREENS_TIMEOUT) {
if (DEBUG_ORIENTATION) Slog.v(TAG_WM, "Changing surface while display frozen: " + w);
- w.mOrientationChanging = true;
+ w.setOrientationChanging(true);
w.mLastFreezeDuration = 0;
mRoot.mOrientationChangeComplete = false;
if (mWindowsFreezingScreen == WINDOWS_FREEZING_SCREENS_NONE) {
@@ -6479,6 +6488,21 @@
ArrayList<WindowState> windows) {
mRoot.dumpWindowsNoHeader(pw, dumpAll, windows);
+ if (!mHidingNonSystemOverlayWindows.isEmpty()) {
+ pw.println();
+ pw.println(" Hiding System Alert Windows:");
+ for (int i = mHidingNonSystemOverlayWindows.size() - 1; i >= 0; i--) {
+ final WindowState w = mHidingNonSystemOverlayWindows.get(i);
+ pw.print(" #"); pw.print(i); pw.print(' ');
+ pw.print(w);
+ if (dumpAll) {
+ pw.println(":");
+ w.dump(pw, " ", true);
+ } else {
+ pw.println();
+ }
+ }
+ }
if (mPendingRemove.size() > 0) {
pw.println();
pw.println(" Remove pending for:");
@@ -7593,4 +7617,28 @@
boolean hasWideColorGamutSupport() {
return mHasWideColorGamutSupport;
}
+
+ void updateNonSystemOverlayWindowsVisibilityIfNeeded(WindowState win, boolean surfaceShown) {
+ if (!win.hideNonSystemOverlayWindowsWhenVisible()) {
+ return;
+ }
+ final boolean systemAlertWindowsHidden = !mHidingNonSystemOverlayWindows.isEmpty();
+ if (surfaceShown) {
+ if (!mHidingNonSystemOverlayWindows.contains(win)) {
+ mHidingNonSystemOverlayWindows.add(win);
+ }
+ } else {
+ mHidingNonSystemOverlayWindows.remove(win);
+ }
+
+ final boolean hideSystemAlertWindows = !mHidingNonSystemOverlayWindows.isEmpty();
+
+ if (systemAlertWindowsHidden == hideSystemAlertWindows) {
+ return;
+ }
+
+ mRoot.forAllWindows((w) -> {
+ w.setForceHideNonSystemOverlayWindowIfNeeded(hideSystemAlertWindows);
+ }, false /* traverseTopToBottom */);
+ }
}
diff --git a/services/core/java/com/android/server/wm/WindowState.java b/services/core/java/com/android/server/wm/WindowState.java
index f74948f..17768e6 100644
--- a/services/core/java/com/android/server/wm/WindowState.java
+++ b/services/core/java/com/android/server/wm/WindowState.java
@@ -46,6 +46,7 @@
import static android.view.WindowManager.LayoutParams.LAST_SUB_WINDOW;
import static android.view.WindowManager.LayoutParams.MATCH_PARENT;
import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_COMPATIBLE_WINDOW;
+import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_HIDE_NON_SYSTEM_OVERLAY_WINDOWS;
import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_LAYOUT_CHILD_WINDOW_IN_PARENT_FRAME;
import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_NO_MOVE_ANIMATION;
import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_WILL_NOT_REPLACE_ON_RELAUNCH;
@@ -59,7 +60,9 @@
import static android.view.WindowManager.LayoutParams.TYPE_DRAWN_APPLICATION;
import static android.view.WindowManager.LayoutParams.TYPE_INPUT_METHOD;
import static android.view.WindowManager.LayoutParams.TYPE_INPUT_METHOD_DIALOG;
+import static android.view.WindowManager.LayoutParams.TYPE_TOAST;
import static android.view.WindowManager.LayoutParams.TYPE_WALLPAPER;
+import static android.view.WindowManager.LayoutParams.isSystemAlertWindowType;
import static android.view.WindowManagerGlobal.RELAYOUT_RES_DRAG_RESIZING_DOCKED;
import static android.view.WindowManagerGlobal.RELAYOUT_RES_DRAG_RESIZING_FREEFORM;
import static android.view.WindowManagerGlobal.RELAYOUT_RES_FIRST_TIME;
@@ -208,6 +211,8 @@
boolean mPolicyVisibilityAfterAnim = true;
private boolean mAppOpVisibility = true;
boolean mPermanentlyHidden; // the window should never be shown again
+ // This is a non-system overlay window that is currently force hidden.
+ private boolean mForceHideNonSystemOverlayWindow;
boolean mAppFreezing;
boolean mHidden; // Used to determine if to show child windows.
boolean mWallpaperVisible; // for wallpaper, what was last vis report?
@@ -441,7 +446,7 @@
* Set when the orientation is changing and this window has not yet
* been updated for the new orientation.
*/
- boolean mOrientationChanging;
+ private boolean mOrientationChanging;
/**
* The orientation during the last visible call to relayout. If our
@@ -560,6 +565,13 @@
final Rect mLastSurfaceInsets = new Rect();
/**
+ * A flag set by the {@link WindowState} parent to indicate that the parent has examined this
+ * {@link WindowState} in its overall drawing context. This book-keeping allows the parent to
+ * make sure all children have been considered.
+ */
+ private boolean mDrawnStateEvaluated;
+
+ /**
* Compares two window sub-layers and returns -1 if the first is lesser than the second in terms
* of z-order and 1 otherwise.
*/
@@ -675,6 +687,27 @@
mSession.windowAddedLocked(mAttrs.packageName);
}
+ /**
+ * Returns whether this {@link WindowState} has been considered for drawing by its parent.
+ */
+ boolean getDrawnStatedEvaluated() {
+ return mDrawnStateEvaluated;
+ }
+
+ /**
+ * Sets whether this {@link WindowState} has been considered for drawing by its parent. Should
+ * be cleared when detached from parent.
+ */
+ void setDrawnStateEvaluated(boolean evaluated) {
+ mDrawnStateEvaluated = evaluated;
+ }
+
+ @Override
+ void onParentSet() {
+ super.onParentSet();
+ setDrawnStateEvaluated(false /*evaluated*/);
+ }
+
@Override
public int getOwningUid() {
return mOwnerUid;
@@ -1156,7 +1189,8 @@
// then we need to hold off on unfreezing the display until this window has been
// redrawn; to do that, we need to go through the process of getting informed by the
// application when it has finished drawing.
- if (mOrientationChanging || dragResizingChanged || isResizedWhileNotDragResizing()) {
+ if (getOrientationChanging() || dragResizingChanged
+ || isResizedWhileNotDragResizing()) {
if (DEBUG_SURFACE_TRACE || DEBUG_ANIM || DEBUG_ORIENTATION || DEBUG_RESIZE) {
Slog.v(TAG_WM, "Orientation or resize start waiting for draw"
+ ", mDrawState=DRAW_PENDING in " + this
@@ -1171,17 +1205,33 @@
if (DEBUG_RESIZE || DEBUG_ORIENTATION) Slog.v(TAG_WM, "Resizing window " + this);
mService.mResizingWindows.add(this);
}
- } else if (mOrientationChanging) {
+ } else if (getOrientationChanging()) {
if (isDrawnLw()) {
if (DEBUG_ORIENTATION) Slog.v(TAG_WM, "Orientation not waiting for draw in "
+ this + ", surfaceController " + winAnimator.mSurfaceController);
- mOrientationChanging = false;
+ setOrientationChanging(false);
mLastFreezeDuration = (int)(SystemClock.elapsedRealtime()
- mService.mDisplayFreezeTime);
}
}
}
+ boolean getOrientationChanging() {
+ // In addition to the local state flag, we must also consider the difference in the last
+ // reported configuration vs. the current state. If the client code has not been informed of
+ // the change, logic dependent on having finished processing the orientation, such as
+ // unfreezing, could be improperly triggered.
+ // TODO(b/62846907): Checking against {@link mLastReportedConfiguration} could be flaky as
+ // this is not necessarily what the client has processed yet. Find a
+ // better indicator consistent with the client.
+ return mOrientationChanging
+ || getConfiguration().orientation != mLastReportedConfiguration.orientation;
+ }
+
+ void setOrientationChanging(boolean changing) {
+ mOrientationChanging = changing;
+ }
+
DisplayContent getDisplayContent() {
return mToken.getDisplayContent();
}
@@ -2207,8 +2257,7 @@
}
}
- void prepareWindowToDisplayDuringRelayout(MergedConfiguration mergedConfiguration,
- boolean wasVisible) {
+ void prepareWindowToDisplayDuringRelayout(boolean wasVisible) {
// We need to turn on screen regardless of visibility.
if ((mAttrs.flags & FLAG_TURN_SCREEN_ON) != 0) {
if (DEBUG_VISIBILITY) Slog.v(TAG, "Relayout window turning screen on: " + this);
@@ -2230,16 +2279,16 @@
if (isDrawnLw() && mService.okToDisplay()) {
mWinAnimator.applyEnterAnimationLocked();
}
+ }
- if (isConfigChanged()) {
- final Configuration globalConfig = mService.mRoot.getConfiguration();
- final Configuration overrideConfig = getMergedOverrideConfiguration();
- mergedConfiguration.setConfiguration(globalConfig, overrideConfig);
- if (DEBUG_CONFIGURATION) Slog.i(TAG, "Window " + this
- + " visible with new global config: " + globalConfig
- + " merged override config: " + overrideConfig);
- mLastReportedConfiguration.setTo(getConfiguration());
- }
+ void getMergedConfiguration(MergedConfiguration outConfiguration) {
+ final Configuration globalConfig = mService.mRoot.getConfiguration();
+ final Configuration overrideConfig = getMergedOverrideConfiguration();
+ outConfiguration.setConfiguration(globalConfig, overrideConfig);
+ }
+
+ void setReportedConfiguration(MergedConfiguration config) {
+ mLastReportedConfiguration.setTo(config.getMergedConfiguration());
}
void adjustStartingWindowFlags() {
@@ -2371,6 +2420,10 @@
// to handle their windows being removed from under them.
return false;
}
+ if (mForceHideNonSystemOverlayWindow) {
+ // This is an alert window that is currently force hidden.
+ return false;
+ }
if (mPolicyVisibility && mPolicyVisibilityAfterAnim) {
// Already showing.
return false;
@@ -2447,6 +2500,22 @@
return true;
}
+ void setForceHideNonSystemOverlayWindowIfNeeded(boolean forceHide) {
+ if (mOwnerCanAddInternalSystemWindow
+ || (!isSystemAlertWindowType(mAttrs.type) && mAttrs.type != TYPE_TOAST)) {
+ return;
+ }
+ if (mForceHideNonSystemOverlayWindow == forceHide) {
+ return;
+ }
+ mForceHideNonSystemOverlayWindow = forceHide;
+ if (forceHide) {
+ hideLw(true /* doAnimation */, true /* requestAnim */);
+ } else {
+ showLw(true /* doAnimation */, true /* requestAnim */);
+ }
+ }
+
public void setAppOpVisibilityLw(boolean state) {
if (mAppOpVisibility != state) {
mAppOpVisibility = state;
@@ -2636,10 +2705,10 @@
mAppFreezing = false;
- if (mHasSurface && !mOrientationChanging
+ if (mHasSurface && !getOrientationChanging()
&& mService.mWindowsFreezingScreen != WINDOWS_FREEZING_SCREENS_TIMEOUT) {
if (DEBUG_ORIENTATION) Slog.v(TAG_WM, "set mOrientationChanging of " + this);
- mOrientationChanging = true;
+ setOrientationChanging(true);
mService.mRoot.mOrientationChangeComplete = false;
}
mLastFreezeDuration = 0;
@@ -3005,14 +3074,12 @@
try {
if (DEBUG_RESIZE || DEBUG_ORIENTATION) Slog.v(TAG, "Reporting new frame to " + this
+ ": " + mCompatFrame);
- final MergedConfiguration mergedConfiguration;
- if (isConfigChanged()) {
- mergedConfiguration = new MergedConfiguration(mService.mRoot.getConfiguration(),
- getMergedOverrideConfiguration());
- mLastReportedConfiguration.setTo(mergedConfiguration.getMergedConfiguration());
- } else {
- mergedConfiguration = null;
- }
+ final MergedConfiguration mergedConfiguration =
+ new MergedConfiguration(mService.mRoot.getConfiguration(),
+ getMergedOverrideConfiguration());
+
+ setReportedConfiguration(mergedConfiguration);
+
if (DEBUG_ORIENTATION && mWinAnimator.mDrawState == DRAW_PENDING)
Slog.i(TAG, "Resizing " + this + " WITH DRAW PENDING");
@@ -3060,7 +3127,7 @@
mWinAnimator.mSurfaceResized = false;
mReportOrientationChanged = false;
} catch (RemoteException e) {
- mOrientationChanging = false;
+ setOrientationChanging(false);
mLastFreezeDuration = (int)(SystemClock.elapsedRealtime()
- mService.mDisplayFreezeTime);
// We are assuming the hosting process is dead or in a zombie state.
@@ -3330,7 +3397,7 @@
pw.println(Integer.toHexString(mSystemUiVisibility));
}
if (!mPolicyVisibility || !mPolicyVisibilityAfterAnim || !mAppOpVisibility
- || isParentWindowHidden()|| mPermanentlyHidden) {
+ || isParentWindowHidden()|| mPermanentlyHidden || mForceHideNonSystemOverlayWindow) {
pw.print(prefix); pw.print("mPolicyVisibility=");
pw.print(mPolicyVisibility);
pw.print(" mPolicyVisibilityAfterAnim=");
@@ -3338,7 +3405,9 @@
pw.print(" mAppOpVisibility=");
pw.print(mAppOpVisibility);
pw.print(" parentHidden="); pw.print(isParentWindowHidden());
- pw.print(" mPermanentlyHidden="); pw.println(mPermanentlyHidden);
+ pw.print(" mPermanentlyHidden="); pw.print(mPermanentlyHidden);
+ pw.print(" mForceHideNonSystemOverlayWindow="); pw.println(
+ mForceHideNonSystemOverlayWindow);
}
if (!mRelayoutCalled || mLayoutNeeded) {
pw.print(prefix); pw.print("mRelayoutCalled="); pw.print(mRelayoutCalled);
@@ -3419,10 +3488,13 @@
pw.print(" mDestroying="); pw.print(mDestroying);
pw.print(" mRemoved="); pw.println(mRemoved);
}
- if (mOrientationChanging || mAppFreezing || mTurnOnScreen
+ if (getOrientationChanging() || mAppFreezing || mTurnOnScreen
|| mReportOrientationChanged) {
pw.print(prefix); pw.print("mOrientationChanging=");
pw.print(mOrientationChanging);
+ pw.print(" configOrientationChanging=");
+ pw.print(mLastReportedConfiguration.orientation
+ != getConfiguration().orientation);
pw.print(" mAppFreezing="); pw.print(mAppFreezing);
pw.print(" mTurnOnScreen="); pw.print(mTurnOnScreen);
pw.print(" mReportOrientationChanged="); pw.println(mReportOrientationChanged);
@@ -3593,6 +3665,17 @@
&& (mAttrs.privateFlags & PRIVATE_FLAG_LAYOUT_CHILD_WINDOW_IN_PARENT_FRAME) != 0;
}
+ /**
+ * Returns true if any window added by an application process that if of type
+ * {@link android.view.WindowManager.LayoutParams#TYPE_TOAST} or that requires that requires
+ * {@link android.app.AppOpsManager#OP_SYSTEM_ALERT_WINDOW} permission should be hidden when
+ * this window is visible.
+ */
+ boolean hideNonSystemOverlayWindowsWhenVisible() {
+ return (mAttrs.privateFlags & PRIVATE_FLAG_HIDE_NON_SYSTEM_OVERLAY_WINDOWS) != 0
+ && mSession.mCanHideNonSystemOverlayWindows;
+ }
+
/** Returns the parent window if this is a child of another window, else null. */
WindowState getParentWindow() {
// NOTE: We are not calling getParent() directly as the WindowState might be a child of a
@@ -4342,8 +4425,7 @@
return !mLastSurfaceInsets.equals(mAttrs.surfaceInsets);
}
- int relayoutVisibleWindow(MergedConfiguration mergedConfiguration, int result, int attrChanges,
- int oldVisibility) {
+ int relayoutVisibleWindow(int result, int attrChanges, int oldVisibility) {
final boolean wasVisible = isVisibleLw();
result |= (!wasVisible || !isDrawnLw()) ? RELAYOUT_RES_FIRST_TIME : 0;
@@ -4366,7 +4448,7 @@
mWinAnimator.mEnteringAnimation = true;
- prepareWindowToDisplayDuringRelayout(mergedConfiguration, wasVisible);
+ prepareWindowToDisplayDuringRelayout(wasVisible);
if ((attrChanges & FORMAT_CHANGED) != 0) {
// If the format can't be changed in place, preserve the old surface until the app draws
diff --git a/services/core/java/com/android/server/wm/WindowStateAnimator.java b/services/core/java/com/android/server/wm/WindowStateAnimator.java
index 33cb908..df30cfc 100644
--- a/services/core/java/com/android/server/wm/WindowStateAnimator.java
+++ b/services/core/java/com/android/server/wm/WindowStateAnimator.java
@@ -1527,11 +1527,11 @@
// There is no need to wait for an animation change if our window is gone for layout
// already as we'll never be visible.
- if (w.mOrientationChanging && w.isGoneForLayoutLw()) {
+ if (w.getOrientationChanging() && w.isGoneForLayoutLw()) {
if (DEBUG_ORIENTATION) {
Slog.v(TAG, "Orientation change skips hidden " + w);
}
- w.mOrientationChanging = false;
+ w.setOrientationChanging(false);
}
return;
}
@@ -1564,8 +1564,8 @@
// really hidden (gone for layout), there is no point in still waiting for it.
// Note that this does introduce a potential glitch if the window becomes unhidden
// before it has drawn for the new orientation.
- if (w.mOrientationChanging && w.isGoneForLayoutLw()) {
- w.mOrientationChanging = false;
+ if (w.getOrientationChanging() && w.isGoneForLayoutLw()) {
+ w.setOrientationChanging(false);
if (DEBUG_ORIENTATION) Slog.v(TAG,
"Orientation change skips hidden " + w);
}
@@ -1618,7 +1618,7 @@
mAnimator.setPendingLayoutChanges(w.getDisplayId(),
WindowManagerPolicy.FINISH_LAYOUT_REDO_ANIM);
} else {
- w.mOrientationChanging = false;
+ w.setOrientationChanging(false);
}
}
if (hasSurface()) {
@@ -1631,14 +1631,14 @@
displayed = true;
}
- if (w.mOrientationChanging) {
+ if (w.getOrientationChanging()) {
if (!w.isDrawnLw()) {
mAnimator.mBulkUpdateParams &= ~SET_ORIENTATION_CHANGE_COMPLETE;
mAnimator.mLastWindowFreezeSource = w;
if (DEBUG_ORIENTATION) Slog.v(TAG,
"Orientation continue waiting for draw in " + w);
} else {
- w.mOrientationChanging = false;
+ w.setOrientationChanging(false);
if (DEBUG_ORIENTATION) Slog.v(TAG, "Orientation change complete in " + w);
}
}
diff --git a/services/core/java/com/android/server/wm/WindowSurfaceController.java b/services/core/java/com/android/server/wm/WindowSurfaceController.java
index 27927e6..1728cfb 100644
--- a/services/core/java/com/android/server/wm/WindowSurfaceController.java
+++ b/services/core/java/com/android/server/wm/WindowSurfaceController.java
@@ -24,10 +24,8 @@
import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_VISIBILITY;
import static com.android.server.wm.WindowManagerDebugConfig.TAG_WITH_CLASS_NAME;
import static com.android.server.wm.WindowManagerDebugConfig.TAG_WM;
-import static android.view.Surface.SCALING_MODE_FREEZE;
import static android.view.Surface.SCALING_MODE_SCALE_TO_WINDOW;
-import android.graphics.PixelFormat;
import android.graphics.Point;
import android.graphics.PointF;
import android.graphics.Rect;
@@ -514,6 +512,8 @@
void setShown(boolean surfaceShown) {
mSurfaceShown = surfaceShown;
+ mService.updateNonSystemOverlayWindowsVisibilityIfNeeded(mAnimator.mWin, surfaceShown);
+
if (mWindowSession != null) {
mWindowSession.onWindowSurfaceVisibilityChanged(this, mSurfaceShown, mWindowType);
}
diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
index 8cac6e0..68349a1 100644
--- a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
+++ b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
@@ -2020,12 +2020,10 @@
private void setDeviceOwnerSystemPropertyLocked() {
final boolean deviceProvisioned =
mInjector.settingsGlobalGetInt(Settings.Global.DEVICE_PROVISIONED, 0) != 0;
+ final boolean hasDeviceOwner = mOwners.hasDeviceOwner();
// If the device is not provisioned and there is currently no device owner, do not set the
- // read-only system property yet, since Device owner may still be provisioned. For Wear
- // devices, if there is already a device owner then it's OK to set the property to true now,
- // regardless the provision state.
- final boolean isWatchWithDeviceOwner = mIsWatch && mOwners.hasDeviceOwner();
- if (!isWatchWithDeviceOwner && !deviceProvisioned) {
+ // read-only system property yet, since Device owner may still be provisioned.
+ if (!hasDeviceOwner && !deviceProvisioned) {
return;
}
// Still at the first stage of CryptKeeper double bounce, mOwners.hasDeviceOwner is
@@ -2034,20 +2032,16 @@
return;
}
- if (!TextUtils.isEmpty(mInjector.systemPropertiesGet(PROPERTY_DEVICE_OWNER_PRESENT))) {
+ if (!mInjector.systemPropertiesGet(PROPERTY_DEVICE_OWNER_PRESENT, "").isEmpty()) {
Slog.w(LOG_TAG, "Trying to set ro.device_owner, but it has already been set?");
} else {
- if (mOwners.hasDeviceOwner()) {
- mInjector.systemPropertiesSet(PROPERTY_DEVICE_OWNER_PRESENT, "true");
- Slog.i(LOG_TAG, "Set ro.device_owner property to true");
+ final String value = Boolean.toString(hasDeviceOwner);
+ mInjector.systemPropertiesSet(PROPERTY_DEVICE_OWNER_PRESENT, value);
+ Slog.i(LOG_TAG, "Set ro.device_owner property to " + value);
- if (mInjector.securityLogGetLoggingEnabledProperty()) {
- mSecurityLogMonitor.start();
- maybePauseDeviceWideLoggingLocked();
- }
- } else {
- mInjector.systemPropertiesSet(PROPERTY_DEVICE_OWNER_PRESENT, "false");
- Slog.i(LOG_TAG, "Set ro.device_owner property to false");
+ if (hasDeviceOwner && mInjector.securityLogGetLoggingEnabledProperty()) {
+ mSecurityLogMonitor.start();
+ maybePauseDeviceWideLoggingLocked();
}
}
}
diff --git a/services/net/java/android/net/ip/IpManager.java b/services/net/java/android/net/ip/IpManager.java
index a94536c..48fa970 100644
--- a/services/net/java/android/net/ip/IpManager.java
+++ b/services/net/java/android/net/ip/IpManager.java
@@ -35,6 +35,7 @@
import android.net.metrics.IpConnectivityLog;
import android.net.metrics.IpManagerEvent;
import android.net.util.MultinetworkPolicyTracker;
+import android.net.util.SharedLog;
import android.os.INetworkManagementService;
import android.os.Message;
import android.os.RemoteException;
@@ -187,7 +188,7 @@
}
private void log(String msg) {
- mLocalLog.log(PREFIX + msg);
+ mLog.log(PREFIX + msg);
}
@Override
@@ -414,7 +415,7 @@
private final WakeupMessage mProvisioningTimeoutAlarm;
private final WakeupMessage mDhcpActionTimeoutAlarm;
private final MultinetworkPolicyTracker mMultinetworkPolicyTracker;
- private final LocalLog mLocalLog;
+ private final SharedLog mLog;
private final LocalLog mConnectivityPacketLog;
private final MessageHandlingLogger mMsgStateLogger;
private final IpConnectivityLog mMetricsLog = new IpConnectivityLog();
@@ -455,7 +456,7 @@
mCallback = new LoggingCallbackWrapper(callback);
mNwService = nwService;
- mLocalLog = new LocalLog(MAX_LOG_RECORDS);
+ mLog = new SharedLog(MAX_LOG_RECORDS, mTag);
mConnectivityPacketLog = new LocalLog(MAX_PACKET_RECORDS);
mMsgStateLogger = new MessageHandlingLogger();
@@ -500,7 +501,7 @@
private void logMsg(String msg) {
Log.d(mTag, msg);
- getHandler().post(() -> { mLocalLog.log("OBSERVED " + msg); });
+ getHandler().post(() -> { mLog.log("OBSERVED " + msg); });
}
};
@@ -508,7 +509,7 @@
mLinkProperties.setInterfaceName(mInterfaceName);
mMultinetworkPolicyTracker = new MultinetworkPolicyTracker(mContext, getHandler(),
- () -> { mLocalLog.log("OBSERVED AvoidBadWifi changed"); });
+ () -> { mLog.log("OBSERVED AvoidBadWifi changed"); });
mProvisioningTimeoutAlarm = new WakeupMessage(mContext, getHandler(),
mTag + ".EVENT_PROVISIONING_TIMEOUT", EVENT_PROVISIONING_TIMEOUT);
@@ -658,7 +659,7 @@
pw.println();
pw.println(mTag + " StateMachine dump:");
pw.increaseIndent();
- mLocalLog.readOnlyLocalLog().dump(fd, pw, args);
+ mLog.dump(fd, pw, args);
pw.decreaseIndent();
pw.println();
@@ -693,7 +694,7 @@
msg.arg1, msg.arg2, Objects.toString(msg.obj), mMsgStateLogger);
final String richerLogLine = getWhatToString(msg.what) + " " + logLine;
- mLocalLog.log(richerLogLine);
+ mLog.log(richerLogLine);
if (VDBG) {
Log.d(mTag, richerLogLine);
}
@@ -717,7 +718,7 @@
private void logError(String fmt, Object... args) {
final String msg = "ERROR " + String.format(fmt, args);
Log.e(mTag, msg);
- mLocalLog.log(msg);
+ mLog.log(msg);
}
private void getNetworkInterface() {
@@ -1088,6 +1089,7 @@
mIpReachabilityMonitor = new IpReachabilityMonitor(
mContext,
mInterfaceName,
+ mLog,
new IpReachabilityMonitor.Callback() {
@Override
public void notifyLost(InetAddress ip, String logMsg) {
diff --git a/services/net/java/android/net/ip/IpReachabilityMonitor.java b/services/net/java/android/net/ip/IpReachabilityMonitor.java
index d13449a..97c9d82e 100644
--- a/services/net/java/android/net/ip/IpReachabilityMonitor.java
+++ b/services/net/java/android/net/ip/IpReachabilityMonitor.java
@@ -35,6 +35,7 @@
import android.net.netlink.StructNdMsg;
import android.net.netlink.StructNlMsgHdr;
import android.net.util.MultinetworkPolicyTracker;
+import android.net.util.SharedLog;
import android.os.PowerManager;
import android.os.SystemClock;
import android.system.ErrnoException;
@@ -150,6 +151,7 @@
private final PowerManager.WakeLock mWakeLock;
private final String mInterfaceName;
private final int mInterfaceIndex;
+ private final SharedLog mLog;
private final Callback mCallback;
private final MultinetworkPolicyTracker mMultinetworkPolicyTracker;
private final NetlinkSocketObserver mNetlinkSocketObserver;
@@ -221,11 +223,11 @@
return errno;
}
- public IpReachabilityMonitor(Context context, String ifName, Callback callback) {
- this(context, ifName, callback, null);
+ public IpReachabilityMonitor(Context context, String ifName, SharedLog log, Callback callback) {
+ this(context, ifName, log, callback, null);
}
- public IpReachabilityMonitor(Context context, String ifName, Callback callback,
+ public IpReachabilityMonitor(Context context, String ifName, SharedLog log, Callback callback,
MultinetworkPolicyTracker tracker) throws IllegalArgumentException {
mInterfaceName = ifName;
int ifIndex = -1;
@@ -237,6 +239,7 @@
}
mWakeLock = ((PowerManager) context.getSystemService(Context.POWER_SERVICE)).newWakeLock(
PowerManager.PARTIAL_WAKE_LOCK, TAG + "." + mInterfaceName);
+ mLog = log.forSubComponent(TAG);
mCallback = callback;
mMultinetworkPolicyTracker = tracker;
mNetlinkSocketObserver = new NetlinkSocketObserver();
@@ -403,6 +406,8 @@
break;
}
final int returnValue = probeNeighbor(mInterfaceIndex, target);
+ mLog.log(String.format("put neighbor %s into NUD_PROBE state (rval=%d)",
+ target.getHostAddress(), returnValue));
logEvent(IpReachabilityEvent.PROBE, returnValue);
}
mLastProbeTimeMs = SystemClock.elapsedRealtime();
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 c58b733..faa91b8 100644
--- a/services/tests/servicestests/src/com/android/server/devicepolicy/DevicePolicyManagerTest.java
+++ b/services/tests/servicestests/src/com/android/server/devicepolicy/DevicePolicyManagerTest.java
@@ -2307,11 +2307,6 @@
// restore to the debuggable build state
getServices().buildMock.isDebuggable = true;
- // Always return the default (second arg) when getting system property for long type
- when(getServices().systemProperties.getLong(anyString(), anyLong())).thenAnswer(
- invocation -> invocation.getArguments()[1]
- );
-
// reset to default (0 means the admin is not participating, so default should be returned)
dpm.setRequiredStrongAuthTimeout(admin1, 0);
diff --git a/services/tests/servicestests/src/com/android/server/devicepolicy/DpmTestBase.java b/services/tests/servicestests/src/com/android/server/devicepolicy/DpmTestBase.java
index e0ea573..0c8a787 100644
--- a/services/tests/servicestests/src/com/android/server/devicepolicy/DpmTestBase.java
+++ b/services/tests/servicestests/src/com/android/server/devicepolicy/DpmTestBase.java
@@ -16,9 +16,13 @@
package com.android.server.devicepolicy;
+import static org.mockito.ArgumentMatchers.anyBoolean;
+import static org.mockito.ArgumentMatchers.anyLong;
+import static org.mockito.ArgumentMatchers.anyString;
import static org.mockito.Matchers.anyInt;
import static org.mockito.Matchers.eq;
import static org.mockito.Mockito.doReturn;
+import static org.mockito.Mockito.when;
import android.app.admin.DevicePolicyManager;
import android.content.ComponentName;
@@ -62,6 +66,7 @@
adminAnotherPackage = new ComponentName(DpmMockContext.ANOTHER_PACKAGE_NAME,
"whatever.random.class");
adminNoPerm = new ComponentName(mRealTestContext, DummyDeviceAdmins.AdminNoPerm.class);
+ mockSystemPropertiesToReturnDefault();
}
@Override
@@ -213,4 +218,25 @@
// Set up getPackageInfo().
markPackageAsInstalled(admin.getPackageName(), ai, UserHandle.getUserId(packageUid));
}
+
+ /**
+ * By default, system properties are mocked to return default value. Override the mock if you
+ * want a specific value.
+ */
+ private void mockSystemPropertiesToReturnDefault() {
+ when(getServices().systemProperties.get(
+ anyString(), anyString())).thenAnswer(
+ invocation -> invocation.getArguments()[1]
+ );
+
+ when(getServices().systemProperties.getBoolean(
+ anyString(), anyBoolean())).thenAnswer(
+ invocation -> invocation.getArguments()[1]
+ );
+
+ when(getServices().systemProperties.getLong(
+ anyString(), anyLong())).thenAnswer(
+ invocation -> invocation.getArguments()[1]
+ );
+ }
}
diff --git a/services/tests/servicestests/src/com/android/server/display/DisplayManagerServiceTest.java b/services/tests/servicestests/src/com/android/server/display/DisplayManagerServiceTest.java
index e3ce17b..61df22e 100644
--- a/services/tests/servicestests/src/com/android/server/display/DisplayManagerServiceTest.java
+++ b/services/tests/servicestests/src/com/android/server/display/DisplayManagerServiceTest.java
@@ -29,9 +29,11 @@
import android.view.WindowManagerInternal;
import com.android.server.LocalServices;
+import com.android.server.SystemService;
import com.android.server.display.DisplayDeviceInfo;
import com.android.server.display.DisplayManagerService.SyncRoot;
import com.android.server.display.VirtualDisplayAdapter.SurfaceControlDisplayFactory;
+import com.android.server.lights.LightsManager;
import org.mockito.ArgumentCaptor;
import org.mockito.Mock;
@@ -45,35 +47,51 @@
@SmallTest
public class DisplayManagerServiceTest extends AndroidTestCase {
- private Handler mHandler;
- private DisplayManagerService mDisplayManager;
+ private static final int MSG_REGISTER_DEFAULT_DISPLAY_ADAPTERS = 1;
+ private static final long SHORT_DEFAULT_DISPLAY_TIMEOUT_MILLIS = 10;
+
+ private final DisplayManagerService.Injector mShortMockedInjector =
+ new DisplayManagerService.Injector() {
+ @Override
+ VirtualDisplayAdapter getVirtualDisplayAdapter(SyncRoot syncRoot,
+ Context context, Handler handler, DisplayAdapter.Listener listener) {
+ return mMockVirtualDisplayAdapter;
+ }
+
+ @Override
+ long getDefaultDisplayDelayTimeout() {
+ return SHORT_DEFAULT_DISPLAY_TIMEOUT_MILLIS;
+ }
+ };
+ private final DisplayManagerService.Injector mBasicInjector =
+ new DisplayManagerService.Injector() {
+ @Override
+ VirtualDisplayAdapter getVirtualDisplayAdapter(SyncRoot syncRoot,
+ Context context, Handler handler,
+ DisplayAdapter.Listener displayAdapterListener) {
+ return new VirtualDisplayAdapter(syncRoot, context, handler,
+ displayAdapterListener,
+ (String name, boolean secure) -> mMockDisplayToken);
+ }
+ };
+
@Mock InputManagerInternal mMockInputManagerInternal;
@Mock IVirtualDisplayCallback.Stub mMockAppToken;
@Mock WindowManagerInternal mMockWindowManagerInternal;
+ @Mock LightsManager mMockLightsManager;
@Mock VirtualDisplayAdapter mMockVirtualDisplayAdapter;
@Mock IBinder mMockDisplayToken;
@Override
protected void setUp() throws Exception {
MockitoAnnotations.initMocks(this);
- mDisplayManager = new DisplayManagerService(mContext,
- new DisplayManagerService.Injector() {
- @Override
- VirtualDisplayAdapter getVirtualDisplayAdapter(SyncRoot syncRoot, Context context,
- Handler handler, DisplayAdapter.Listener displayAdapterListener) {
- return new VirtualDisplayAdapter(syncRoot, context, handler, displayAdapterListener,
- (String name, boolean secure) -> mMockDisplayToken);
- }
- });
- mHandler = mDisplayManager.getDisplayHandler();
LocalServices.removeServiceForTest(InputManagerInternal.class);
LocalServices.addService(InputManagerInternal.class, mMockInputManagerInternal);
LocalServices.removeServiceForTest(WindowManagerInternal.class);
LocalServices.addService(WindowManagerInternal.class, mMockWindowManagerInternal);
-
- mDisplayManager.systemReady(false /* safeMode */, false /* onlyCore */);
- mDisplayManager.windowManagerAndInputReady();
+ LocalServices.removeServiceForTest(LightsManager.class);
+ LocalServices.addService(LightsManager.class, mMockLightsManager);
super.setUp();
}
@@ -83,8 +101,14 @@
}
public void testCreateVirtualDisplay_sentToInputManager() throws Exception {
+ DisplayManagerService displayManager =
+ new DisplayManagerService(mContext, mBasicInjector);
+ registerDefaultDisplays(displayManager);
+ displayManager.systemReady(false /* safeMode */, true /* onlyCore */);
+ displayManager.windowManagerAndInputReady();
+
// This is effectively the DisplayManager service published to ServiceManager.
- DisplayManagerService.BinderService bs = mDisplayManager.new BinderService();
+ DisplayManagerService.BinderService bs = displayManager.new BinderService();
String uniqueId = "uniqueId --- Test";
String uniqueIdPrefix = "virtual:" + mContext.getPackageName() + ":";
@@ -99,10 +123,10 @@
"Test Virtual Display", width, height, dpi, null /* surface */, flags /* flags */,
uniqueId);
- mDisplayManager.performTraversalInTransactionFromWindowManagerInternal();
+ displayManager.performTraversalInTransactionFromWindowManagerInternal();
// flush the handler
- mHandler.runWithScissors(() -> {}, 0 /* now */);
+ displayManager.getDisplayHandler().runWithScissors(() -> {}, 0 /* now */);
ArgumentCaptor<List<DisplayViewport>> virtualViewportCaptor =
ArgumentCaptor.forClass(List.class);
@@ -118,8 +142,12 @@
}
public void testCreateVirtualDisplayRotatesWithContent() throws Exception {
+ DisplayManagerService displayManager =
+ new DisplayManagerService(mContext, mBasicInjector);
+ registerDefaultDisplays(displayManager);
+
// This is effectively the DisplayManager service published to ServiceManager.
- DisplayManagerService.BinderService bs = mDisplayManager.new BinderService();
+ DisplayManagerService.BinderService bs = displayManager.new BinderService();
String uniqueId = "uniqueId --- Rotates With Content Test";
int width = 600;
@@ -133,13 +161,76 @@
"Test Virtual Display", width, height, dpi, null /* surface */, flags /* flags */,
uniqueId);
- mDisplayManager.performTraversalInTransactionFromWindowManagerInternal();
+ displayManager.performTraversalInTransactionFromWindowManagerInternal();
// flush the handler
- mHandler.runWithScissors(() -> {}, 0 /* now */);
+ displayManager.getDisplayHandler().runWithScissors(() -> {}, 0 /* now */);
- DisplayDeviceInfo ddi = mDisplayManager.getDisplayDeviceInfoInternal(displayId);
+ DisplayDeviceInfo ddi = displayManager.getDisplayDeviceInfoInternal(displayId);
assertNotNull(ddi);
assertTrue((ddi.flags & DisplayDeviceInfo.FLAG_ROTATES_WITH_CONTENT) != 0);
}
+
+ /**
+ * Tests that the virtual display is created along-side the default display.
+ */
+ public void testStartVirtualDisplayWithDefaultDisplay_Succeeds() throws Exception {
+ DisplayManagerService displayManager =
+ new DisplayManagerService(mContext, mShortMockedInjector);
+ registerDefaultDisplays(displayManager);
+ displayManager.onBootPhase(SystemService.PHASE_WAIT_FOR_DEFAULT_DISPLAY);
+ }
+
+ /**
+ * Tests that we get a Runtime exception when we cannot initialize the default display.
+ */
+ public void testStartVirtualDisplayWithDefDisplay_NoDefaultDisplay() throws Exception {
+ DisplayManagerService displayManager =
+ new DisplayManagerService(mContext, mShortMockedInjector);
+ Handler handler = displayManager.getDisplayHandler();
+ handler.runWithScissors(() -> {}, 0 /* now */);
+
+ try {
+ displayManager.onBootPhase(SystemService.PHASE_WAIT_FOR_DEFAULT_DISPLAY);
+ } catch (RuntimeException e) {
+ return;
+ }
+ fail("Expected DisplayManager to throw RuntimeException when it cannot initialize the"
+ + " default display");
+ }
+
+ /**
+ * Tests that we get a Runtime exception when we cannot initialize the virtual display.
+ */
+ public void testStartVirtualDisplayWithDefDisplay_NoVirtualDisplayAdapter() throws Exception {
+ DisplayManagerService displayManager = new DisplayManagerService(mContext,
+ new DisplayManagerService.Injector() {
+ @Override
+ VirtualDisplayAdapter getVirtualDisplayAdapter(SyncRoot syncRoot,
+ Context context, Handler handler, DisplayAdapter.Listener listener) {
+ return null; // return null for the adapter. This should cause a failure.
+ }
+
+ @Override
+ long getDefaultDisplayDelayTimeout() {
+ return SHORT_DEFAULT_DISPLAY_TIMEOUT_MILLIS;
+ }
+ });
+ try {
+ displayManager.onBootPhase(SystemService.PHASE_WAIT_FOR_DEFAULT_DISPLAY);
+ } catch (RuntimeException e) {
+ return;
+ }
+ fail("Expected DisplayManager to throw RuntimeException when it cannot initialize the"
+ + " virtual display adapter");
+ }
+
+ private void registerDefaultDisplays(DisplayManagerService displayManager) {
+ Handler handler = displayManager.getDisplayHandler();
+ // Would prefer to call displayManager.onStart() directly here but it performs binderService
+ // registration which triggers security exceptions when running from a test.
+ handler.sendEmptyMessage(MSG_REGISTER_DEFAULT_DISPLAY_ADAPTERS);
+ // flush the handler
+ handler.runWithScissors(() -> {}, 0 /* now */);
+ }
}
diff --git a/services/tests/servicestests/src/com/android/server/timezone/PackageStatusStorageTest.java b/services/tests/servicestests/src/com/android/server/timezone/PackageStatusStorageTest.java
index dd56072..b57cac0 100644
--- a/services/tests/servicestests/src/com/android/server/timezone/PackageStatusStorageTest.java
+++ b/services/tests/servicestests/src/com/android/server/timezone/PackageStatusStorageTest.java
@@ -25,6 +25,8 @@
import android.support.test.filters.SmallTest;
import java.io.File;
+import java.io.PrintWriter;
+import java.io.StringWriter;
import static junit.framework.Assert.assertTrue;
import static org.junit.Assert.assertEquals;
@@ -228,4 +230,27 @@
assertFalse(writeOk2);
assertEquals(expectedPackageStatus, mPackageStatusStorage.getPackageStatus());
}
+
+ @Test
+ public void dump() {
+ StringWriter stringWriter = new StringWriter();
+ PrintWriter printWriter = new PrintWriter(stringWriter);
+
+ // Dump initial state.
+ mPackageStatusStorage.dump(printWriter);
+
+ // No crash and it does something.
+ assertFalse(stringWriter.toString().isEmpty());
+
+ // Reset
+ stringWriter.getBuffer().setLength(0);
+ assertTrue(stringWriter.toString().isEmpty());
+
+ // Store something.
+ mPackageStatusStorage.generateCheckToken(VALID_PACKAGE_VERSIONS);
+
+ mPackageStatusStorage.dump(printWriter);
+
+ assertFalse(stringWriter.toString().isEmpty());
+ }
}
diff --git a/services/tests/servicestests/src/com/android/server/timezone/PackageTrackerTest.java b/services/tests/servicestests/src/com/android/server/timezone/PackageTrackerTest.java
index 4c7680b..a972e4f 100644
--- a/services/tests/servicestests/src/com/android/server/timezone/PackageTrackerTest.java
+++ b/services/tests/servicestests/src/com/android/server/timezone/PackageTrackerTest.java
@@ -30,6 +30,9 @@
import android.support.test.InstrumentationRegistry;
import android.support.test.filters.SmallTest;
+import java.io.PrintWriter;
+import java.io.StringWriter;
+
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotNull;
@@ -1174,6 +1177,16 @@
assertFalse(token1.equals(token2));
}
+ @Test
+ public void dump() {
+ StringWriter stringWriter = new StringWriter();
+ PrintWriter printWriter = new PrintWriter(stringWriter);
+
+ mPackageTracker.dump(printWriter);
+
+ assertFalse(stringWriter.toString().isEmpty());
+ }
+
private void simulatePackageInstallation(PackageVersions packageVersions) throws Exception {
configureApplicationsValidManifests(packageVersions);
diff --git a/services/tests/servicestests/src/com/android/server/timezone/RulesManagerServiceTest.java b/services/tests/servicestests/src/com/android/server/timezone/RulesManagerServiceTest.java
index 1407e26..2887e3b 100644
--- a/services/tests/servicestests/src/com/android/server/timezone/RulesManagerServiceTest.java
+++ b/services/tests/servicestests/src/com/android/server/timezone/RulesManagerServiceTest.java
@@ -32,11 +32,15 @@
import android.os.ParcelFileDescriptor;
import java.io.File;
+import java.io.FileDescriptor;
import java.io.FileOutputStream;
import java.io.IOException;
+import java.io.PrintWriter;
import java.util.concurrent.Executor;
import javax.annotation.Nullable;
+import libcore.io.IoUtils;
+
import static com.android.server.timezone.RulesManagerService.REQUIRED_UPDATER_PERMISSION;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
@@ -52,6 +56,7 @@
import static org.mockito.Mockito.reset;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.verifyNoMoreInteractions;
+import static org.mockito.Mockito.verifyZeroInteractions;
import static org.mockito.Mockito.when;
/**
@@ -724,6 +729,97 @@
verifyPackageTrackerCalled(null /* token */, true /* success */);
}
+ @Test
+ public void dump_noPermission() throws Exception {
+ when(mMockPermissionHelper.checkDumpPermission(any(String.class), any(PrintWriter.class)))
+ .thenReturn(false);
+
+ doDumpCallAndCapture(mRulesManagerService, null);
+ verifyZeroInteractions(mMockPackageTracker, mMockTimeZoneDistroInstaller);
+ }
+
+ @Test
+ public void dump_emptyArgs() throws Exception {
+ doSuccessfulDumpCall(mRulesManagerService, new String[0]);
+
+ // Verify the package tracker was consulted.
+ verify(mMockPackageTracker).dump(any(PrintWriter.class));
+ }
+
+ @Test
+ public void dump_nullArgs() throws Exception {
+ doSuccessfulDumpCall(mRulesManagerService, null);
+ // Verify the package tracker was consulted.
+ verify(mMockPackageTracker).dump(any(PrintWriter.class));
+ }
+
+ @Test
+ public void dump_unknownArgs() throws Exception {
+ String dumpedTextUnknownArgs = doSuccessfulDumpCall(
+ mRulesManagerService, new String[] { "foo", "bar"});
+
+ // Verify the package tracker was consulted.
+ verify(mMockPackageTracker).dump(any(PrintWriter.class));
+
+ String dumpedTextZeroArgs = doSuccessfulDumpCall(mRulesManagerService, null);
+ assertEquals(dumpedTextZeroArgs, dumpedTextUnknownArgs);
+ }
+
+ @Test
+ public void dump_formatState() throws Exception {
+ // Just expect these to not throw exceptions, not return nothing, and not interact with the
+ // package tracker.
+ doSuccessfulDumpCall(mRulesManagerService, dumpFormatArgs("p"));
+ doSuccessfulDumpCall(mRulesManagerService, dumpFormatArgs("s"));
+ doSuccessfulDumpCall(mRulesManagerService, dumpFormatArgs("c"));
+ doSuccessfulDumpCall(mRulesManagerService, dumpFormatArgs("i"));
+ doSuccessfulDumpCall(mRulesManagerService, dumpFormatArgs("o"));
+ doSuccessfulDumpCall(mRulesManagerService, dumpFormatArgs("t"));
+ doSuccessfulDumpCall(mRulesManagerService, dumpFormatArgs("a"));
+ doSuccessfulDumpCall(mRulesManagerService, dumpFormatArgs("z" /* Unknown */));
+ doSuccessfulDumpCall(mRulesManagerService, dumpFormatArgs("piscotz"));
+
+ verifyZeroInteractions(mMockPackageTracker);
+ }
+
+ private static String[] dumpFormatArgs(String argsString) {
+ return new String[] { "-format_state", argsString};
+ }
+
+ private String doSuccessfulDumpCall(RulesManagerService rulesManagerService, String[] args)
+ throws Exception {
+ when(mMockPermissionHelper.checkDumpPermission(any(String.class), any(PrintWriter.class)))
+ .thenReturn(true);
+
+ // Set up the mocks to return (arbitrary) information about the current device state.
+ when(mMockTimeZoneDistroInstaller.getSystemRulesVersion()).thenReturn("2017a");
+ when(mMockTimeZoneDistroInstaller.getInstalledDistroVersion()).thenReturn(
+ new DistroVersion(2, 3, "2017b", 4));
+ when(mMockTimeZoneDistroInstaller.getStagedDistroOperation()).thenReturn(
+ StagedDistroOperation.install(new DistroVersion(5, 6, "2017c", 7)));
+
+ // Do the dump call.
+ String dumpedOutput = doDumpCallAndCapture(rulesManagerService, args);
+
+ assertFalse(dumpedOutput.isEmpty());
+
+ return dumpedOutput;
+ }
+
+ private static String doDumpCallAndCapture(
+ RulesManagerService rulesManagerService, String[] args) throws IOException {
+ File file = File.createTempFile("dump", null);
+ try {
+ try (FileOutputStream fos = new FileOutputStream(file)) {
+ FileDescriptor fd = fos.getFD();
+ rulesManagerService.dump(fd, args);
+ }
+ return IoUtils.readFileAsString(file.getAbsolutePath());
+ } finally {
+ file.delete();
+ }
+ }
+
private void verifyNoPackageTrackerCallsMade() {
verifyNoMoreInteractions(mMockPackageTracker);
reset(mMockPackageTracker);
diff --git a/services/tests/servicestests/src/com/android/server/wm/WindowStateTests.java b/services/tests/servicestests/src/com/android/server/wm/WindowStateTests.java
index c809c32..67db5f4 100644
--- a/services/tests/servicestests/src/com/android/server/wm/WindowStateTests.java
+++ b/services/tests/servicestests/src/com/android/server/wm/WindowStateTests.java
@@ -218,8 +218,7 @@
root.mAttrs.flags |= WindowManager.LayoutParams.FLAG_TURN_SCREEN_ON;
root.mTurnOnScreen = false;
- root.prepareWindowToDisplayDuringRelayout(new MergedConfiguration(),
- wasVisible /*wasVisible*/);
+ root.prepareWindowToDisplayDuringRelayout(wasVisible /*wasVisible*/);
assertTrue(root.mTurnOnScreen);
}
}
diff --git a/telecomm/java/android/telecom/DisconnectCause.java b/telecomm/java/android/telecom/DisconnectCause.java
index e6b567e..dcf5c27 100644
--- a/telecomm/java/android/telecom/DisconnectCause.java
+++ b/telecomm/java/android/telecom/DisconnectCause.java
@@ -83,6 +83,13 @@
*/
public static final String REASON_WIFI_ON_BUT_WFC_OFF = "REASON_WIFI_ON_BUT_WFC_OFF";
+ /**
+ * Reason code (returned via {@link #getReason()}), which indicates that the video telephony
+ * call was disconnected because IMS access is blocked.
+ * @hide
+ */
+ public static final String REASON_IMS_ACCESS_BLOCKED = "REASON_IMS_ACCESS_BLOCKED";
+
private int mDisconnectCode;
private CharSequence mDisconnectLabel;
private CharSequence mDisconnectDescription;
diff --git a/telecomm/java/android/telecom/PhoneAccount.java b/telecomm/java/android/telecom/PhoneAccount.java
index 31bb064..691e7cf 100644
--- a/telecomm/java/android/telecom/PhoneAccount.java
+++ b/telecomm/java/android/telecom/PhoneAccount.java
@@ -127,6 +127,8 @@
/**
* Boolean {@link PhoneAccount} extras key (see {@link PhoneAccount#getExtras()}) which
* indicates whether a Self-Managed {@link PhoneAccount} should log its calls to the call log.
+ * Self-Managed {@link PhoneAccount}s are responsible for their own notifications, so the system
+ * will not create a notification when a missed call is logged.
* <p>
* By default, Self-Managed {@link PhoneAccount}s do not log their calls to the call log.
* Setting this extra to {@code true} provides a means for them to log their calls.
diff --git a/telephony/java/android/telephony/MbmsDownloadManager.java b/telephony/java/android/telephony/MbmsDownloadManager.java
index b3f46c2..231f2c8 100644
--- a/telephony/java/android/telephony/MbmsDownloadManager.java
+++ b/telephony/java/android/telephony/MbmsDownloadManager.java
@@ -93,19 +93,21 @@
/**
* Integer extra indicating the result code of the download. One of
* {@link #RESULT_SUCCESSFUL}, {@link #RESULT_EXPIRED}, or {@link #RESULT_CANCELLED}.
+ * TODO: Not systemapi.
*/
public static final String EXTRA_RESULT = "android.telephony.mbms.extra.RESULT";
/**
* Extra containing the {@link android.telephony.mbms.FileInfo} for which the download result
* is for. Must not be null.
- * TODO: future systemapi (here and and all extras) except the two for the app intent
+ * TODO: Not systemapi.
*/
public static final String EXTRA_FILE_INFO = "android.telephony.mbms.extra.FILE_INFO";
/**
* Extra containing the {@link DownloadRequest} for which the download result or file
* descriptor request is for. Must not be null.
+ * TODO: future systemapi (here and and all extras) except the three for the app intent
*/
public static final String EXTRA_REQUEST = "android.telephony.mbms.extra.REQUEST";
@@ -180,6 +182,7 @@
* {@link android.telephony.mbms.DownloadRequest.Builder#setAppIntent(Intent)}.
* Will always be set to a non-null value if {@link #EXTRA_RESULT} is set to
* {@link #RESULT_SUCCESSFUL}.
+ * TODO: Not systemapi.
*/
public static final String EXTRA_COMPLETED_FILE_URI =
"android.telephony.mbms.extra.COMPLETED_FILE_URI";
@@ -554,7 +557,7 @@
private File getDownloadRequestTokenPath(DownloadRequest request) {
File tempFileLocation = MbmsUtils.getEmbmsTempFileDirForService(mContext,
- request.getFileServiceInfo());
+ request.getFileServiceId());
String downloadTokenFileName = request.getHash()
+ MbmsDownloadReceiver.DOWNLOAD_TOKEN_SUFFIX;
return new File(tempFileLocation, downloadTokenFileName);
diff --git a/telephony/java/android/telephony/mbms/DownloadRequest.java b/telephony/java/android/telephony/mbms/DownloadRequest.java
index 345729d..01e0bbd 100644
--- a/telephony/java/android/telephony/mbms/DownloadRequest.java
+++ b/telephony/java/android/telephony/mbms/DownloadRequest.java
@@ -21,7 +21,14 @@
import android.os.Parcel;
import android.os.Parcelable;
import android.util.Base64;
+import android.util.Log;
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.io.ObjectInputStream;
+import java.io.ObjectOutputStream;
+import java.io.Serializable;
import java.net.URISyntaxException;
import java.nio.charset.StandardCharsets;
import java.security.MessageDigest;
@@ -35,24 +42,52 @@
public class DownloadRequest implements Parcelable {
// Version code used to keep token calculation consistent.
private static final int CURRENT_VERSION = 1;
+ private static final String LOG_TAG = "MbmsDownloadRequest";
+
+ /**
+ * Maximum permissible length for the app's download-completion intent, when serialized via
+ * {@link Intent#toUri(int)}.
+ */
+ public static final int MAX_APP_INTENT_SIZE = 50000;
+
+ /**
+ * Maximum permissible length for the app's destination path, when serialized via
+ * {@link Uri#toString()}.
+ */
+ public static final int MAX_DESTINATION_URI_SIZE = 50000;
/** @hide */
+ private static class OpaqueDataContainer implements Serializable {
+ private final String destinationUri;
+ private final String appIntent;
+ private final int version;
+
+ public OpaqueDataContainer(String destinationUri, String appIntent, int version) {
+ this.destinationUri = destinationUri;
+ this.appIntent = appIntent;
+ this.version = version;
+ }
+ }
+
public static class Builder {
- private int id;
- private FileServiceInfo serviceInfo;
+ private String fileServiceId;
private Uri source;
private Uri dest;
private int subscriptionId;
private String appIntent;
private int version = CURRENT_VERSION;
- public Builder setId(int id) {
- this.id = id;
+ public Builder setServiceInfo(FileServiceInfo serviceInfo) {
+ fileServiceId = serviceInfo.getServiceId();
return this;
}
- public Builder setServiceInfo(FileServiceInfo serviceInfo) {
- this.serviceInfo = serviceInfo;
+ /**
+ * @hide
+ * TODO: systemapi
+ */
+ public Builder setServiceId(String serviceId) {
+ fileServiceId = serviceId;
return this;
}
@@ -62,6 +97,10 @@
}
public Builder setDest(Uri dest) {
+ if (dest.toString().length() > MAX_DESTINATION_URI_SIZE) {
+ throw new IllegalArgumentException("Destination uri must not exceed length " +
+ MAX_DESTINATION_URI_SIZE);
+ }
this.dest = dest;
return this;
}
@@ -73,33 +112,53 @@
public Builder setAppIntent(Intent intent) {
this.appIntent = intent.toUri(0);
+ if (this.appIntent.length() > MAX_APP_INTENT_SIZE) {
+ throw new IllegalArgumentException("App intent must not exceed length " +
+ MAX_APP_INTENT_SIZE);
+ }
return this;
}
- public Builder setVersion(int version) {
- this.version = version;
+ /**
+ * For use by middleware only
+ * TODO: systemapi
+ * @hide
+ */
+ public Builder setOpaqueData(byte[] data) {
+ try {
+ ObjectInputStream stream = new ObjectInputStream(new ByteArrayInputStream(data));
+ OpaqueDataContainer dataContainer = (OpaqueDataContainer) stream.readObject();
+ version = dataContainer.version;
+ appIntent = dataContainer.appIntent;
+ dest = Uri.parse(dataContainer.destinationUri);
+ } catch (IOException e) {
+ // Really should never happen
+ Log.e(LOG_TAG, "Got IOException trying to parse opaque data");
+ throw new IllegalArgumentException(e);
+ } catch (ClassNotFoundException e) {
+ Log.e(LOG_TAG, "Got ClassNotFoundException trying to parse opaque data");
+ throw new IllegalArgumentException(e);
+ }
return this;
}
public DownloadRequest build() {
- return new DownloadRequest(id, serviceInfo, source, dest,
+ return new DownloadRequest(fileServiceId, source, dest,
subscriptionId, appIntent, version);
}
}
- private final int downloadId;
- private final FileServiceInfo fileServiceInfo;
+ private final String fileServiceId;
private final Uri sourceUri;
private final Uri destinationUri;
private final int subscriptionId;
private final String serializedResultIntentForApp;
private final int version;
- private DownloadRequest(int id, FileServiceInfo serviceInfo,
+ private DownloadRequest(String fileServiceId,
Uri source, Uri dest,
int sub, String appIntent, int version) {
- downloadId = id;
- fileServiceInfo = serviceInfo;
+ this.fileServiceId = fileServiceId;
sourceUri = source;
destinationUri = dest;
subscriptionId = sub;
@@ -112,8 +171,7 @@
}
private DownloadRequest(DownloadRequest dr) {
- downloadId = dr.downloadId;
- fileServiceInfo = dr.fileServiceInfo;
+ fileServiceId = dr.fileServiceId;
sourceUri = dr.sourceUri;
destinationUri = dr.destinationUri;
subscriptionId = dr.subscriptionId;
@@ -122,8 +180,7 @@
}
private DownloadRequest(Parcel in) {
- downloadId = in.readInt();
- fileServiceInfo = in.readParcelable(getClass().getClassLoader());
+ fileServiceId = in.readString();
sourceUri = in.readParcelable(getClass().getClassLoader());
destinationUri = in.readParcelable(getClass().getClassLoader());
subscriptionId = in.readInt();
@@ -136,8 +193,7 @@
}
public void writeToParcel(Parcel out, int flags) {
- out.writeInt(downloadId);
- out.writeParcelable(fileServiceInfo, flags);
+ out.writeString(fileServiceId);
out.writeParcelable(sourceUri, flags);
out.writeParcelable(destinationUri, flags);
out.writeInt(subscriptionId);
@@ -145,12 +201,8 @@
out.writeInt(version);
}
- public int getDownloadId() {
- return downloadId;
- }
-
- public FileServiceInfo getFileServiceInfo() {
- return fileServiceInfo;
+ public String getFileServiceId() {
+ return fileServiceId;
}
public Uri getSourceUri() {
@@ -173,6 +225,27 @@
}
}
+ /**
+ * @hide
+ * TODO: systemapi
+ */
+ public byte[] getOpaqueData() {
+ try {
+ ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
+ ObjectOutputStream stream = new ObjectOutputStream(byteArrayOutputStream);
+ OpaqueDataContainer container = new OpaqueDataContainer(
+ destinationUri.toString(), serializedResultIntentForApp, version);
+ stream.writeObject(container);
+ stream.flush();
+ return byteArrayOutputStream.toByteArray();
+ } catch (IOException e) {
+ // Really should never happen
+ Log.e(LOG_TAG, "Got IOException trying to serialize opaque data");
+ return null;
+ }
+ }
+
+ /** @hide */
public int getVersion() {
return version;
}
@@ -228,10 +301,9 @@
return false;
}
DownloadRequest request = (DownloadRequest) o;
- return downloadId == request.downloadId &&
- subscriptionId == request.subscriptionId &&
+ return subscriptionId == request.subscriptionId &&
version == request.version &&
- Objects.equals(fileServiceInfo, request.fileServiceInfo) &&
+ Objects.equals(fileServiceId, request.fileServiceId) &&
Objects.equals(sourceUri, request.sourceUri) &&
Objects.equals(destinationUri, request.destinationUri) &&
Objects.equals(serializedResultIntentForApp, request.serializedResultIntentForApp);
@@ -239,7 +311,7 @@
@Override
public int hashCode() {
- return Objects.hash(downloadId, fileServiceInfo, sourceUri, destinationUri,
+ return Objects.hash(fileServiceId, sourceUri, destinationUri,
subscriptionId, serializedResultIntentForApp, version);
}
}
diff --git a/telephony/java/android/telephony/mbms/MbmsDownloadReceiver.java b/telephony/java/android/telephony/mbms/MbmsDownloadReceiver.java
index 5bc53a8..3617165 100644
--- a/telephony/java/android/telephony/mbms/MbmsDownloadReceiver.java
+++ b/telephony/java/android/telephony/mbms/MbmsDownloadReceiver.java
@@ -83,7 +83,7 @@
public static final int RESULT_DOWNLOAD_FINALIZATION_ERROR = 4;
/**
- * Indicates that the manager weas unable to generate one or more of the requested file
+ * Indicates that the manager was unable to generate one or more of the requested file
* descriptors.
* This is a non-fatal result code -- some file descriptors may still be generated, but there
* is no guarantee that they will be the same number as requested.
@@ -149,7 +149,7 @@
DownloadRequest request = intent.getParcelableExtra(MbmsDownloadManager.EXTRA_REQUEST);
String expectedTokenFileName = request.getHash() + DOWNLOAD_TOKEN_SUFFIX;
File expectedTokenFile = new File(
- MbmsUtils.getEmbmsTempFileDirForService(context, request.getFileServiceInfo()),
+ MbmsUtils.getEmbmsTempFileDirForService(context, request.getFileServiceId()),
expectedTokenFileName);
if (!expectedTokenFile.exists()) {
Log.w(LOG_TAG, "Supplied download request does not match a token that we have. " +
@@ -201,22 +201,24 @@
Uri destinationUri = request.getDestinationUri();
Uri finalTempFile = intent.getParcelableExtra(MbmsDownloadManager.EXTRA_FINAL_URI);
- if (!verifyTempFilePath(context, request.getFileServiceInfo(), finalTempFile)) {
+ if (!verifyTempFilePath(context, request.getFileServiceId(), finalTempFile)) {
Log.w(LOG_TAG, "Download result specified an invalid temp file " + finalTempFile);
setResultCode(RESULT_DOWNLOAD_FINALIZATION_ERROR);
return;
}
- String relativePath = calculateDestinationFileRelativePath(request,
- (FileInfo) intent.getParcelableExtra(MbmsDownloadManager.EXTRA_FILE_INFO));
+ FileInfo completedFileInfo =
+ (FileInfo) intent.getParcelableExtra(MbmsDownloadManager.EXTRA_FILE_INFO);
+ String relativePath = calculateDestinationFileRelativePath(request, completedFileInfo);
Uri finalFileLocation = moveTempFile(finalTempFile, destinationUri, relativePath);
if (finalFileLocation == null) {
Log.w(LOG_TAG, "Failed to move temp file to final destination");
- // TODO: how do we notify the app of this?
setResultCode(RESULT_DOWNLOAD_FINALIZATION_ERROR);
+ return;
}
intentForApp.putExtra(MbmsDownloadManager.EXTRA_COMPLETED_FILE_URI, finalFileLocation);
+ intentForApp.putExtra(MbmsDownloadManager.EXTRA_FILE_INFO, completedFileInfo);
context.sendBroadcast(intentForApp);
setResultCode(RESULT_OK);
@@ -235,7 +237,7 @@
}
for (Uri tempFileUri : tempFiles) {
- if (verifyTempFilePath(context, request.getFileServiceInfo(), tempFileUri)) {
+ if (verifyTempFilePath(context, request.getFileServiceId(), tempFileUri)) {
File tempFile = new File(tempFileUri.getSchemeSpecificPart());
tempFile.delete();
}
@@ -276,7 +278,8 @@
private ArrayList<UriPathPair> generateFreshTempFiles(Context context,
FileServiceInfo serviceInfo,
int freshFdCount) {
- File tempFileDir = MbmsUtils.getEmbmsTempFileDirForService(context, serviceInfo);
+ File tempFileDir = MbmsUtils.getEmbmsTempFileDirForService(context,
+ serviceInfo.getServiceId());
if (!tempFileDir.exists()) {
tempFileDir.mkdirs();
}
@@ -327,7 +330,7 @@
ArrayList<UriPathPair> result = new ArrayList<>(pausedFiles.size());
for (Uri fileUri : pausedFiles) {
- if (!verifyTempFilePath(context, serviceInfo, fileUri)) {
+ if (!verifyTempFilePath(context, serviceInfo.getServiceId(), fileUri)) {
Log.w(LOG_TAG, "Supplied file " + fileUri + " is not a valid temp file to resume");
setResultCode(RESULT_TEMP_FILE_GENERATION_ERROR);
continue;
@@ -351,7 +354,8 @@
private void cleanupTempFiles(Context context, Intent intent) {
FileServiceInfo serviceInfo =
intent.getParcelableExtra(MbmsDownloadManager.EXTRA_SERVICE_INFO);
- File tempFileDir = MbmsUtils.getEmbmsTempFileDirForService(context, serviceInfo);
+ File tempFileDir = MbmsUtils.getEmbmsTempFileDirForService(context,
+ serviceInfo.getServiceId());
List<Uri> filesInUse =
intent.getParcelableArrayListExtra(MbmsDownloadManager.EXTRA_TEMP_FILES_IN_USE);
File[] filesToDelete = tempFileDir.listFiles(new FileFilter() {
@@ -439,7 +443,7 @@
return null;
}
- private static boolean verifyTempFilePath(Context context, FileServiceInfo serviceInfo,
+ private static boolean verifyTempFilePath(Context context, String serviceId,
Uri filePath) {
if (!ContentResolver.SCHEME_FILE.equals(filePath.getScheme())) {
Log.w(LOG_TAG, "Uri " + filePath + " does not have a file scheme");
@@ -454,7 +458,7 @@
}
if (!MbmsUtils.isContainedIn(
- MbmsUtils.getEmbmsTempFileDirForService(context, serviceInfo), tempFile)) {
+ MbmsUtils.getEmbmsTempFileDirForService(context, serviceId), tempFile)) {
return false;
}
diff --git a/telephony/java/android/telephony/mbms/MbmsUtils.java b/telephony/java/android/telephony/mbms/MbmsUtils.java
index b28950e..1e03fb9 100644
--- a/telephony/java/android/telephony/mbms/MbmsUtils.java
+++ b/telephony/java/android/telephony/mbms/MbmsUtils.java
@@ -89,10 +89,9 @@
/**
* Returns a File linked to the directory used to store temp files for this file service
*/
- public static File getEmbmsTempFileDirForService(Context context, FileServiceInfo serviceInfo) {
+ public static File getEmbmsTempFileDirForService(Context context, String serviceId) {
File embmsTempFileDir = MbmsTempFileProvider.getEmbmsTempFileDir(context);
- String tempFileDirName = String.valueOf(serviceInfo.getServiceId());
- return new File(embmsTempFileDir, tempFileDirName);
+ return new File(embmsTempFileDir, serviceId);
}
}
diff --git a/test-runner/Android.mk b/test-runner/Android.mk
index b41dadb..9053b23 100644
--- a/test-runner/Android.mk
+++ b/test-runner/Android.mk
@@ -30,6 +30,20 @@
include $(BUILD_JAVA_LIBRARY)
+# Build the repackaged.android.test.runner library
+# ================================================
+include $(CLEAR_VARS)
+
+LOCAL_SRC_FILES := $(call all-java-files-under, src)
+
+LOCAL_JAVA_LIBRARIES := core-oj core-libart framework legacy-test
+
+LOCAL_JARJAR_RULES := $(LOCAL_PATH)/../legacy-test/jarjar-rules.txt
+
+LOCAL_MODULE:= repackaged.android.test.runner
+
+include $(BUILD_STATIC_JAVA_LIBRARY)
+
# Generate the stub source files for android.test.runner.stubs
# ============================================================
include $(CLEAR_VARS)
diff --git a/tests/net/java/android/net/nsd/NsdManagerTest.java b/tests/net/java/android/net/nsd/NsdManagerTest.java
index adf6998..f77608f 100644
--- a/tests/net/java/android/net/nsd/NsdManagerTest.java
+++ b/tests/net/java/android/net/nsd/NsdManagerTest.java
@@ -349,7 +349,6 @@
chan.connect(mContext, this, msg.replyTo);
chan.sendMessage(AsyncChannel.CMD_CHANNEL_FULLY_CONNECTED);
}
-
}
public static MockServiceHandler create(Context context) {
diff --git a/tests/net/java/android/net/util/SharedLogTest.java b/tests/net/java/android/net/util/SharedLogTest.java
index 3957cb0..d46facf 100644
--- a/tests/net/java/android/net/util/SharedLogTest.java
+++ b/tests/net/java/android/net/util/SharedLogTest.java
@@ -33,8 +33,8 @@
@RunWith(AndroidJUnit4.class)
@SmallTest
public class SharedLogTest {
- private static final String TIMESTAMP_PATTERN = "\\d{2}:\\d{2}:\\d{2}\\.\\d{3}";
- private static final String TIMESTAMP = "HH:MM:SS.xxx";
+ private static final String TIMESTAMP_PATTERN = "\\d{2}:\\d{2}:\\d{2}";
+ private static final String TIMESTAMP = "HH:MM:SS";
@Test
public void testBasicOperation() {
@@ -85,7 +85,7 @@
String got = lines[i];
String want = expected[i];
assertTrue(String.format("'%s' did not contain '%s'", got, want), got.endsWith(want));
- assertTrue(String.format("'%s' did not contain a HH:MM:SS.xxx timestamp", got),
+ assertTrue(String.format("'%s' did not contain a %s timestamp", got, TIMESTAMP),
got.replaceFirst(TIMESTAMP_PATTERN, TIMESTAMP).contains(TIMESTAMP));
}
}
diff --git a/tests/net/java/com/android/internal/util/TestUtils.java b/tests/net/java/com/android/internal/util/TestUtils.java
new file mode 100644
index 0000000..c9fa340
--- /dev/null
+++ b/tests/net/java/com/android/internal/util/TestUtils.java
@@ -0,0 +1,54 @@
+/*
+ * 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.internal.util;
+
+import static org.junit.Assert.fail;
+
+import android.os.ConditionVariable;
+import android.os.Handler;
+import android.os.HandlerThread;
+import android.os.Looper;
+
+public final class TestUtils {
+ private TestUtils() { }
+
+ /**
+ * Block until the given Handler thread becomes idle, or until timeoutMs has passed.
+ */
+ public static void waitForIdleHandler(HandlerThread handlerThread, long timeoutMs) {
+ // TODO: convert to getThreadHandler once it is available on aosp
+ waitForIdleLooper(handlerThread.getLooper(), timeoutMs);
+ }
+
+ /**
+ * Block until the given Looper becomes idle, or until timeoutMs has passed.
+ */
+ public static void waitForIdleLooper(Looper looper, long timeoutMs) {
+ waitForIdleHandler(new Handler(looper), timeoutMs);
+ }
+
+ /**
+ * Block until the given Handler becomes idle, or until timeoutMs has passed.
+ */
+ public static void waitForIdleHandler(Handler handler, long timeoutMs) {
+ final ConditionVariable cv = new ConditionVariable();
+ handler.post(() -> cv.open());
+ if (!cv.block(timeoutMs)) {
+ fail(handler.toString() + " did not become idle after " + timeoutMs + " ms");
+ }
+ }
+}
diff --git a/tests/net/java/com/android/server/ConnectivityServiceTest.java b/tests/net/java/com/android/server/ConnectivityServiceTest.java
index 198ddc6..bed1c32 100644
--- a/tests/net/java/com/android/server/ConnectivityServiceTest.java
+++ b/tests/net/java/com/android/server/ConnectivityServiceTest.java
@@ -19,10 +19,13 @@
import static android.net.ConnectivityManager.CONNECTIVITY_ACTION;
import static android.net.ConnectivityManager.TYPE_ETHERNET;
import static android.net.ConnectivityManager.TYPE_MOBILE;
+import static android.net.ConnectivityManager.TYPE_NONE;
import static android.net.ConnectivityManager.TYPE_WIFI;
import static android.net.ConnectivityManager.getNetworkTypeName;
import static android.net.NetworkCapabilities.*;
+import static com.android.internal.util.TestUtils.waitForIdleHandler;
+
import static org.mockito.Mockito.anyBoolean;
import static org.mockito.Mockito.anyInt;
import static org.mockito.Mockito.eq;
@@ -112,6 +115,7 @@
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.function.BooleanSupplier;
+import java.util.function.Predicate;
/**
* Tests for {@link ConnectivityService}.
@@ -212,20 +216,8 @@
}
}
- /**
- * Block until the given handler becomes idle, or until timeoutMs has passed.
- */
- private static void waitForIdleHandler(HandlerThread handlerThread, int timeoutMs) {
- final ConditionVariable cv = new ConditionVariable();
- final Handler handler = new Handler(handlerThread.getLooper());
- handler.post(() -> cv.open());
- if (!cv.block(timeoutMs)) {
- fail("HandlerThread " + handlerThread.getName() +
- " did not become idle after " + timeoutMs + " ms");
- }
- }
-
- public void waitForIdle(int timeoutMs) {
+ public void waitForIdle(int timeoutMsAsInt) {
+ long timeoutMs = timeoutMsAsInt;
waitForIdleHandler(mService.mHandlerThread, timeoutMs);
waitForIdle(mCellNetworkAgent, timeoutMs);
waitForIdle(mWiFiNetworkAgent, timeoutMs);
@@ -233,7 +225,7 @@
waitForIdleHandler(mService.mHandlerThread, timeoutMs);
}
- public void waitForIdle(MockNetworkAgent agent, int timeoutMs) {
+ public void waitForIdle(MockNetworkAgent agent, long timeoutMs) {
if (agent == null) {
return;
}
@@ -327,6 +319,9 @@
case TRANSPORT_CELLULAR:
mScore = 50;
break;
+ case TRANSPORT_WIFI_AWARE:
+ mScore = 20;
+ break;
default:
throw new UnsupportedOperationException("unimplemented network type");
}
@@ -408,6 +403,15 @@
* @param validated Indicate if network should pretend to be validated.
*/
public void connect(boolean validated) {
+ connect(validated, true);
+ }
+
+ /**
+ * Transition this NetworkAgent to CONNECTED state.
+ * @param validated Indicate if network should pretend to be validated.
+ * @param hasInternet Indicate if network should pretend to have NET_CAPABILITY_INTERNET.
+ */
+ public void connect(boolean validated, boolean hasInternet) {
assertEquals("MockNetworkAgents can only be connected once",
mNetworkInfo.getDetailedState(), DetailedState.IDLE);
assertFalse(mNetworkCapabilities.hasCapability(NET_CAPABILITY_INTERNET));
@@ -430,7 +434,9 @@
};
mCm.registerNetworkCallback(request, callback);
}
- addCapability(NET_CAPABILITY_INTERNET);
+ if (hasInternet) {
+ addCapability(NET_CAPABILITY_INTERNET);
+ }
connectWithoutInternet();
@@ -784,7 +790,10 @@
* Fails if TIMEOUT_MS goes by before {@code conditionVariable} opens.
*/
static private void waitFor(ConditionVariable conditionVariable) {
- assertTrue(conditionVariable.block(TIMEOUT_MS));
+ if (conditionVariable.block(TIMEOUT_MS)) {
+ return;
+ }
+ fail("ConditionVariable was blocked for more than " + TIMEOUT_MS + "ms");
}
@Override
@@ -842,7 +851,7 @@
case TRANSPORT_CELLULAR:
return TYPE_MOBILE;
default:
- throw new IllegalStateException("Unknown transport " + transport);
+ return TYPE_NONE;
}
}
@@ -853,6 +862,9 @@
// Test getActiveNetwork()
assertNotNull(mCm.getActiveNetwork());
assertEquals(mCm.getActiveNetwork(), mCm.getActiveNetworkForUid(Process.myUid()));
+ if (!NetworkCapabilities.isValidTransport(transport)) {
+ throw new IllegalStateException("Unknown transport " + transport);
+ }
switch (transport) {
case TRANSPORT_WIFI:
assertEquals(mCm.getActiveNetwork(), mWiFiNetworkAgent.getNetwork());
@@ -861,7 +873,7 @@
assertEquals(mCm.getActiveNetwork(), mCellNetworkAgent.getNetwork());
break;
default:
- throw new IllegalStateException("Unknown transport" + transport);
+ break;
}
// Test getNetworkInfo(Network)
assertNotNull(mCm.getNetworkInfo(mCm.getActiveNetwork()));
@@ -879,7 +891,7 @@
assertNull(mCm.getActiveNetwork());
assertNull(mCm.getActiveNetworkForUid(Process.myUid()));
// Test getAllNetworks()
- assertEquals(0, mCm.getAllNetworks().length);
+ assertEmpty(mCm.getAllNetworks());
}
/**
@@ -920,7 +932,7 @@
mCellNetworkAgent.connect(true);
waitFor(cv);
verifyActiveNetwork(TRANSPORT_CELLULAR);
- assertEquals(2, mCm.getAllNetworks().length);
+ assertLength(2, mCm.getAllNetworks());
assertTrue(mCm.getAllNetworks()[0].equals(mCm.getActiveNetwork()) ||
mCm.getAllNetworks()[1].equals(mCm.getActiveNetwork()));
assertTrue(mCm.getAllNetworks()[0].equals(mWiFiNetworkAgent.getNetwork()) ||
@@ -930,7 +942,7 @@
mWiFiNetworkAgent.connect(true);
waitFor(cv);
verifyActiveNetwork(TRANSPORT_WIFI);
- assertEquals(2, mCm.getAllNetworks().length);
+ assertLength(2, mCm.getAllNetworks());
assertTrue(mCm.getAllNetworks()[0].equals(mCm.getActiveNetwork()) ||
mCm.getAllNetworks()[1].equals(mCm.getActiveNetwork()));
assertTrue(mCm.getAllNetworks()[0].equals(mCellNetworkAgent.getNetwork()) ||
@@ -938,9 +950,9 @@
// Test cellular linger timeout.
waitFor(mCellNetworkAgent.getDisconnectedCV());
waitForIdle();
- assertEquals(1, mCm.getAllNetworks().length);
+ assertLength(1, mCm.getAllNetworks());
verifyActiveNetwork(TRANSPORT_WIFI);
- assertEquals(1, mCm.getAllNetworks().length);
+ assertLength(1, mCm.getAllNetworks());
assertEquals(mCm.getAllNetworks()[0], mCm.getActiveNetwork());
// Test WiFi disconnect.
cv = waitForConnectivityBroadcasts(1);
@@ -1281,7 +1293,26 @@
return expectCallback(state, agent, TIMEOUT_MS);
}
- void expectAvailableCallbacks(MockNetworkAgent agent, boolean expectSuspended, int timeoutMs) {
+ CallbackInfo expectCallbackLike(Predicate<CallbackInfo> fn) {
+ return expectCallbackLike(fn, TIMEOUT_MS);
+ }
+
+ CallbackInfo expectCallbackLike(Predicate<CallbackInfo> fn, int timeoutMs) {
+ int timeLeft = timeoutMs;
+ while (timeLeft > 0) {
+ long start = SystemClock.elapsedRealtime();
+ CallbackInfo info = nextCallback(timeLeft);
+ if (fn.test(info)) {
+ return info;
+ }
+ timeLeft -= (SystemClock.elapsedRealtime() - start);
+ }
+ fail("Did not receive expected callback after " + timeoutMs + "ms");
+ return null;
+ }
+
+ void expectAvailableCallbacks(
+ MockNetworkAgent agent, boolean expectSuspended, int timeoutMs) {
expectCallback(CallbackState.AVAILABLE, agent, timeoutMs);
if (expectSuspended) {
expectCallback(CallbackState.SUSPENDED, agent, timeoutMs);
@@ -1838,26 +1869,18 @@
@SmallTest
public void testNoMutableNetworkRequests() throws Exception {
PendingIntent pendingIntent = PendingIntent.getBroadcast(mContext, 0, new Intent("a"), 0);
- NetworkRequest.Builder builder = new NetworkRequest.Builder();
- builder.addCapability(NET_CAPABILITY_VALIDATED);
- try {
- mCm.requestNetwork(builder.build(), new NetworkCallback());
- fail();
- } catch (IllegalArgumentException expected) {}
- try {
- mCm.requestNetwork(builder.build(), pendingIntent);
- fail();
- } catch (IllegalArgumentException expected) {}
- builder = new NetworkRequest.Builder();
- builder.addCapability(NET_CAPABILITY_CAPTIVE_PORTAL);
- try {
- mCm.requestNetwork(builder.build(), new NetworkCallback());
- fail();
- } catch (IllegalArgumentException expected) {}
- try {
- mCm.requestNetwork(builder.build(), pendingIntent);
- fail();
- } catch (IllegalArgumentException expected) {}
+ NetworkRequest request1 = new NetworkRequest.Builder()
+ .addCapability(NET_CAPABILITY_VALIDATED)
+ .build();
+ NetworkRequest request2 = new NetworkRequest.Builder()
+ .addCapability(NET_CAPABILITY_CAPTIVE_PORTAL)
+ .build();
+
+ Class<IllegalArgumentException> expected = IllegalArgumentException.class;
+ assertException(() -> { mCm.requestNetwork(request1, new NetworkCallback()); }, expected);
+ assertException(() -> { mCm.requestNetwork(request1, pendingIntent); }, expected);
+ assertException(() -> { mCm.requestNetwork(request2, new NetworkCallback()); }, expected);
+ assertException(() -> { mCm.requestNetwork(request2, pendingIntent); }, expected);
}
@SmallTest
@@ -1869,7 +1892,7 @@
mCellNetworkAgent.connectWithoutInternet();
waitFor(cv);
waitForIdle();
- assertEquals(0, mCm.getAllNetworks().length);
+ assertEmpty(mCm.getAllNetworks());
verifyNoNetwork();
// Test bringing up validated WiFi.
@@ -2543,7 +2566,7 @@
assertTrue(testFactory.getMyStartRequested());
// Bring up cell data and check that the factory stops looking.
- assertEquals(1, mCm.getAllNetworks().length);
+ assertLength(1, mCm.getAllNetworks());
mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
testFactory.expectAddRequests(2); // Because the cell request changes score twice.
mCellNetworkAgent.connect(true);
@@ -2554,7 +2577,7 @@
// Check that cell data stays up.
waitForIdle();
verifyActiveNetwork(TRANSPORT_WIFI);
- assertEquals(2, mCm.getAllNetworks().length);
+ assertLength(2, mCm.getAllNetworks());
// Turn off mobile data always on and expect the request to disappear...
testFactory.expectRemoveRequests(1);
@@ -2563,7 +2586,7 @@
// ... and cell data to be torn down.
cellNetworkCallback.expectCallback(CallbackState.LOST, mCellNetworkAgent);
- assertEquals(1, mCm.getAllNetworks().length);
+ assertLength(1, mCm.getAllNetworks());
testFactory.unregister();
mCm.unregisterNetworkCallback(cellNetworkCallback);
@@ -2784,19 +2807,17 @@
NetworkRequest nr = new NetworkRequest.Builder().addTransportType(
NetworkCapabilities.TRANSPORT_WIFI).build();
final TestNetworkCallback networkCallback = new TestNetworkCallback();
- final int requestTimeoutMs = 100;
+ final int requestTimeoutMs = 50;
mCm.requestNetwork(nr, networkCallback, requestTimeoutMs);
mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
mWiFiNetworkAgent.connect(false);
- final int assertTimeoutMs = 150;
+ final int assertTimeoutMs = 100;
networkCallback.expectAvailableCallbacks(mWiFiNetworkAgent, false, assertTimeoutMs);
- sleepFor(20);
mWiFiNetworkAgent.disconnect();
networkCallback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
- // pass timeout and validate that UNAVAILABLE is not called
- sleepFor(100);
+ // Validate that UNAVAILABLE is not called
networkCallback.assertNoCallback();
}
@@ -2823,24 +2844,20 @@
}
/**
- * Validate that when a network request is unregistered (cancelled) the time-out for that
- * request doesn't trigger the onUnavailable() callback.
+ * Validate that when a network request is unregistered (cancelled), no posterior event can
+ * trigger the callback.
*/
@SmallTest
- public void testTimedoutAfterUnregisteredNetworkRequest() {
+ public void testNoCallbackAfterUnregisteredNetworkRequest() {
NetworkRequest nr = new NetworkRequest.Builder().addTransportType(
NetworkCapabilities.TRANSPORT_WIFI).build();
final TestNetworkCallback networkCallback = new TestNetworkCallback();
final int timeoutMs = 10;
+
mCm.requestNetwork(nr, networkCallback, timeoutMs);
-
- // remove request
mCm.unregisterNetworkCallback(networkCallback);
-
- // pass timeout and validate that no callbacks
- // Note: doesn't validate that nothing called from CS since even if called the CM already
- // unregisters the callback and won't pass it through!
- sleepFor(15);
+ // Regardless of the timeout, unregistering the callback in ConnectivityManager ensures
+ // that this callback will not be called.
networkCallback.assertNoCallback();
// create a network satisfying request - validate that request not triggered
@@ -3259,12 +3276,87 @@
}
}
- /* test utilities */
- // TODO: eliminate all usages of sleepFor and replace by proper timeouts/waitForIdle.
- static private void sleepFor(int ms) {
+ @SmallTest
+ public void testNetworkInfoOfTypeNone() {
+ ConditionVariable broadcastCV = waitForConnectivityBroadcasts(1);
+
+ verifyNoNetwork();
+ MockNetworkAgent lowpanNetwork = new MockNetworkAgent(TRANSPORT_WIFI_AWARE);
+ assertNull(mCm.getActiveNetworkInfo());
+
+ Network[] allNetworks = mCm.getAllNetworks();
+ assertLength(1, allNetworks);
+ Network network = allNetworks[0];
+ NetworkCapabilities capabilities = mCm.getNetworkCapabilities(network);
+ assertTrue(capabilities.hasTransport(TRANSPORT_WIFI_AWARE));
+
+ final NetworkRequest request =
+ new NetworkRequest.Builder().addTransportType(TRANSPORT_WIFI_AWARE).build();
+ final TestNetworkCallback callback = new TestNetworkCallback();
+ mCm.registerNetworkCallback(request, callback);
+
+ // Bring up lowpan.
+ lowpanNetwork.connect(false, false);
+ callback.expectAvailableCallbacks(lowpanNetwork);
+
+ assertNull(mCm.getActiveNetworkInfo());
+ assertNull(mCm.getActiveNetwork());
+ // TODO: getAllNetworkInfo is dirty and returns a non-empty array rght from the start
+ // of this test. Fix it and uncomment the assert below.
+ //assertEmpty(mCm.getAllNetworkInfo());
+
+ // Disconnect lowpan.
+ lowpanNetwork.disconnect();
+ callback.expectCallback(CallbackState.LOST, lowpanNetwork);
+ mCm.unregisterNetworkCallback(callback);
+
+ verifyNoNetwork();
+ if (broadcastCV.block(10)) {
+ fail("expected no broadcast, but got CONNECTIVITY_ACTION broadcast");
+ }
+ }
+
+ @SmallTest
+ public void testDeprecatedAndUnsupportedOperations() throws Exception {
+ final int TYPE_NONE = ConnectivityManager.TYPE_NONE;
+ assertNull(mCm.getNetworkInfo(TYPE_NONE));
+ assertNull(mCm.getNetworkForType(TYPE_NONE));
+ assertNull(mCm.getLinkProperties(TYPE_NONE));
+ assertFalse(mCm.isNetworkSupported(TYPE_NONE));
+
+ assertException(() -> { mCm.networkCapabilitiesForType(TYPE_NONE); },
+ IllegalArgumentException.class);
+
+ Class<UnsupportedOperationException> unsupported = UnsupportedOperationException.class;
+ assertException(() -> { mCm.startUsingNetworkFeature(TYPE_WIFI, ""); }, unsupported);
+ assertException(() -> { mCm.stopUsingNetworkFeature(TYPE_WIFI, ""); }, unsupported);
+ // TODO: let test context have configuration application target sdk version
+ // and test that pre-M requesting for TYPE_NONE sends back APN_REQUEST_FAILED
+ assertException(() -> { mCm.startUsingNetworkFeature(TYPE_NONE, ""); }, unsupported);
+ assertException(() -> { mCm.stopUsingNetworkFeature(TYPE_NONE, ""); }, unsupported);
+ assertException(() -> { mCm.requestRouteToHostAddress(TYPE_NONE, null); }, unsupported);
+ }
+
+ private static <T> void assertEmpty(T[] ts) {
+ int length = ts.length;
+ assertEquals("expected empty array, but length was " + length, 0, length);
+ }
+
+ private static <T> void assertLength(int expected, T[] got) {
+ int length = got.length;
+ assertEquals(String.format("expected array of length %s, but length was %s for %s",
+ expected, length, Arrays.toString(got)), expected, length);
+ }
+
+ private static <T> void assertException(Runnable block, Class<T> expected) {
try {
- Thread.sleep(ms);
- } catch (InterruptedException e) {
+ block.run();
+ fail("Expected exception of type " + expected);
+ } catch (Exception got) {
+ if (!got.getClass().equals(expected)) {
+ fail("Expected exception of type " + expected + " but got " + got);
+ }
+ return;
}
}
}
diff --git a/tests/net/java/com/android/server/connectivity/TetheringTest.java b/tests/net/java/com/android/server/connectivity/TetheringTest.java
index ab874ce..acf9e8f7 100644
--- a/tests/net/java/com/android/server/connectivity/TetheringTest.java
+++ b/tests/net/java/com/android/server/connectivity/TetheringTest.java
@@ -16,6 +16,11 @@
package com.android.server.connectivity;
+import static android.hardware.usb.UsbManager.USB_CONFIGURED;
+import static android.hardware.usb.UsbManager.USB_CONNECTED;
+import static android.hardware.usb.UsbManager.USB_FUNCTION_RNDIS;
+import static android.net.ConnectivityManager.TETHERING_WIFI;
+import static android.net.ConnectivityManager.TETHERING_USB;
import static android.net.wifi.WifiManager.IFACE_IP_MODE_LOCAL_ONLY;
import static android.net.wifi.WifiManager.IFACE_IP_MODE_TETHERED;
import static android.net.wifi.WifiManager.EXTRA_WIFI_AP_INTERFACE_NAME;
@@ -133,6 +138,7 @@
public Object getSystemService(String name) {
if (Context.CONNECTIVITY_SERVICE.equals(name)) return mConnectivityManager;
if (Context.WIFI_SERVICE.equals(name)) return mWifiManager;
+ if (Context.USB_SERVICE.equals(name)) return mUsbManager;
return super.getSystemService(name);
}
}
@@ -145,7 +151,7 @@
when(mResources.getStringArray(com.android.internal.R.array.config_tether_usb_regexs))
.thenReturn(new String[0]);
when(mResources.getStringArray(com.android.internal.R.array.config_tether_wifi_regexs))
- .thenReturn(new String[]{ "test_wlan\\d" });
+ .thenReturn(new String[]{ "test_wlan\\d", "test_rndis\\d" });
when(mResources.getStringArray(com.android.internal.R.array.config_tether_bluetooth_regexs))
.thenReturn(new String[0]);
when(mResources.getIntArray(com.android.internal.R.array.config_tether_upstream_types))
@@ -245,6 +251,14 @@
mServiceContext.sendStickyBroadcastAsUser(intent, UserHandle.ALL);
}
+ private void sendUsbBroadcast(boolean connected, boolean configured, boolean rndisFunction) {
+ final Intent intent = new Intent(UsbManager.ACTION_USB_STATE);
+ intent.putExtra(USB_CONNECTED, connected);
+ intent.putExtra(USB_CONFIGURED, configured);
+ intent.putExtra(USB_FUNCTION_RNDIS, rndisFunction);
+ mServiceContext.sendStickyBroadcastAsUser(intent, UserHandle.ALL);
+ }
+
private void verifyInterfaceServingModeStarted() throws Exception {
verify(mNMService, times(1)).getInterfaceConfig(mTestIfname);
verify(mNMService, times(1))
@@ -287,6 +301,32 @@
}
@Test
+ public void testUsbConfiguredBroadcastStartsTethering() throws Exception {
+ when(mConnectivityManager.isTetheringSupported()).thenReturn(true);
+
+ // Emulate pressing the USB tethering button in Settings UI.
+ mTethering.startTethering(TETHERING_USB, null, false);
+ mLooper.dispatchAll();
+ verify(mUsbManager, times(1)).setCurrentFunction(UsbManager.USB_FUNCTION_RNDIS, false);
+
+ // Pretend we receive a USB connected broadcast. Here we also pretend
+ // that the RNDIS function is somehow enabled, so that we see if we
+ // might trip ourselves up.
+ sendUsbBroadcast(true, false, true);
+ mLooper.dispatchAll();
+ // This should produce no activity of any kind.
+ verifyNoMoreInteractions(mConnectivityManager);
+ verifyNoMoreInteractions(mNMService);
+
+ // Pretend we then receive USB configured broadcast.
+ sendUsbBroadcast(true, true, true);
+ mLooper.dispatchAll();
+ // Now we should see the start of tethering mechanics (in this case:
+ // tetherMatchingInterfaces() which starts by fetching all interfaces).
+ verify(mNMService, times(1)).listInterfaces();
+ }
+
+ @Test
public void failingLocalOnlyHotspotLegacyApBroadcastWithIfaceStatusChanged() throws Exception {
failingLocalOnlyHotspotLegacyApBroadcast(true);
}
@@ -366,7 +406,7 @@
when(mWifiManager.startSoftAp(any(WifiConfiguration.class))).thenReturn(true);
// Emulate pressing the WiFi tethering button.
- mTethering.startTethering(ConnectivityManager.TETHERING_WIFI, null, false);
+ mTethering.startTethering(TETHERING_WIFI, null, false);
mLooper.dispatchAll();
verify(mWifiManager, times(1)).startSoftAp(null);
verifyNoMoreInteractions(mWifiManager);
@@ -394,7 +434,7 @@
when(mWifiManager.startSoftAp(any(WifiConfiguration.class))).thenReturn(true);
// Emulate pressing the WiFi tethering button.
- mTethering.startTethering(ConnectivityManager.TETHERING_WIFI, null, false);
+ mTethering.startTethering(TETHERING_WIFI, null, false);
mLooper.dispatchAll();
verify(mWifiManager, times(1)).startSoftAp(null);
verifyNoMoreInteractions(mWifiManager);
@@ -440,7 +480,7 @@
/////
// Emulate pressing the WiFi tethering button.
- mTethering.stopTethering(ConnectivityManager.TETHERING_WIFI);
+ mTethering.stopTethering(TETHERING_WIFI);
mLooper.dispatchAll();
verify(mWifiManager, times(1)).stopSoftAp();
verifyNoMoreInteractions(mWifiManager);
@@ -476,7 +516,7 @@
doThrow(new RemoteException()).when(mNMService).setIpForwardingEnabled(true);
// Emulate pressing the WiFi tethering button.
- mTethering.startTethering(ConnectivityManager.TETHERING_WIFI, null, false);
+ mTethering.startTethering(TETHERING_WIFI, null, false);
mLooper.dispatchAll();
verify(mWifiManager, times(1)).startSoftAp(null);
verifyNoMoreInteractions(mWifiManager);
diff --git a/tests/net/java/com/android/server/connectivity/tethering/UpstreamNetworkMonitorTest.java b/tests/net/java/com/android/server/connectivity/tethering/UpstreamNetworkMonitorTest.java
index fb5c577..69c93b1 100644
--- a/tests/net/java/com/android/server/connectivity/tethering/UpstreamNetworkMonitorTest.java
+++ b/tests/net/java/com/android/server/connectivity/tethering/UpstreamNetworkMonitorTest.java
@@ -44,6 +44,9 @@
import android.net.ConnectivityManager;
import android.net.ConnectivityManager.NetworkCallback;
import android.net.IConnectivityManager;
+import android.net.IpPrefix;
+import android.net.LinkAddress;
+import android.net.LinkProperties;
import android.net.Network;
import android.net.NetworkCapabilities;
import android.net.NetworkRequest;
@@ -66,6 +69,7 @@
import java.util.ArrayList;
import java.util.Collection;
+import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
@@ -77,6 +81,9 @@
public class UpstreamNetworkMonitorTest {
private static final int EVENT_UNM_UPDATE = 1;
+ private static final boolean INCLUDES = true;
+ private static final boolean EXCLUDES = false;
+
@Mock private Context mContext;
@Mock private IConnectivityManager mCS;
@Mock private SharedLog mLog;
@@ -94,7 +101,8 @@
mCM = spy(new TestConnectivityManager(mContext, mCS));
mSM = new TestStateMachine();
- mUNM = new UpstreamNetworkMonitor(mSM, EVENT_UNM_UPDATE, (ConnectivityManager) mCM, mLog);
+ mUNM = new UpstreamNetworkMonitor(
+ (ConnectivityManager) mCM, mSM, mLog, EVENT_UNM_UPDATE);
}
@After public void tearDown() throws Exception {
@@ -315,6 +323,101 @@
assertTrue(netReq.networkCapabilities.hasCapability(NET_CAPABILITY_DUN));
}
+ @Test
+ public void testOffloadExemptPrefixes() throws Exception {
+ mUNM.start();
+
+ // [0] Test minimum set of exempt prefixes.
+ Set<IpPrefix> exempt = mUNM.getOffloadExemptPrefixes();
+ final String[] MINSET = {
+ "127.0.0.0/8", "169.254.0.0/16",
+ "::/3", "fe80::/64", "fc00::/7", "ff00::/8",
+ };
+ assertPrefixSet(exempt, INCLUDES, MINSET);
+ final Set<String> alreadySeen = new HashSet<>();
+ Collections.addAll(alreadySeen, MINSET);
+ assertEquals(alreadySeen.size(), exempt.size());
+
+ // [1] Pretend Wi-Fi connects.
+ final TestNetworkAgent wifiAgent = new TestNetworkAgent(mCM, TRANSPORT_WIFI);
+ final LinkProperties wifiLp = new LinkProperties();
+ wifiLp.setInterfaceName("wlan0");
+ final String[] WIFI_ADDRS = {
+ "fe80::827a:bfff:fe6f:374d", "100.112.103.18",
+ "2001:db8:4:fd00:827a:bfff:fe6f:374d",
+ "2001:db8:4:fd00:6dea:325a:fdae:4ef4",
+ "fd6a:a640:60bf:e985::123", // ULA address for good measure.
+ };
+ for (String addrStr : WIFI_ADDRS) {
+ final String cidr = addrStr.contains(":") ? "/64" : "/20";
+ wifiLp.addLinkAddress(new LinkAddress(addrStr + cidr));
+ }
+ wifiAgent.fakeConnect();
+ wifiAgent.sendLinkProperties(wifiLp);
+
+ exempt = mUNM.getOffloadExemptPrefixes();
+ assertPrefixSet(exempt, INCLUDES, alreadySeen);
+ final String[] wifiLinkPrefixes = {
+ // Excludes link-local as that's already tested within MINSET.
+ "100.112.96.0/20", "2001:db8:4:fd00::/64", "fd6a:a640:60bf:e985::/64",
+ };
+ assertPrefixSet(exempt, INCLUDES, wifiLinkPrefixes);
+ Collections.addAll(alreadySeen, wifiLinkPrefixes);
+ assertEquals(alreadySeen.size(), exempt.size());
+
+ // [2] Pretend mobile connects.
+ final TestNetworkAgent cellAgent = new TestNetworkAgent(mCM, TRANSPORT_CELLULAR);
+ final LinkProperties cellLp = new LinkProperties();
+ cellLp.setInterfaceName("rmnet_data0");
+ final String[] CELL_ADDRS = {
+ "10.102.211.48", "2001:db8:0:1:b50e:70d9:10c9:433d",
+ };
+ for (String addrStr : CELL_ADDRS) {
+ final String cidr = addrStr.contains(":") ? "/64" : "/27";
+ cellLp.addLinkAddress(new LinkAddress(addrStr + cidr));
+ }
+ cellAgent.fakeConnect();
+ cellAgent.sendLinkProperties(cellLp);
+
+ exempt = mUNM.getOffloadExemptPrefixes();
+ assertPrefixSet(exempt, INCLUDES, alreadySeen);
+ final String[] cellLinkPrefixes = { "10.102.211.32/27", "2001:db8:0:1::/64" };
+ assertPrefixSet(exempt, INCLUDES, cellLinkPrefixes);
+ Collections.addAll(alreadySeen, cellLinkPrefixes);
+ assertEquals(alreadySeen.size(), exempt.size());
+
+ // [3] Pretend DUN connects.
+ final TestNetworkAgent dunAgent = new TestNetworkAgent(mCM, TRANSPORT_CELLULAR);
+ dunAgent.networkCapabilities.addCapability(NET_CAPABILITY_DUN);
+ final LinkProperties dunLp = new LinkProperties();
+ dunLp.setInterfaceName("rmnet_data1");
+ final String[] DUN_ADDRS = {
+ "192.0.2.48", "2001:db8:1:2:b50e:70d9:10c9:433d",
+ };
+ for (String addrStr : DUN_ADDRS) {
+ final String cidr = addrStr.contains(":") ? "/64" : "/27";
+ cellLp.addLinkAddress(new LinkAddress(addrStr + cidr));
+ }
+ dunAgent.fakeConnect();
+ dunAgent.sendLinkProperties(dunLp);
+
+ exempt = mUNM.getOffloadExemptPrefixes();
+ assertPrefixSet(exempt, INCLUDES, alreadySeen);
+ final String[] dunLinkPrefixes = { "192.0.2.32/27", "2001:db8:1:2::/64" };
+ assertPrefixSet(exempt, INCLUDES, dunLinkPrefixes);
+ Collections.addAll(alreadySeen, dunLinkPrefixes);
+ assertEquals(alreadySeen.size(), exempt.size());
+
+ // [4] Pretend Wi-Fi disconnected. It's addresses/prefixes should no
+ // longer be included (should be properly removed).
+ wifiAgent.fakeDisconnect();
+ exempt = mUNM.getOffloadExemptPrefixes();
+ assertPrefixSet(exempt, INCLUDES, MINSET);
+ assertPrefixSet(exempt, EXCLUDES, wifiLinkPrefixes);
+ assertPrefixSet(exempt, INCLUDES, cellLinkPrefixes);
+ assertPrefixSet(exempt, INCLUDES, dunLinkPrefixes);
+ }
+
private void assertSatisfiesLegacyType(int legacyType, NetworkState ns) {
if (legacyType == TYPE_NONE) {
assertTrue(ns == null);
@@ -476,6 +579,12 @@
cb.onLost(networkId);
}
}
+
+ public void sendLinkProperties(LinkProperties lp) {
+ for (NetworkCallback cb : cm.listening.keySet()) {
+ cb.onLinkPropertiesChanged(networkId, lp);
+ }
+ }
}
public static class TestStateMachine extends StateMachine {
@@ -504,4 +613,19 @@
static NetworkCapabilities copy(NetworkCapabilities nc) {
return new NetworkCapabilities(nc);
}
+
+ static void assertPrefixSet(Set<IpPrefix> prefixes, boolean expectation, String... expected) {
+ final Set<String> expectedSet = new HashSet<>();
+ Collections.addAll(expectedSet, expected);
+ assertPrefixSet(prefixes, expectation, expectedSet);
+ }
+
+ static void assertPrefixSet(Set<IpPrefix> prefixes, boolean expectation, Set<String> expected) {
+ for (String expectedPrefix : expected) {
+ final String errStr = expectation ? "did not find" : "found";
+ assertEquals(
+ String.format("Failed expectation: %s prefix: %s", errStr, expectedPrefix),
+ expectation, prefixes.contains(new IpPrefix(expectedPrefix)));
+ }
+ }
}
diff --git a/tests/net/java/com/android/server/net/NetworkStatsObserversTest.java b/tests/net/java/com/android/server/net/NetworkStatsObserversTest.java
index 92dcdac..2be5dae 100644
--- a/tests/net/java/com/android/server/net/NetworkStatsObserversTest.java
+++ b/tests/net/java/com/android/server/net/NetworkStatsObserversTest.java
@@ -27,6 +27,8 @@
import static android.net.TrafficStats.MB_IN_BYTES;
import static android.text.format.DateUtils.MINUTE_IN_MILLIS;
+import static com.android.internal.util.TestUtils.waitForIdleHandler;
+
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
@@ -56,7 +58,6 @@
import com.android.internal.net.VpnInfo;
import com.android.server.net.NetworkStatsService;
-import com.android.server.net.NetworkStatsServiceTest.IdleableHandlerThread;
import com.android.server.net.NetworkStatsServiceTest.LatchedHandler;
import java.util.ArrayList;
@@ -102,7 +103,7 @@
private long mElapsedRealtime;
- private IdleableHandlerThread mObserverHandlerThread;
+ private HandlerThread mObserverHandlerThread;
private Handler mObserverNoopHandler;
private LatchedHandler mHandler;
@@ -118,7 +119,7 @@
public void setUp() throws Exception {
MockitoAnnotations.initMocks(this);
- mObserverHandlerThread = new IdleableHandlerThread("HandlerThread");
+ mObserverHandlerThread = new HandlerThread("HandlerThread");
mObserverHandlerThread.start();
final Looper observerLooper = mObserverHandlerThread.getLooper();
mStatsObservers = new NetworkStatsObservers() {
@@ -319,7 +320,7 @@
xtSnapshot, uidSnapshot, mActiveIfaces, mActiveUidIfaces,
VPN_INFO, TEST_START);
waitForObserverToIdle();
- assertEquals(NetworkStatsManager.CALLBACK_LIMIT_REACHED, mHandler.mLastMessageType);
+ assertEquals(NetworkStatsManager.CALLBACK_LIMIT_REACHED, mHandler.lastMessageType);
}
@Test
@@ -356,7 +357,7 @@
xtSnapshot, uidSnapshot, mActiveIfaces, mActiveUidIfaces,
VPN_INFO, TEST_START);
waitForObserverToIdle();
- assertEquals(NetworkStatsManager.CALLBACK_LIMIT_REACHED, mHandler.mLastMessageType);
+ assertEquals(NetworkStatsManager.CALLBACK_LIMIT_REACHED, mHandler.lastMessageType);
}
@Test
@@ -429,7 +430,7 @@
xtSnapshot, uidSnapshot, mActiveIfaces, mActiveUidIfaces,
VPN_INFO, TEST_START);
waitForObserverToIdle();
- assertEquals(NetworkStatsManager.CALLBACK_LIMIT_REACHED, mHandler.mLastMessageType);
+ assertEquals(NetworkStatsManager.CALLBACK_LIMIT_REACHED, mHandler.lastMessageType);
}
@Test
@@ -470,19 +471,7 @@
}
private void waitForObserverToIdle() {
- waitForIdleLooper(mObserverHandlerThread.getLooper(), WAIT_TIMEOUT_MS);
- waitForIdleLooper(mHandler.getLooper(), WAIT_TIMEOUT_MS);
+ waitForIdleHandler(mObserverHandlerThread, WAIT_TIMEOUT_MS);
+ waitForIdleHandler(mHandler, WAIT_TIMEOUT_MS);
}
-
- // TODO: unify with ConnectivityService.waitForIdleHandler and
- // NetworkServiceStatsTest.IdleableHandlerThread
- private static void waitForIdleLooper(Looper looper, long timeoutMs) {
- final ConditionVariable cv = new ConditionVariable();
- final Handler handler = new Handler(looper);
- handler.post(() -> cv.open());
- if (!cv.block(timeoutMs)) {
- fail("Looper did not become idle after " + timeoutMs + " ms");
- }
- }
-
}
diff --git a/tests/net/java/com/android/server/net/NetworkStatsServiceTest.java b/tests/net/java/com/android/server/net/NetworkStatsServiceTest.java
index 029693f..feb46d3 100644
--- a/tests/net/java/com/android/server/net/NetworkStatsServiceTest.java
+++ b/tests/net/java/com/android/server/net/NetworkStatsServiceTest.java
@@ -45,6 +45,7 @@
import static android.text.format.DateUtils.WEEK_IN_MILLIS;
import static com.android.server.net.NetworkStatsService.ACTION_NETWORK_STATS_POLL;
+import static com.android.internal.util.TestUtils.waitForIdleHandler;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
@@ -154,7 +155,7 @@
private @Mock IConnectivityManager mConnManager;
private @Mock IBinder mBinder;
private @Mock AlarmManager mAlarmManager;
- private IdleableHandlerThread mHandlerThread;
+ private HandlerThread mHandlerThread;
private Handler mHandler;
private NetworkStatsService mService;
@@ -181,7 +182,7 @@
mServiceContext, mNetManager, mAlarmManager, wakeLock, mTime,
TelephonyManager.getDefault(), mSettings, new NetworkStatsObservers(),
mStatsDir, getBaseDir(mStatsDir));
- mHandlerThread = new IdleableHandlerThread("HandlerThread");
+ mHandlerThread = new HandlerThread("HandlerThread");
mHandlerThread.start();
Handler.Callback callback = new NetworkStatsService.HandlerCallback(mService);
mHandler = new Handler(mHandlerThread.getLooper(), callback);
@@ -886,7 +887,7 @@
// Send dummy message to make sure that any previous message has been handled
mHandler.sendMessage(mHandler.obtainMessage(-1));
- mHandlerThread.waitForIdle(WAIT_TIMEOUT);
+ waitForIdleHandler(mHandler, WAIT_TIMEOUT);
@@ -908,7 +909,7 @@
assertNetworkTotal(sTemplateWifi, 1024L, 1L, 2048L, 2L, 0);
// make sure callback has not being called
- assertEquals(INVALID_TYPE, latchedHandler.mLastMessageType);
+ assertEquals(INVALID_TYPE, latchedHandler.lastMessageType);
// and bump forward again, with counters going higher. this is
// important, since it will trigger the data usage callback
@@ -926,7 +927,7 @@
// Wait for the caller to ack receipt of CALLBACK_LIMIT_REACHED
assertTrue(cv.block(WAIT_TIMEOUT));
- assertEquals(NetworkStatsManager.CALLBACK_LIMIT_REACHED, latchedHandler.mLastMessageType);
+ assertEquals(NetworkStatsManager.CALLBACK_LIMIT_REACHED, latchedHandler.lastMessageType);
cv.close();
// Allow binder to disconnect
@@ -937,7 +938,7 @@
// Wait for the caller to ack receipt of CALLBACK_RELEASED
assertTrue(cv.block(WAIT_TIMEOUT));
- assertEquals(NetworkStatsManager.CALLBACK_RELEASED, latchedHandler.mLastMessageType);
+ assertEquals(NetworkStatsManager.CALLBACK_RELEASED, latchedHandler.lastMessageType);
// Make sure that the caller binder gets disconnected
verify(mBinder).unlinkToDeath(any(IBinder.DeathRecipient.class), anyInt());
@@ -1203,12 +1204,12 @@
mServiceContext.sendBroadcast(new Intent(ACTION_NETWORK_STATS_POLL));
// Send dummy message to make sure that any previous message has been handled
mHandler.sendMessage(mHandler.obtainMessage(-1));
- mHandlerThread.waitForIdle(WAIT_TIMEOUT);
+ waitForIdleHandler(mHandler, WAIT_TIMEOUT);
}
static class LatchedHandler extends Handler {
private final ConditionVariable mCv;
- int mLastMessageType = INVALID_TYPE;
+ int lastMessageType = INVALID_TYPE;
LatchedHandler(Looper looper, ConditionVariable cv) {
super(looper);
@@ -1217,49 +1218,9 @@
@Override
public void handleMessage(Message msg) {
- mLastMessageType = msg.what;
+ lastMessageType = msg.what;
mCv.open();
super.handleMessage(msg);
}
}
-
- /**
- * A subclass of HandlerThread that allows callers to wait for it to become idle. waitForIdle
- * will return immediately if the handler is already idle.
- */
- static class IdleableHandlerThread extends HandlerThread {
- private IdleHandler mIdleHandler;
-
- public IdleableHandlerThread(String name) {
- super(name);
- }
-
- public void waitForIdle(long timeoutMs) {
- final ConditionVariable cv = new ConditionVariable();
- final MessageQueue queue = getLooper().getQueue();
-
- synchronized (queue) {
- if (queue.isIdle()) {
- return;
- }
-
- assertNull("BUG: only one idle handler allowed", mIdleHandler);
- mIdleHandler = new IdleHandler() {
- public boolean queueIdle() {
- cv.open();
- mIdleHandler = null;
- return false; // Remove the handler.
- }
- };
- queue.addIdleHandler(mIdleHandler);
- }
-
- if (!cv.block(timeoutMs)) {
- fail("HandlerThread " + getName() + " did not become idle after " + timeoutMs
- + " ms");
- queue.removeIdleHandler(mIdleHandler);
- }
- }
- }
-
}