Merge "Do not commit session twice"
diff --git a/Android.bp b/Android.bp
index db0f0ea..107d0ac 100644
--- a/Android.bp
+++ b/Android.bp
@@ -27,6 +27,7 @@
java_library {
name: "framework",
+ installable: true,
srcs: [
// From build/make/core/pathmap.mk FRAMEWORK_BASE_SUBDIRS
@@ -761,6 +762,7 @@
// ============================================================
java_library {
name: "ext",
+ installable: true,
no_framework_libs: true,
static_libs: [
"libphonenumber-platform",
@@ -1192,6 +1194,24 @@
" -showAnnotation android.annotation.TestApi",
}
+droiddoc {
+ name: "hiddenapi-mappings",
+ defaults: ["framework-docs-default"],
+ arg_files: [
+ "core/res/AndroidManifest.xml",
+ ":api-version-xml",
+ "core/java/overview.html",
+ ":current-support-api",
+ ],
+ dex_mapping_filename: "dex-mapping.txt",
+ args: framework_docs_args +
+ " -referenceonly" +
+ " -nodocs" +
+ " -showUnannotated" +
+ " -showAnnotation android.annotation.SystemApi" +
+ " -showAnnotation android.annotation.TestApi",
+}
+
filegroup {
name: "apache-http-stubs-sources",
srcs: [
diff --git a/apct-tests/perftests/core/src/android/os/BinderCallsStatsPerfTest.java b/apct-tests/perftests/core/src/android/os/BinderCallsStatsPerfTest.java
index e4a8503..e126fb8 100644
--- a/apct-tests/perftests/core/src/android/os/BinderCallsStatsPerfTest.java
+++ b/apct-tests/perftests/core/src/android/os/BinderCallsStatsPerfTest.java
@@ -45,7 +45,7 @@
@Before
public void setUp() {
- mBinderCallsStats = new BinderCallsStats(true);
+ mBinderCallsStats = new BinderCallsStats();
}
@After
@@ -54,6 +54,7 @@
@Test
public void timeCallSession() {
+ mBinderCallsStats.setDetailedTracking(true);
final BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
Binder b = new Binder();
int i = 0;
@@ -66,9 +67,9 @@
@Test
public void timeCallSessionTrackingDisabled() {
+ mBinderCallsStats.setDetailedTracking(false);
final BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
Binder b = new Binder();
- mBinderCallsStats = new BinderCallsStats(false);
while (state.keepRunning()) {
BinderCallsStats.CallSession s = mBinderCallsStats.callStarted(b, 0);
mBinderCallsStats.callEnded(s, 0, 0);
diff --git a/api/current.txt b/api/current.txt
index f90ab4b..dcc19e6 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -6120,8 +6120,10 @@
}
public final class UiAutomation {
+ method public void adoptShellPermissionIdentity();
method public void clearWindowAnimationFrameStats();
method public boolean clearWindowContentFrameStats(int);
+ method public void dropShellPermissionIdentity();
method public android.view.accessibility.AccessibilityEvent executeAndWaitForEvent(java.lang.Runnable, android.app.UiAutomation.AccessibilityEventFilter, long) throws java.util.concurrent.TimeoutException;
method public android.os.ParcelFileDescriptor executeShellCommand(java.lang.String);
method public android.view.accessibility.AccessibilityNodeInfo findFocus(int);
@@ -42412,8 +42414,10 @@
method public java.lang.CharSequence getDisplayName();
method public java.lang.String getIccId();
method public int getIconTint();
- method public int getMcc();
- method public int getMnc();
+ method public deprecated int getMcc();
+ method public java.lang.String getMccString();
+ method public deprecated int getMnc();
+ method public java.lang.String getMncString();
method public java.lang.String getNumber();
method public int getSimSlotIndex();
method public int getSubscriptionId();
@@ -42506,9 +42510,13 @@
method public java.lang.String getIccAuthentication(int, int, java.lang.String);
method public java.lang.String getImei();
method public java.lang.String getImei(int);
+ method public java.lang.String getTypeAllocationCode();
+ method public java.lang.String getTypeAllocationCode(int);
method public java.lang.String getLine1Number();
method public java.lang.String getMeid();
method public java.lang.String getMeid(int);
+ method public java.lang.String getManufacturerCode();
+ method public java.lang.String getManufacturerCode(int);
method public java.lang.String getMmsUAProfUrl();
method public java.lang.String getMmsUserAgent();
method public java.lang.String getNai();
diff --git a/api/test-current.txt b/api/test-current.txt
index e052578..e5061ed 100644
--- a/api/test-current.txt
+++ b/api/test-current.txt
@@ -274,7 +274,9 @@
method public abstract java.lang.String getPermissionControllerPackageName();
method public abstract java.lang.String getServicesSystemSharedLibraryPackageName();
method public abstract java.lang.String getSharedSystemSharedLibraryPackageName();
+ method public abstract void grantRuntimePermission(java.lang.String, java.lang.String, android.os.UserHandle);
method public abstract boolean isPermissionReviewModeEnabled();
+ method public abstract void revokeRuntimePermission(java.lang.String, java.lang.String, android.os.UserHandle);
field public static final java.lang.String FEATURE_ADOPTABLE_STORAGE = "android.software.adoptable_storage";
field public static final java.lang.String FEATURE_FILE_BASED_ENCRYPTION = "android.software.file_based_encryption";
field public static final int MATCH_FACTORY_ONLY = 2097152; // 0x200000
diff --git a/cmds/content/src/com/android/commands/content/Content.java b/cmds/content/src/com/android/commands/content/Content.java
index 6e0bd3a..36e51b9 100644
--- a/cmds/content/src/com/android/commands/content/Content.java
+++ b/cmds/content/src/com/android/commands/content/Content.java
@@ -462,7 +462,7 @@
IBinder token = new Binder();
try {
ContentProviderHolder holder = activityManager.getContentProviderExternal(
- providerName, mUserId, token);
+ providerName, mUserId, token, "*cmd*");
if (holder == null) {
throw new IllegalStateException("Could not find provider: " + providerName);
}
diff --git a/cmds/uiautomator/library/testrunner-src/com/android/uiautomator/core/ShellUiAutomatorBridge.java b/cmds/uiautomator/library/testrunner-src/com/android/uiautomator/core/ShellUiAutomatorBridge.java
index 6538515..950a258 100644
--- a/cmds/uiautomator/library/testrunner-src/com/android/uiautomator/core/ShellUiAutomatorBridge.java
+++ b/cmds/uiautomator/library/testrunner-src/com/android/uiautomator/core/ShellUiAutomatorBridge.java
@@ -62,7 +62,7 @@
IBinder token = new Binder();
try {
ContentProviderHolder holder = activityManager.getContentProviderExternal(
- providerName, UserHandle.USER_SYSTEM, token);
+ providerName, UserHandle.USER_SYSTEM, token, "*uiautomator*");
if (holder == null) {
throw new IllegalStateException("Could not find provider: " + providerName);
}
diff --git a/core/java/android/app/ActivityManager.java b/core/java/android/app/ActivityManager.java
index 3f579bc..f27b286 100644
--- a/core/java/android/app/ActivityManager.java
+++ b/core/java/android/app/ActivityManager.java
@@ -3080,32 +3080,16 @@
*/
public int processState;
- /**
- * Whether the app is focused in multi-window environment.
- * @hide
- */
- public boolean isFocused;
-
- /**
- * Copy of {@link com.android.server.am.ProcessRecord#lastActivityTime} of the process.
- * @hide
- */
- public long lastActivityTime;
-
public RunningAppProcessInfo() {
importance = IMPORTANCE_FOREGROUND;
importanceReasonCode = REASON_UNKNOWN;
processState = PROCESS_STATE_IMPORTANT_FOREGROUND;
- isFocused = false;
- lastActivityTime = 0;
}
public RunningAppProcessInfo(String pProcessName, int pPid, String pArr[]) {
processName = pProcessName;
pid = pPid;
pkgList = pArr;
- isFocused = false;
- lastActivityTime = 0;
}
public int describeContents() {
@@ -3126,8 +3110,6 @@
ComponentName.writeToParcel(importanceReasonComponent, dest);
dest.writeInt(importanceReasonImportance);
dest.writeInt(processState);
- dest.writeInt(isFocused ? 1 : 0);
- dest.writeLong(lastActivityTime);
}
public void readFromParcel(Parcel source) {
@@ -3144,8 +3126,6 @@
importanceReasonComponent = ComponentName.readFromParcel(source);
importanceReasonImportance = source.readInt();
processState = source.readInt();
- isFocused = source.readInt() != 0;
- lastActivityTime = source.readLong();
}
public static final Creator<RunningAppProcessInfo> CREATOR =
diff --git a/core/java/android/app/ActivityManagerInternal.java b/core/java/android/app/ActivityManagerInternal.java
index ed06f2a..7a9a553 100644
--- a/core/java/android/app/ActivityManagerInternal.java
+++ b/core/java/android/app/ActivityManagerInternal.java
@@ -22,6 +22,7 @@
import android.content.IIntentSender;
import android.content.Intent;
import android.content.pm.ApplicationInfo;
+import android.content.pm.UserInfo;
import android.content.res.Configuration;
import android.os.Bundle;
import android.os.IBinder;
@@ -216,4 +217,16 @@
public abstract void updateOomAdj();
public abstract void sendForegroundProfileChanged(int userId);
+
+ /**
+ * Returns whether the given user requires credential entry at this time. This is used to
+ * intercept activity launches for work apps when the Work Challenge is present.
+ */
+ public abstract boolean shouldConfirmCredentials(int userId);
+ public abstract int[] getCurrentProfileIds();
+ public abstract UserInfo getCurrentUser();
+ public abstract void ensureNotSpecialUser(int userId);
+ public abstract boolean isCurrentProfile(int userId);
+ public abstract boolean hasStartedUserState(int userId);
+ public abstract void finishUserSwitch(Object uss);
}
diff --git a/core/java/android/app/AppOpsManager.java b/core/java/android/app/AppOpsManager.java
index 8b33963..c3404a5 100644
--- a/core/java/android/app/AppOpsManager.java
+++ b/core/java/android/app/AppOpsManager.java
@@ -2487,7 +2487,7 @@
*/
public int noteProxyOpNoThrow(int op, String proxiedPackageName) {
try {
- return mService.noteProxyOperation(op, mContext.getOpPackageName(),
+ return mService.noteProxyOperation(op, Process.myUid(), mContext.getOpPackageName(),
Binder.getCallingUid(), proxiedPackageName);
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
diff --git a/core/java/android/app/AppOpsManagerInternal.java b/core/java/android/app/AppOpsManagerInternal.java
index 24c5d23..f5d5e6e 100644
--- a/core/java/android/app/AppOpsManagerInternal.java
+++ b/core/java/android/app/AppOpsManagerInternal.java
@@ -18,12 +18,55 @@
import android.util.SparseIntArray;
+import com.android.internal.util.function.QuadFunction;
+import com.android.internal.util.function.TriFunction;
+
/**
* App ops service local interface.
*
* @hide Only for use within the system server.
*/
public abstract class AppOpsManagerInternal {
+ /** Interface to override app ops checks via composition */
+ public interface CheckOpsDelegate {
+ /**
+ * Allows overriding check operation behavior.
+ *
+ * @param code The op code to check.
+ * @param uid The UID for which to check.
+ * @param packageName The package for which to check.
+ * @param superImpl The super implementation.
+ * @return The app op check result.
+ */
+ int checkOperation(int code, int uid, String packageName,
+ TriFunction<Integer, Integer, String, Integer> superImpl);
+
+ /**
+ * Allows overriding check audio operation behavior.
+ *
+ * @param code The op code to check.
+ * @param usage The audio op usage.
+ * @param uid The UID for which to check.
+ * @param packageName The package for which to check.
+ * @param superImpl The super implementation.
+ * @return The app op check result.
+ */
+ int checkAudioOperation(int code, int usage, int uid, String packageName,
+ QuadFunction<Integer, Integer, Integer, String, Integer> superImpl);
+
+ /**
+ * Allows overriding note operation behavior.
+ *
+ * @param code The op code to note.
+ * @param uid The UID for which to note.
+ * @param packageName The package for which to note.
+ * @param superImpl The super implementation.
+ * @return The app op note result.
+ */
+ int noteOperation(int code, int uid, String packageName,
+ TriFunction<Integer, Integer, String, Integer> superImpl);
+ }
+
/**
* Set the currently configured device and profile owners. Specifies the package uid (value)
* that has been configured for each user (key) that has one. These will be allowed privileged
diff --git a/core/java/android/app/IActivityManager.aidl b/core/java/android/app/IActivityManager.aidl
index 76244ea..19d7c83 100644
--- a/core/java/android/app/IActivityManager.aidl
+++ b/core/java/android/app/IActivityManager.aidl
@@ -268,7 +268,7 @@
void showBootMessage(in CharSequence msg, boolean always);
void killAllBackgroundProcesses();
ContentProviderHolder getContentProviderExternal(in String name, int userId,
- in IBinder token);
+ in IBinder token, String tag);
void removeContentProviderExternal(in String name, in IBinder token);
// Get memory information about the calling process.
void getMyMemoryState(out ActivityManager.RunningAppProcessInfo outInfo);
@@ -498,4 +498,19 @@
* user unlock progress.
*/
boolean startUserInBackgroundWithListener(int userid, IProgressListener unlockProgressListener);
+
+ /**
+ * Method for the shell UID to start deletating its permission identity to an
+ * active instrumenation. The shell can delegate permissions only to one active
+ * instrumentation at a time. An active instrumentation is one running and
+ * started from the shell.
+ */
+ void startDelegateShellPermissionIdentity(int uid);
+
+ /**
+ * Method for the shell UID to stop deletating its permission identity to an
+ * active instrumenation. An active instrumentation is one running and
+ * started from the shell.
+ */
+ void stopDelegateShellPermissionIdentity();
}
diff --git a/core/java/android/app/IUiAutomationConnection.aidl b/core/java/android/app/IUiAutomationConnection.aidl
index d01938b..ac4bf7d 100644
--- a/core/java/android/app/IUiAutomationConnection.aidl
+++ b/core/java/android/app/IUiAutomationConnection.aidl
@@ -47,7 +47,8 @@
in ParcelFileDescriptor source);
void grantRuntimePermission(String packageName, String permission, int userId);
void revokeRuntimePermission(String packageName, String permission, int userId);
-
+ void adoptShellPermissionIdentity(int uid);
+ void dropShellPermissionIdentity();
// Called from the system process.
oneway void shutdown();
}
diff --git a/core/java/android/app/NotificationChannel.java b/core/java/android/app/NotificationChannel.java
index 1ad3054..03fd139 100644
--- a/core/java/android/app/NotificationChannel.java
+++ b/core/java/android/app/NotificationChannel.java
@@ -38,6 +38,7 @@
import org.xmlpull.v1.XmlSerializer;
import java.io.IOException;
+import java.io.PrintWriter;
import java.util.Arrays;
/**
@@ -942,6 +943,32 @@
return result;
}
+ /** @hide */
+ public void dump(PrintWriter pw, String prefix, boolean redacted) {
+ String redactedName = redacted ? TextUtils.trimToLengthWithEllipsis(mName, 3) : mName;
+ String output = "NotificationChannel{"
+ + "mId='" + mId + '\''
+ + ", mName=" + redactedName
+ + ", mDescription=" + (!TextUtils.isEmpty(mDesc) ? "hasDescription " : "")
+ + ", mImportance=" + mImportance
+ + ", mBypassDnd=" + mBypassDnd
+ + ", mLockscreenVisibility=" + mLockscreenVisibility
+ + ", mSound=" + mSound
+ + ", mLights=" + mLights
+ + ", mLightColor=" + mLightColor
+ + ", mVibration=" + Arrays.toString(mVibration)
+ + ", mUserLockedFields=" + Integer.toHexString(mUserLockedFields)
+ + ", mFgServiceShown=" + mFgServiceShown
+ + ", mVibrationEnabled=" + mVibrationEnabled
+ + ", mShowBadge=" + mShowBadge
+ + ", mDeleted=" + mDeleted
+ + ", mGroup='" + mGroup + '\''
+ + ", mAudioAttributes=" + mAudioAttributes
+ + ", mBlockableSystem=" + mBlockableSystem
+ + '}';
+ pw.println(prefix + output);
+ }
+
@Override
public String toString() {
return "NotificationChannel{"
diff --git a/core/java/android/app/UiAutomation.java b/core/java/android/app/UiAutomation.java
index 5662aea..44f28796 100644
--- a/core/java/android/app/UiAutomation.java
+++ b/core/java/android/app/UiAutomation.java
@@ -33,6 +33,7 @@
import android.os.IBinder;
import android.os.Looper;
import android.os.ParcelFileDescriptor;
+import android.os.Process;
import android.os.RemoteException;
import android.os.SystemClock;
import android.os.UserHandle;
@@ -50,6 +51,7 @@
import android.view.accessibility.IAccessibilityInteractionConnection;
import com.android.internal.util.function.pooled.PooledLambda;
+
import libcore.io.IoUtils;
import java.io.IOException;
@@ -347,6 +349,46 @@
}
/**
+ * Adopt the permission identity of the shell UID. This allows you to call APIs protected
+ * permissions which normal apps cannot hold but are granted to the shell UID. If you
+ * already adopted the shell permission identity this method would be a no-op.
+ * Note that your permission state becomes that of the shell UID and it is not a
+ * combination of your and the shell UID permissions.
+ *
+ * @see #dropShellPermissionIdentity()
+ */
+ public void adoptShellPermissionIdentity() {
+ synchronized (mLock) {
+ throwIfNotConnectedLocked();
+ }
+ try {
+ // Calling out without a lock held.
+ mUiAutomationConnection.adoptShellPermissionIdentity(Process.myUid());
+ } catch (RemoteException re) {
+ Log.e(LOG_TAG, "Error executing adopting shell permission identity!", re);
+ }
+ }
+
+ /**
+ * Drop the shell permission identity adopted by a previous call to
+ * {@link #adoptShellPermissionIdentity()}. If you did not adopt the shell permission
+ * identity this method would be a no-op.
+ *
+ * @see #adoptShellPermissionIdentity()
+ */
+ public void dropShellPermissionIdentity() {
+ synchronized (mLock) {
+ throwIfNotConnectedLocked();
+ }
+ try {
+ // Calling out without a lock held.
+ mUiAutomationConnection.dropShellPermissionIdentity();
+ } catch (RemoteException re) {
+ Log.e(LOG_TAG, "Error executing dropping shell permission identity!", re);
+ }
+ }
+
+ /**
* Performs a global action. Such an action can be performed at any moment
* regardless of the current application or user location in that application.
* For example going back, going home, opening recents, etc.
@@ -999,6 +1041,8 @@
*
* @param command The command to execute.
* @return A file descriptor to the standard output stream.
+ *
+ * @see #adoptShellPermissionIdentity()
*/
public ParcelFileDescriptor executeShellCommand(String command) {
synchronized (mLock) {
@@ -1081,22 +1125,6 @@
return result;
}
- private static float getDegreesForRotation(int value) {
- switch (value) {
- case Surface.ROTATION_90: {
- return 360f - 90f;
- }
- case Surface.ROTATION_180: {
- return 360f - 180f;
- }
- case Surface.ROTATION_270: {
- return 360f - 270f;
- } default: {
- return 0;
- }
- }
- }
-
private boolean isConnectedLocked() {
return mConnectionId != CONNECTION_ID_UNDEFINED;
}
diff --git a/core/java/android/app/UiAutomationConnection.java b/core/java/android/app/UiAutomationConnection.java
index d3828ab..ac3f2e7 100644
--- a/core/java/android/app/UiAutomationConnection.java
+++ b/core/java/android/app/UiAutomationConnection.java
@@ -30,6 +30,7 @@
import android.os.RemoteException;
import android.os.ServiceManager;
import android.os.UserHandle;
+import android.util.Log;
import android.view.IWindowManager;
import android.view.InputEvent;
import android.view.SurfaceControl;
@@ -37,7 +38,6 @@
import android.view.WindowContentFrameStats;
import android.view.accessibility.AccessibilityEvent;
import android.view.accessibility.IAccessibilityManager;
-import android.util.Log;
import libcore.io.IoUtils;
@@ -71,6 +71,9 @@
private final IPackageManager mPackageManager = IPackageManager.Stub
.asInterface(ServiceManager.getService("package"));
+ private final IActivityManager mActivityManager = IActivityManager.Stub
+ .asInterface(ServiceManager.getService("activity"));
+
private final Object mLock = new Object();
private final Binder mToken = new Binder();
@@ -274,6 +277,36 @@
}
}
+ @Override
+ public void adoptShellPermissionIdentity(int uid) throws RemoteException {
+ synchronized (mLock) {
+ throwIfCalledByNotTrustedUidLocked();
+ throwIfShutdownLocked();
+ throwIfNotConnectedLocked();
+ }
+ final long identity = Binder.clearCallingIdentity();
+ try {
+ mActivityManager.startDelegateShellPermissionIdentity(uid);
+ } finally {
+ Binder.restoreCallingIdentity(identity);
+ }
+ }
+
+ @Override
+ public void dropShellPermissionIdentity() throws RemoteException {
+ synchronized (mLock) {
+ throwIfCalledByNotTrustedUidLocked();
+ throwIfShutdownLocked();
+ throwIfNotConnectedLocked();
+ }
+ final long identity = Binder.clearCallingIdentity();
+ try {
+ mActivityManager.stopDelegateShellPermissionIdentity();
+ } finally {
+ Binder.restoreCallingIdentity(identity);
+ }
+ }
+
public class Repeater implements Runnable {
// Continuously read readFrom and write back to writeTo until EOF is encountered
private final InputStream readFrom;
diff --git a/core/java/android/content/pm/PackageManager.java b/core/java/android/content/pm/PackageManager.java
index a622af8..ce551ee 100644
--- a/core/java/android/content/pm/PackageManager.java
+++ b/core/java/android/content/pm/PackageManager.java
@@ -3582,6 +3582,7 @@
*
* @hide
*/
+ @TestApi
@SystemApi
@RequiresPermission(android.Manifest.permission.GRANT_RUNTIME_PERMISSIONS)
public abstract void grantRuntimePermission(@NonNull String packageName,
@@ -3608,6 +3609,7 @@
*
* @hide
*/
+ @TestApi
@SystemApi
@RequiresPermission(android.Manifest.permission.REVOKE_RUNTIME_PERMISSIONS)
public abstract void revokeRuntimePermission(@NonNull String packageName,
diff --git a/core/java/android/content/pm/PackageManagerInternal.java b/core/java/android/content/pm/PackageManagerInternal.java
index f30b3fe..ee752f8 100644
--- a/core/java/android/content/pm/PackageManagerInternal.java
+++ b/core/java/android/content/pm/PackageManagerInternal.java
@@ -29,9 +29,12 @@
import android.os.PersistableBundle;
import android.util.SparseArray;
+import com.android.internal.util.function.TriFunction;
+
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.util.List;
+import java.util.function.BiFunction;
/**
* Package manager local system service interface.
@@ -64,6 +67,32 @@
void onPackageRemoved(@NonNull String packageName);
}
+ /** Interface to override permission checks via composition */
+ public interface CheckPermissionDelegate {
+ /**
+ * Allows overriding check permission behavior.
+ *
+ * @param permName The permission to check.
+ * @param pkgName The package for which to check.
+ * @param userId The user for which to check.
+ * @param superImpl The super implementation.
+ * @return The check permission result.
+ */
+ int checkPermission(String permName, String pkgName, int userId,
+ TriFunction<String, String, Integer, Integer> superImpl);
+
+ /**
+ * Allows overriding check UID permission behavior.
+ *
+ * @param permName The permission to check.
+ * @param uid The UID for which to check.
+ * @param superImpl The super implementation.
+ * @return The check permission result.
+ */
+ int checkUidPermission(String permName, int uid,
+ BiFunction<String, Integer, Integer> superImpl);
+ }
+
/**
* Provider for package names.
*/
@@ -628,4 +657,18 @@
*/
public abstract boolean hasSignatureCapability(int serverUid, int clientUid,
@PackageParser.SigningDetails.CertCapabilities int capability);
+
+ /**
+ * Get the delegate to influence permission checking.
+ *
+ * @return The delegate instance or null to clear.
+ */
+ public abstract @Nullable CheckPermissionDelegate getCheckPermissionDelegate();
+
+ /**
+ * Set a delegate to influence permission checking.
+ *
+ * @param delegate A delegate instance or null to clear.
+ */
+ public abstract void setCheckPermissionDelegate(@Nullable CheckPermissionDelegate delegate);
}
diff --git a/core/java/android/os/BatteryStats.java b/core/java/android/os/BatteryStats.java
index 221abed..9cf7de5 100644
--- a/core/java/android/os/BatteryStats.java
+++ b/core/java/android/os/BatteryStats.java
@@ -247,8 +247,10 @@
* - Deferred job metrics.
* New in version 32:
* - Ambient display properly output in data dump.
+ * New in version 33:
+ * - Fixed bug in min learned capacity updating process.
*/
- static final int CHECKIN_VERSION = 32;
+ static final int CHECKIN_VERSION = 33;
/**
* Old version, we hit 9 and ran out of room, need to remove.
diff --git a/core/java/android/os/Binder.java b/core/java/android/os/Binder.java
index ac87105..ab2cf86 100644
--- a/core/java/android/os/Binder.java
+++ b/core/java/android/os/Binder.java
@@ -23,6 +23,7 @@
import android.util.Slog;
import android.util.SparseIntArray;
+import com.android.internal.annotations.GuardedBy;
import com.android.internal.os.BinderCallsStats;
import com.android.internal.os.BinderInternal;
import com.android.internal.util.FastPrintWriter;
@@ -551,6 +552,20 @@
}
/**
+ * Resolves a transaction code to a human readable name.
+ *
+ * <p>Default implementation is a stub that returns null.
+ * <p>AIDL generated code will return the original method name.
+ *
+ * @param transactionCode The code to resolve.
+ * @return A human readable name.
+ * @hide
+ */
+ public @Nullable String getTransactionName(int transactionCode) {
+ return null;
+ }
+
+ /**
* Implemented to call the more convenient version
* {@link #dump(FileDescriptor, PrintWriter, String[])}.
*/
@@ -730,7 +745,7 @@
}
res = onTransact(code, data, reply, flags);
} catch (RemoteException|RuntimeException e) {
- binderCallsStats.callThrewException(callSession);
+ binderCallsStats.callThrewException(callSession, e);
if (LOG_RUNTIME_EXCEPTION) {
Log.w(TAG, "Caught a RuntimeException from the binder stub implementation.", e);
}
@@ -1027,19 +1042,19 @@
new ArrayList[MAIN_INDEX_SIZE];
}
- private static ProxyMap sProxyMap = new ProxyMap();
+ @GuardedBy("sProxyMap")
+ private static final ProxyMap sProxyMap = new ProxyMap();
/**
* Dump proxy debug information.
*
- * Note: this method is not thread-safe; callers must serialize with other
- * accesses to sProxyMap, in particular {@link #getInstance(long, long)}.
- *
* @hide
*/
private static void dumpProxyDebugInfo() {
if (Build.IS_DEBUGGABLE) {
- sProxyMap.dumpProxyInterfaceCounts();
+ synchronized (sProxyMap) {
+ sProxyMap.dumpProxyInterfaceCounts();
+ }
// Note that we don't call dumpPerUidProxyCounts(); this is because this
// method may be called as part of the uid limit being hit, and calling
// back into the UID tracking code would cause us to try to acquire a mutex
@@ -1049,8 +1064,6 @@
/**
* Return a BinderProxy for IBinder.
- * This method is thread-hostile! The (native) caller serializes getInstance() calls using
- * gProxyLock.
* If we previously returned a BinderProxy bp for the same iBinder, and bp is still
* in use, then we return the same bp.
*
@@ -1062,21 +1075,23 @@
*/
private static BinderProxy getInstance(long nativeData, long iBinder) {
BinderProxy result;
- try {
- result = sProxyMap.get(iBinder);
- if (result != null) {
- return result;
+ synchronized (sProxyMap) {
+ try {
+ result = sProxyMap.get(iBinder);
+ if (result != null) {
+ return result;
+ }
+ result = new BinderProxy(nativeData);
+ } catch (Throwable e) {
+ // We're throwing an exception (probably OOME); don't drop nativeData.
+ NativeAllocationRegistry.applyFreeFunction(NoImagePreloadHolder.sNativeFinalizer,
+ nativeData);
+ throw e;
}
- result = new BinderProxy(nativeData);
- } catch (Throwable e) {
- // We're throwing an exception (probably OOME); don't drop nativeData.
- NativeAllocationRegistry.applyFreeFunction(NoImagePreloadHolder.sNativeFinalizer,
- nativeData);
- throw e;
+ NoImagePreloadHolder.sRegistry.registerNativeAllocation(result, nativeData);
+ // The registry now owns nativeData, even if registration threw an exception.
+ sProxyMap.set(iBinder, result);
}
- NoImagePreloadHolder.sRegistry.registerNativeAllocation(result, nativeData);
- // The registry now owns nativeData, even if registration threw an exception.
- sProxyMap.set(iBinder, result);
return result;
}
diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java
index 13d4d08..82b66d7 100644
--- a/core/java/android/provider/Settings.java
+++ b/core/java/android/provider/Settings.java
@@ -6991,8 +6991,6 @@
*/
public static final String SELECTED_SPELL_CHECKER = "selected_spell_checker";
- private static final Validator SELECTED_SPELL_CHECKER_VALIDATOR = COMPONENT_NAME_VALIDATOR;
-
/**
* {@link android.view.textservice.SpellCheckerSubtype#hashCode()} of the selected subtype
* of the selected spell checker service which is one of the services managed by the text
@@ -7003,9 +7001,6 @@
public static final String SELECTED_SPELL_CHECKER_SUBTYPE =
"selected_spell_checker_subtype";
- private static final Validator SELECTED_SPELL_CHECKER_SUBTYPE_VALIDATOR =
- ANY_INTEGER_VALIDATOR;
-
/**
* Whether spell checker is enabled or not.
*
@@ -7013,8 +7008,6 @@
*/
public static final String SPELL_CHECKER_ENABLED = "spell_checker_enabled";
- private static final Validator SPELL_CHECKER_ENABLED_VALIDATOR = BOOLEAN_VALIDATOR;
-
/**
* What happens when the user presses the Power button while in-call
* and the screen is on.<br/>
@@ -7133,35 +7126,6 @@
public static final String UI_NIGHT_MODE = "ui_night_mode";
/**
- * The current device UI theme mode effect SystemUI and Launcher.<br/>
- * <b>Values:</b><br/>
- * 0 - The mode that theme will controlled by wallpaper color.<br/>
- * 1 - The mode that will always light theme.<br/>
- * 2 - The mode that will always dark theme.<br/>
- *
- * @hide
- */
- public static final String THEME_MODE = "theme_mode";
-
- /**
- * THEME_MODE value for wallpaper mode.
- * @hide
- */
- public static final int THEME_MODE_WALLPAPER = 0;
-
- /**
- * THEME_MODE value for light theme mode.
- * @hide
- */
- public static final int THEME_MODE_LIGHT = 1;
-
- /**
- * THEME_MODE value for dark theme mode.
- * @hide
- */
- public static final int THEME_MODE_DARK = 2;
-
- /**
* Whether screensavers are enabled.
* @hide
*/
@@ -8007,9 +7971,6 @@
WIFI_NETWORKS_AVAILABLE_NOTIFICATION_ON, // moved to global
WIFI_NETWORKS_AVAILABLE_REPEAT_DELAY, // moved to global
WIFI_NUM_OPEN_NETWORKS_KEPT, // moved to global
- SELECTED_SPELL_CHECKER,
- SELECTED_SPELL_CHECKER_SUBTYPE,
- SPELL_CHECKER_ENABLED,
MOUNT_PLAY_NOTIFICATION_SND,
MOUNT_UMS_AUTOSTART,
MOUNT_UMS_PROMPT,
@@ -8134,10 +8095,6 @@
VALIDATORS.put(WIFI_NETWORKS_AVAILABLE_REPEAT_DELAY,
WIFI_NETWORKS_AVAILABLE_REPEAT_DELAY_VALIDATOR);
VALIDATORS.put(WIFI_NUM_OPEN_NETWORKS_KEPT, WIFI_NUM_OPEN_NETWORKS_KEPT_VALIDATOR);
- VALIDATORS.put(SELECTED_SPELL_CHECKER, SELECTED_SPELL_CHECKER_VALIDATOR);
- VALIDATORS.put(SELECTED_SPELL_CHECKER_SUBTYPE,
- SELECTED_SPELL_CHECKER_SUBTYPE_VALIDATOR);
- VALIDATORS.put(SPELL_CHECKER_ENABLED, SPELL_CHECKER_ENABLED_VALIDATOR);
VALIDATORS.put(MOUNT_PLAY_NOTIFICATION_SND, MOUNT_PLAY_NOTIFICATION_SND_VALIDATOR);
VALIDATORS.put(MOUNT_UMS_AUTOSTART, MOUNT_UMS_AUTOSTART_VALIDATOR);
VALIDATORS.put(MOUNT_UMS_PROMPT, MOUNT_UMS_PROMPT_VALIDATOR);
@@ -13022,6 +12979,21 @@
*/
public static final String GNSS_HAL_LOCATION_REQUEST_DURATION_MILLIS =
"gnss_hal_location_request_duration_millis";
+
+ /**
+ * Binder call stats settings.
+ *
+ * The following strings are supported as keys:
+ * <pre>
+ * enabled (boolean)
+ * detailed_tracking (boolean)
+ * upload_data (boolean)
+ * sampling_interval (int)
+ * </pre>
+ *
+ * @hide
+ */
+ public static final String BINDER_CALLS_STATS = "binder_calls_stats";
}
/**
diff --git a/core/java/android/service/notification/ZenModeConfig.java b/core/java/android/service/notification/ZenModeConfig.java
index 5546e80..df88e64 100644
--- a/core/java/android/service/notification/ZenModeConfig.java
+++ b/core/java/android/service/notification/ZenModeConfig.java
@@ -1007,6 +1007,24 @@
return true;
}
+ /**
+ * Returns whether the conditionId is a valid ScheduleCondition.
+ * If allowNever is true, this will return true even if the ScheduleCondition never occurs.
+ */
+ public static boolean isValidScheduleConditionId(Uri conditionId, boolean allowNever) {
+ ScheduleInfo info;
+ try {
+ info = tryParseScheduleConditionId(conditionId);
+ } catch (NullPointerException | ArrayIndexOutOfBoundsException e) {
+ return false;
+ }
+
+ if (info == null || (!allowNever && (info.days == null || info.days.length == 0))) {
+ return false;
+ }
+ return true;
+ }
+
public static ScheduleInfo tryParseScheduleConditionId(Uri conditionId) {
final boolean isSchedule = conditionId != null
&& conditionId.getScheme().equals(Condition.SCHEME)
diff --git a/core/java/android/text/TextUtils.java b/core/java/android/text/TextUtils.java
index 6b2f802..dde4c1d 100644
--- a/core/java/android/text/TextUtils.java
+++ b/core/java/android/text/TextUtils.java
@@ -2091,6 +2091,25 @@
return (T) text.subSequence(0, size);
}
+ /**
+ * Trims the {@code text} to the first {@code size} characters and adds an ellipsis if the
+ * resulting string is shorter than the input. This will result in an output string which is
+ * longer than {@code size} for most inputs.
+ *
+ * @param size length of the result, should be greater than 0
+ *
+ * @hide
+ */
+ @Nullable
+ public static <T extends CharSequence> T trimToLengthWithEllipsis(@Nullable T text,
+ @IntRange(from = 1) int size) {
+ T trimmed = trimToSize(text, size);
+ if (trimmed.length() < text.length()) {
+ trimmed = (T) (trimmed.toString() + "...");
+ }
+ return trimmed;
+ }
+
private static Object sLock = new Object();
private static char[] sTemp = null;
diff --git a/core/java/android/util/Half.java b/core/java/android/util/Half.java
index 84c2e83..5718d99 100644
--- a/core/java/android/util/Half.java
+++ b/core/java/android/util/Half.java
@@ -20,8 +20,6 @@
import android.annotation.NonNull;
import android.annotation.Nullable;
-import sun.misc.FloatingDecimal;
-
/**
* <p>The {@code Half} class is a wrapper and a utility class to manipulate half-precision 16-bit
* <a href="https://en.wikipedia.org/wiki/Half-precision_floating-point_format">IEEE 754</a>
@@ -1026,7 +1024,7 @@
* half-precision float value
*/
public static @HalfFloat short parseHalf(@NonNull String s) throws NumberFormatException {
- return toHalf(FloatingDecimal.parseFloat(s));
+ return toHalf(Float.parseFloat(s));
}
/**
diff --git a/core/java/android/util/IntArray.java b/core/java/android/util/IntArray.java
index 3617aa7..5a74ec0 100644
--- a/core/java/android/util/IntArray.java
+++ b/core/java/android/util/IntArray.java
@@ -18,9 +18,11 @@
import com.android.internal.util.ArrayUtils;
import com.android.internal.util.Preconditions;
-import java.util.Arrays;
+
import libcore.util.EmptyArray;
+import java.util.Arrays;
+
/**
* Implements a growing array of int primitives.
*
@@ -102,7 +104,7 @@
ensureCapacity(1);
int rightSegment = mSize - index;
mSize++;
- checkBounds(index);
+ ArrayUtils.checkBounds(mSize, index);
if (rightSegment != 0) {
// Move by 1 all values from the right of 'index'
@@ -175,7 +177,7 @@
* Returns the value at the specified position in this array.
*/
public int get(int index) {
- checkBounds(index);
+ ArrayUtils.checkBounds(mSize, index);
return mValues[index];
}
@@ -183,7 +185,7 @@
* Sets the value at the specified position in this array.
*/
public void set(int index, int value) {
- checkBounds(index);
+ ArrayUtils.checkBounds(mSize, index);
mValues[index] = value;
}
@@ -205,7 +207,7 @@
* Removes the value at the specified index from this array.
*/
public void remove(int index) {
- checkBounds(index);
+ ArrayUtils.checkBounds(mSize, index);
System.arraycopy(mValues, index + 1, mValues, index, mSize - index - 1);
mSize--;
}
@@ -223,10 +225,4 @@
public int[] toArray() {
return Arrays.copyOf(mValues, mSize);
}
-
- private void checkBounds(int index) {
- if (index < 0 || mSize <= index) {
- throw new ArrayIndexOutOfBoundsException(mSize, index);
- }
- }
}
diff --git a/core/java/android/util/LongArray.java b/core/java/android/util/LongArray.java
index fa98096..5ed1c8c 100644
--- a/core/java/android/util/LongArray.java
+++ b/core/java/android/util/LongArray.java
@@ -106,7 +106,7 @@
ensureCapacity(1);
int rightSegment = mSize - index;
mSize++;
- checkBounds(index);
+ ArrayUtils.checkBounds(mSize, index);
if (rightSegment != 0) {
// Move by 1 all values from the right of 'index'
@@ -166,7 +166,7 @@
* Returns the value at the specified position in this array.
*/
public long get(int index) {
- checkBounds(index);
+ ArrayUtils.checkBounds(mSize, index);
return mValues[index];
}
@@ -174,7 +174,7 @@
* Sets the value at the specified position in this array.
*/
public void set(int index, long value) {
- checkBounds(index);
+ ArrayUtils.checkBounds(mSize, index);
mValues[index] = value;
}
@@ -196,7 +196,7 @@
* Removes the value at the specified index from this array.
*/
public void remove(int index) {
- checkBounds(index);
+ ArrayUtils.checkBounds(mSize, index);
System.arraycopy(mValues, index + 1, mValues, index, mSize - index - 1);
mSize--;
}
@@ -215,12 +215,6 @@
return Arrays.copyOf(mValues, mSize);
}
- private void checkBounds(int index) {
- if (index < 0 || mSize <= index) {
- throw new ArrayIndexOutOfBoundsException(mSize, index);
- }
- }
-
/**
* Test if each element of {@code a} equals corresponding element from {@code b}
*/
diff --git a/core/java/android/view/InputEvent.java b/core/java/android/view/InputEvent.java
index 1f2aab9..c257364 100644
--- a/core/java/android/view/InputEvent.java
+++ b/core/java/android/view/InputEvent.java
@@ -95,6 +95,19 @@
}
/**
+ * Gets the display id of the event.
+ * @return The display id associated with the event.
+ * @hide
+ */
+ public abstract int getDisplayId();
+
+ /**
+ * Modifies the display id associated with the event
+ * @param displayId
+ * @hide
+ */
+ public abstract void setDisplayId(int displayId);
+ /**
* Copies the event.
*
* @return A deep copy of the event.
diff --git a/core/java/android/view/KeyEvent.java b/core/java/android/view/KeyEvent.java
index 35546f8..2c00391 100644
--- a/core/java/android/view/KeyEvent.java
+++ b/core/java/android/view/KeyEvent.java
@@ -16,6 +16,8 @@
package android.view;
+import static android.view.Display.INVALID_DISPLAY;
+
import android.annotation.NonNull;
import android.annotation.TestApi;
import android.os.Parcel;
@@ -1246,6 +1248,7 @@
private int mDeviceId;
private int mSource;
+ private int mDisplayId;
private int mMetaState;
private int mAction;
private int mKeyCode;
@@ -1473,6 +1476,7 @@
mScanCode = scancode;
mFlags = flags;
mSource = source;
+ mDisplayId = INVALID_DISPLAY;
}
/**
@@ -1497,6 +1501,7 @@
mDeviceId = deviceId;
mFlags = flags;
mSource = InputDevice.SOURCE_KEYBOARD;
+ mDisplayId = INVALID_DISPLAY;
}
/**
@@ -1511,6 +1516,7 @@
mMetaState = origEvent.mMetaState;
mDeviceId = origEvent.mDeviceId;
mSource = origEvent.mSource;
+ mDisplayId = origEvent.mDisplayId;
mScanCode = origEvent.mScanCode;
mFlags = origEvent.mFlags;
mCharacters = origEvent.mCharacters;
@@ -1537,6 +1543,7 @@
mMetaState = origEvent.mMetaState;
mDeviceId = origEvent.mDeviceId;
mSource = origEvent.mSource;
+ mDisplayId = origEvent.mDisplayId;
mScanCode = origEvent.mScanCode;
mFlags = origEvent.mFlags;
mCharacters = origEvent.mCharacters;
@@ -1564,7 +1571,7 @@
*/
public static KeyEvent obtain(long downTime, long eventTime, int action,
int code, int repeat, int metaState,
- int deviceId, int scancode, int flags, int source, String characters) {
+ int deviceId, int scancode, int flags, int source, int displayId, String characters) {
KeyEvent ev = obtain();
ev.mDownTime = downTime;
ev.mEventTime = eventTime;
@@ -1576,11 +1583,26 @@
ev.mScanCode = scancode;
ev.mFlags = flags;
ev.mSource = source;
+ ev.mDisplayId = displayId;
ev.mCharacters = characters;
return ev;
}
/**
+ * Obtains a (potentially recycled) key event.
+ *
+ * @hide
+ */
+ public static KeyEvent obtain(long downTime, long eventTime, int action,
+ int code, int repeat, int metaState,
+ int deviceId, int scancode, int flags, int source, String characters) {
+ return obtain(downTime, eventTime, action, code, repeat, metaState, deviceId, scancode,
+ flags, source, INVALID_DISPLAY, characters);
+ }
+
+ /**
+
+ /**
* Obtains a (potentially recycled) copy of another key event.
*
* @hide
@@ -1597,6 +1619,7 @@
ev.mScanCode = other.mScanCode;
ev.mFlags = other.mFlags;
ev.mSource = other.mSource;
+ ev.mDisplayId = other.mDisplayId;
ev.mCharacters = other.mCharacters;
return ev;
}
@@ -1683,6 +1706,7 @@
mMetaState = origEvent.mMetaState;
mDeviceId = origEvent.mDeviceId;
mSource = origEvent.mSource;
+ mDisplayId = origEvent.mDisplayId;
mScanCode = origEvent.mScanCode;
mFlags = origEvent.mFlags;
// Don't copy mCharacters, since one way or the other we'll lose it
@@ -1917,6 +1941,18 @@
mSource = source;
}
+ /** @hide */
+ @Override
+ public final int getDisplayId() {
+ return mDisplayId;
+ }
+
+ /** @hide */
+ @Override
+ public final void setDisplayId(int displayId) {
+ mDisplayId = displayId;
+ }
+
/**
* <p>Returns the state of the meta keys.</p>
*
@@ -2852,6 +2888,7 @@
msg.append(", downTime=").append(mDownTime);
msg.append(", deviceId=").append(mDeviceId);
msg.append(", source=0x").append(Integer.toHexString(mSource));
+ msg.append(", displayId=").append(mDisplayId);
msg.append(" }");
return msg.toString();
}
@@ -2983,6 +3020,7 @@
private KeyEvent(Parcel in) {
mDeviceId = in.readInt();
mSource = in.readInt();
+ mDisplayId = in.readInt();
mAction = in.readInt();
mKeyCode = in.readInt();
mRepeatCount = in.readInt();
@@ -2999,6 +3037,7 @@
out.writeInt(mDeviceId);
out.writeInt(mSource);
+ out.writeInt(mDisplayId);
out.writeInt(mAction);
out.writeInt(mKeyCode);
out.writeInt(mRepeatCount);
diff --git a/core/java/android/view/MotionEvent.java b/core/java/android/view/MotionEvent.java
index 9148c27..344806a 100644
--- a/core/java/android/view/MotionEvent.java
+++ b/core/java/android/view/MotionEvent.java
@@ -1943,11 +1943,13 @@
}
/** @hide */
+ @Override
public int getDisplayId() {
return nativeGetDisplayId(mNativePtr);
}
/** @hide */
+ @Override
public void setDisplayId(int displayId) {
nativeSetDisplayId(mNativePtr, displayId);
}
diff --git a/core/java/android/view/RenderNode.java b/core/java/android/view/RenderNode.java
index e10eeb0..e0df59f 100644
--- a/core/java/android/view/RenderNode.java
+++ b/core/java/android/view/RenderNode.java
@@ -16,6 +16,7 @@
package android.view;
+import android.annotation.IntDef;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.graphics.Matrix;
@@ -29,6 +30,9 @@
import libcore.util.NativeAllocationRegistry;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+
/**
* <p>A display list records a series of graphics related operations and can replay
* them later. Display lists are usually built by recording operations on a
@@ -449,6 +453,25 @@
return nSetHasOverlappingRendering(mNativeRenderNode, hasOverlappingRendering);
}
+ /** @hide */
+ @IntDef({USAGE_BACKGROUND})
+ @Retention(RetentionPolicy.SOURCE)
+ public @interface UsageHint {}
+
+ /** The default usage hint */
+ public static final int USAGE_UNKNOWN = 0;
+
+ /** Usage is background content */
+ public static final int USAGE_BACKGROUND = 1;
+
+ /**
+ * Provides a hint on what this RenderNode's display list content contains. This hint is used
+ * for automatic content transforms to improve accessibility or similar.
+ */
+ public void setUsageHint(@UsageHint int usageHint) {
+ nSetUsageHint(mNativeRenderNode, usageHint);
+ }
+
/**
* Indicates whether the content of this display list overlaps.
*
@@ -948,6 +971,8 @@
private static native boolean nSetHasOverlappingRendering(long renderNode,
boolean hasOverlappingRendering);
@CriticalNative
+ private static native void nSetUsageHint(long renderNode, int usageHint);
+ @CriticalNative
private static native boolean nSetElevation(long renderNode, float lift);
@CriticalNative
private static native boolean nSetTranslationX(long renderNode, float translationX);
diff --git a/core/java/android/view/View.java b/core/java/android/view/View.java
index 546ea87..19e95b8 100644
--- a/core/java/android/view/View.java
+++ b/core/java/android/view/View.java
@@ -20442,6 +20442,7 @@
private RenderNode getDrawableRenderNode(Drawable drawable, RenderNode renderNode) {
if (renderNode == null) {
renderNode = RenderNode.create(drawable.getClass().getName(), this);
+ renderNode.setUsageHint(RenderNode.USAGE_BACKGROUND);
}
final Rect bounds = drawable.getBounds();
diff --git a/core/java/android/view/WindowManager.java b/core/java/android/view/WindowManager.java
index 4d7b73c..8c7ac73 100644
--- a/core/java/android/view/WindowManager.java
+++ b/core/java/android/view/WindowManager.java
@@ -1692,6 +1692,15 @@
public static final int PRIVATE_FLAG_IS_SCREEN_DECOR = 0x00400000;
/**
+ * Flag to indicate that the status bar window is now in an explicit expanded state, meaning
+ * that status bar will not be hidden by any window with flag {@link #FLAG_FULLSCREEN} or
+ * {@link View#SYSTEM_UI_FLAG_FULLSCREEN} set.
+ * This can only be set by {@link LayoutParams#TYPE_STATUS_BAR}.
+ * @hide
+ */
+ public static final int PRIVATE_FLAG_STATUS_BAR_EXPANDED = 0x00800000;
+
+ /**
* Control flags that are private to the platform.
* @hide
*/
@@ -1779,7 +1788,11 @@
@ViewDebug.FlagToString(
mask = PRIVATE_FLAG_IS_SCREEN_DECOR,
equals = PRIVATE_FLAG_IS_SCREEN_DECOR,
- name = "IS_SCREEN_DECOR")
+ name = "IS_SCREEN_DECOR"),
+ @ViewDebug.FlagToString(
+ mask = PRIVATE_FLAG_STATUS_BAR_EXPANDED,
+ equals = PRIVATE_FLAG_STATUS_BAR_EXPANDED,
+ name = "STATUS_BAR_EXPANDED")
})
@TestApi
public int privateFlags;
diff --git a/core/java/com/android/internal/app/IAppOpsService.aidl b/core/java/com/android/internal/app/IAppOpsService.aidl
index 0ed9724..768dddd 100644
--- a/core/java/com/android/internal/app/IAppOpsService.aidl
+++ b/core/java/com/android/internal/app/IAppOpsService.aidl
@@ -33,7 +33,7 @@
void stopWatchingMode(IAppOpsCallback callback);
IBinder getToken(IBinder clientToken);
int permissionToOpCode(String permission);
- int noteProxyOperation(int code, String proxyPackageName,
+ int noteProxyOperation(int code, int proxyUid, String proxyPackageName,
int callingUid, String callingPackageName);
// Remaining methods are only used in Java.
diff --git a/core/java/com/android/internal/app/procstats/AssociationState.java b/core/java/com/android/internal/app/procstats/AssociationState.java
index e73ec1c..e5d6556 100644
--- a/core/java/com/android/internal/app/procstats/AssociationState.java
+++ b/core/java/com/android/internal/app/procstats/AssociationState.java
@@ -21,37 +21,143 @@
import android.os.SystemClock;
import android.os.UserHandle;
import android.util.ArrayMap;
+import android.util.Slog;
import android.util.TimeUtils;
import java.io.PrintWriter;
+import java.util.ArrayList;
import java.util.Objects;
public final class AssociationState {
private static final String TAG = "ProcessStats";
private static final boolean DEBUG = false;
- private final String mPackage;
+ private final ProcessStats mProcessStats;
+ private final ProcessStats.PackageState mPackageState;
private final String mProcessName;
private final String mName;
private final DurationsTable mDurations;
public final class SourceState {
- public void stop() {
- mNesting--;
- if (mNesting == 0) {
- mDuration += SystemClock.uptimeMillis() - mStartTime;
- mNumActive--;
+ final SourceKey mKey;
+ int mProcStateSeq = -1;
+ int mProcState = ProcessStats.STATE_NOTHING;
+ boolean mInTrackingList;
+ int mNesting;
+ int mCount;
+ long mStartUptime;
+ long mDuration;
+ long mTrackingUptime;
+ int mActiveCount;
+ long mActiveStartUptime;
+ long mActiveDuration;
+
+ SourceState(SourceKey key) {
+ mKey = key;
+ }
+
+ public AssociationState getAssociationState() {
+ return AssociationState.this;
+ }
+
+ public String getProcessName() {
+ return mKey.mProcess;
+ }
+
+ public int getUid() {
+ return mKey.mUid;
+ }
+
+ public void trackProcState(int procState, int seq, long now) {
+ procState = ProcessState.PROCESS_STATE_TO_STATE[procState];
+ if (seq != mProcStateSeq) {
+ mProcStateSeq = seq;
+ mProcState = procState;
+ } else if (procState < mProcState) {
+ mProcState = procState;
+ }
+ if (procState < ProcessStats.STATE_HOME) {
+ if (!mInTrackingList) {
+ mInTrackingList = true;
+ mTrackingUptime = now;
+ mProcessStats.mTrackingAssociations.add(this);
+ }
+ } else {
+ stopTracking(now);
}
}
- int mNesting;
- int mCount;
- long mStartTime;
- long mDuration;
+ public void stop() {
+ mNesting--;
+ if (mNesting == 0) {
+ mDuration += SystemClock.uptimeMillis() - mStartUptime;
+ mNumActive--;
+ stopTracking(SystemClock.uptimeMillis());
+ }
+ }
+
+ void startActive(long now) {
+ if (mInTrackingList) {
+ if (mActiveStartUptime == 0) {
+ mActiveStartUptime = now;
+ mActiveCount++;
+ }
+ } else {
+ Slog.wtf(TAG, "startActive while not tracking: " + this);
+ }
+ }
+
+ void stopActive(long now) {
+ if (mActiveStartUptime != 0) {
+ if (!mInTrackingList) {
+ Slog.wtf(TAG, "stopActive while not tracking: " + this);
+ }
+ mActiveDuration += now - mActiveStartUptime;
+ mActiveStartUptime = 0;
+ }
+ }
+
+ void stopTracking(long now) {
+ stopActive(now);
+ if (mInTrackingList) {
+ mInTrackingList = false;
+ // Do a manual search for where to remove, since these objects will typically
+ // be towards the end of the array.
+ final ArrayList<SourceState> list = mProcessStats.mTrackingAssociations;
+ for (int i = list.size() - 1; i >= 0; i--) {
+ if (list.get(i) == this) {
+ list.remove(i);
+ return;
+ }
+ }
+ Slog.wtf(TAG, "Stop tracking didn't find in tracking list: " + this);
+ }
+ }
+
+ @Override
+ public String toString() {
+ StringBuilder sb = new StringBuilder(64);
+ sb.append("SourceState{").append(Integer.toHexString(System.identityHashCode(this)))
+ .append(" ").append(mKey.mProcess).append("/").append(mKey.mUid);
+ if (mProcState != ProcessStats.STATE_NOTHING) {
+ sb.append(" ").append(DumpUtils.STATE_NAMES[mProcState]).append(" #")
+ .append(mProcStateSeq);
+ }
+ sb.append("}");
+ return sb.toString();
+ }
}
- final static class SourceKey {
+ private final static class SourceKey {
+ /**
+ * UID, consider this final. Not final just to avoid a temporary object during lookup.
+ */
int mUid;
+
+ /**
+ * Process name, consider this final. Not final just to avoid a temporary object during
+ * lookup.
+ */
String mProcess;
SourceKey(int uid, String process) {
@@ -82,7 +188,6 @@
sb.append('}');
return sb.toString();
}
-
}
/**
@@ -92,18 +197,26 @@
private final SourceKey mTmpSourceKey = new SourceKey(0, null);
+ private ProcessState mProc;
+
private int mNumActive;
- public AssociationState(ProcessStats processStats, String pkg, String name,
- String processName) {
- mPackage = pkg;
+ public AssociationState(ProcessStats processStats, ProcessStats.PackageState packageState,
+ String name, String processName, ProcessState proc) {
+ mProcessStats = processStats;
+ mPackageState = packageState;
mName = name;
mProcessName = processName;
mDurations = new DurationsTable(processStats.mTableData);
+ mProc = proc;
+ }
+
+ public int getUid() {
+ return mPackageState.mUid;
}
public String getPackage() {
- return mPackage;
+ return mPackageState.mPackageName;
}
public String getProcessName() {
@@ -114,18 +227,27 @@
return mName;
}
+ public ProcessState getProcess() {
+ return mProc;
+ }
+
+ public void setProcess(ProcessState proc) {
+ mProc = proc;
+ }
+
public SourceState startSource(int uid, String processName) {
mTmpSourceKey.mUid = uid;
mTmpSourceKey.mProcess = processName;
SourceState src = mSources.get(mTmpSourceKey);
if (src == null) {
- src = new SourceState();
- mSources.put(new SourceKey(uid, processName), src);
+ SourceKey key = new SourceKey(uid, processName);
+ src = new SourceState(key);
+ mSources.put(key, src);
}
src.mNesting++;
if (src.mNesting == 1) {
src.mCount++;
- src.mStartTime = SystemClock.uptimeMillis();
+ src.mStartUptime = SystemClock.uptimeMillis();
mNumActive++;
}
return src;
@@ -138,11 +260,13 @@
final SourceState otherSrc = other.mSources.valueAt(isrc);
SourceState mySrc = mSources.get(key);
if (mySrc == null) {
- mySrc = new SourceState();
+ mySrc = new SourceState(key);
mSources.put(key, mySrc);
}
mySrc.mCount += otherSrc.mCount;
mySrc.mDuration += otherSrc.mDuration;
+ mySrc.mActiveCount += otherSrc.mActiveCount;
+ mySrc.mActiveDuration += otherSrc.mActiveDuration;
}
}
@@ -160,8 +284,15 @@
SourceState src = mSources.valueAt(isrc);
if (src.mNesting > 0) {
src.mCount = 1;
- src.mStartTime = now;
+ src.mStartUptime = now;
src.mDuration = 0;
+ if (src.mActiveStartUptime > 0) {
+ src.mActiveCount = 1;
+ src.mActiveStartUptime = now;
+ } else {
+ src.mActiveCount = 0;
+ }
+ src.mActiveDuration = 0;
} else {
mSources.removeAt(isrc);
}
@@ -169,7 +300,7 @@
}
}
- public void writeToParcel(ProcessStats stats, Parcel out, long now) {
+ public void writeToParcel(ProcessStats stats, Parcel out, long nowUptime) {
mDurations.writeToParcel(out);
final int NSRC = mSources.size();
out.writeInt(NSRC);
@@ -180,9 +311,15 @@
stats.writeCommonString(out, key.mProcess);
out.writeInt(src.mCount);
out.writeLong(src.mDuration);
+ out.writeInt(src.mActiveCount);
+ out.writeLong(src.mActiveDuration);
}
}
+ /**
+ * Returns non-null if all else fine, else a String that describes the error that
+ * caused it to fail.
+ */
public String readFromParcel(ProcessStats stats, Parcel in, int parcelVersion) {
if (!mDurations.readFromParcel(in)) {
return "Duration table corrupt";
@@ -195,21 +332,27 @@
final int uid = in.readInt();
final String procName = stats.readCommonString(in, parcelVersion);
final SourceKey key = new SourceKey(uid, procName);
- final SourceState src = new SourceState();
+ final SourceState src = new SourceState(key);
src.mCount = in.readInt();
src.mDuration = in.readLong();
+ src.mActiveCount = in.readInt();
+ src.mActiveDuration = in.readLong();
mSources.put(key, src);
}
return null;
}
- public void commitStateTime(long now) {
+ public void commitStateTime(long nowUptime) {
if (isInUse()) {
for (int isrc = mSources.size() - 1; isrc >= 0; isrc--) {
SourceState src = mSources.valueAt(isrc);
if (src.mNesting > 0) {
- src.mDuration += now - src.mStartTime;
- src.mStartTime = now;
+ src.mDuration += nowUptime - src.mStartUptime;
+ src.mStartUptime = nowUptime;
+ }
+ if (src.mActiveStartUptime > 0) {
+ src.mActiveDuration += nowUptime - src.mActiveStartUptime;
+ src.mActiveStartUptime = nowUptime;
}
}
}
@@ -237,7 +380,7 @@
pw.print(src.mCount);
long duration = src.mDuration;
if (src.mNesting > 0) {
- duration += now - src.mStartTime;
+ duration += now - src.mStartUptime;
}
if (dumpAll) {
pw.print(" / Duration ");
@@ -248,9 +391,37 @@
}
DumpUtils.printPercent(pw, (double)duration/(double)totalTime);
if (src.mNesting > 0) {
- pw.print(" (running)");
+ pw.print(" (running");
+ if (src.mProcState != ProcessStats.STATE_NOTHING) {
+ pw.print(" / ");
+ pw.print(DumpUtils.STATE_NAMES[src.mProcState]);
+ pw.print(" #");
+ pw.print(src.mProcStateSeq);
+ }
+ pw.print(")");
}
pw.println();
+ if (src.mActiveCount > 0) {
+ pw.print(prefixInner);
+ pw.print(" Active count ");
+ pw.print(src.mActiveCount);
+ duration = src.mActiveDuration;
+ if (src.mActiveStartUptime > 0) {
+ duration += now - src.mActiveStartUptime;
+ }
+ if (dumpAll) {
+ pw.print(" / Duration ");
+ TimeUtils.formatDuration(duration, pw);
+ pw.print(" / ");
+ } else {
+ pw.print(" / time ");
+ }
+ DumpUtils.printPercent(pw, (double)duration/(double)totalTime);
+ if (src.mActiveStartUptime > 0) {
+ pw.print(" (running)");
+ }
+ pw.println();
+ }
}
}
@@ -277,7 +448,15 @@
pw.print(src.mCount);
long duration = src.mDuration;
if (src.mNesting > 0) {
- duration += now - src.mStartTime;
+ duration += now - src.mStartUptime;
+ }
+ pw.print(",");
+ pw.print(duration);
+ pw.print(",");
+ pw.print(src.mActiveCount);
+ duration = src.mActiveDuration;
+ if (src.mActiveStartUptime > 0) {
+ duration += now - src.mActiveStartUptime;
}
pw.print(",");
pw.print(duration);
@@ -287,7 +466,7 @@
public String toString() {
return "AssociationState{" + Integer.toHexString(System.identityHashCode(this))
- + " " + mName + " pkg=" + mPackage + " proc="
- + Integer.toHexString(System.identityHashCode(this)) + "}";
+ + " " + mName + " pkg=" + mPackageState.mPackageName + " proc="
+ + Integer.toHexString(System.identityHashCode(mProc)) + "}";
}
}
diff --git a/core/java/com/android/internal/app/procstats/ProcessState.java b/core/java/com/android/internal/app/procstats/ProcessState.java
index 5a08f62..dbf7c93 100644
--- a/core/java/com/android/internal/app/procstats/ProcessState.java
+++ b/core/java/com/android/internal/app/procstats/ProcessState.java
@@ -71,7 +71,7 @@
private static final boolean DEBUG_PARCEL = false;
// Map from process states to the states we track.
- private static final int[] PROCESS_STATE_TO_STATE = new int[] {
+ static final int[] PROCESS_STATE_TO_STATE = new int[] {
STATE_PERSISTENT, // ActivityManager.PROCESS_STATE_PERSISTENT
STATE_PERSISTENT, // ActivityManager.PROCESS_STATE_PERSISTENT_UI
STATE_TOP, // ActivityManager.PROCESS_STATE_TOP
@@ -378,6 +378,10 @@
}
}
+ public int getState() {
+ return mCurState;
+ }
+
public void commitStateTime(long now) {
if (mCurState != STATE_NOTHING) {
long dur = now - mStartTime;
diff --git a/core/java/com/android/internal/app/procstats/ProcessStats.java b/core/java/com/android/internal/app/procstats/ProcessStats.java
index 1f871d9..3cafa5e 100644
--- a/core/java/com/android/internal/app/procstats/ProcessStats.java
+++ b/core/java/com/android/internal/app/procstats/ProcessStats.java
@@ -16,6 +16,7 @@
package com.android.internal.app.procstats;
+import android.content.ComponentName;
import android.os.Debug;
import android.os.Parcel;
import android.os.Parcelable;
@@ -157,7 +158,7 @@
};
// Current version of the parcel format.
- private static final int PARCEL_VERSION = 31;
+ private static final int PARCEL_VERSION = 32;
// In-memory Parcel magic number, used to detect attempts to unmarshall bad data
private static final int MAGIC = 0x50535454;
@@ -168,6 +169,8 @@
public final ProcessMap<LongSparseArray<PackageState>> mPackages = new ProcessMap<>();
public final ProcessMap<ProcessState> mProcesses = new ProcessMap<>();
+ public final ArrayList<AssociationState.SourceState> mTrackingAssociations = new ArrayList<>();
+
public final long[] mMemFactorDurations = new long[ADJ_COUNT];
public int mMemFactor = STATE_NOTHING;
public long mStartTime;
@@ -1203,8 +1206,8 @@
AssociationState asc = hadData
? pkgState.mAssociations.get(associationName) : null;
if (asc == null) {
- asc = new AssociationState(this, pkgName, associationName,
- processName);
+ asc = new AssociationState(this, pkgState, associationName,
+ processName, null);
}
String errorMsg = asc.readFromParcel(this, in, version);
if (errorMsg != null) {
@@ -1308,6 +1311,17 @@
Slog.d(TAG, "GETPROC leaving proc of " + ss);
}
}
+ // Also update active associations.
+ for (int i=commonPkgState.mAssociations.size()-1; i>=0; i--) {
+ AssociationState as = commonPkgState.mAssociations.valueAt(i);
+ if (as.getProcess() == commonProc) {
+ if (DEBUG) Slog.d(TAG, "GETPROC switching association to cloned: "
+ + as);
+ as.setProcess(cloned);
+ } else if (DEBUG) {
+ Slog.d(TAG, "GETPROC leaving proc of " + as);
+ }
+ }
} else {
Slog.w(TAG, "Cloning proc state: no package state " + commonProc.getPackage()
+ "/" + pkgState.mUid + " for proc " + commonProc.getName());
@@ -1356,12 +1370,41 @@
}
final ProcessState procs = processName != null
? getProcessStateLocked(packageName, uid, vers, processName) : null;
- as = new AssociationState(this, packageName, className, processName);
+ as = new AssociationState(this, pkgs, className, processName, procs);
pkgs.mAssociations.put(className, as);
if (DEBUG) Slog.d(TAG, "GETASC: creating " + as + " in " + procs);
return as;
}
+ public void updateTrackingAssociationsLocked(int curSeq, long now) {
+ final int NUM = mTrackingAssociations.size();
+ for (int i = NUM - 1; i >= 0; i--) {
+ final AssociationState.SourceState act = mTrackingAssociations.get(i);
+ if (act.mProcStateSeq != curSeq) {
+ act.mInTrackingList = false;
+ act.mProcState = STATE_NOTHING;
+ mTrackingAssociations.remove(i);
+ } else {
+ final ProcessState proc = act.getAssociationState().getProcess();
+ if (proc != null) {
+ if (act.mProcState == proc.getState()) {
+ act.startActive(now);
+ } else {
+ act.stopActive(now);
+ if (act.mProcState < proc.getState()) {
+ Slog.w(TAG, "Tracking association " + act + " whose proc state "
+ + act.mProcState + " is better than process " + proc
+ + " proc state " + proc.getState());
+ }
+ }
+ } else {
+ Slog.wtf(TAG, "Tracking association without process: " + act
+ + " in " + act.getAssociationState());
+ }
+ }
+ }
+ }
+
public void dumpLocked(PrintWriter pw, String reqPackage, long now, boolean dumpSummary,
boolean dumpAll, boolean activeOnly) {
long totalTime = DumpUtils.dumpSingleTime(null, null, mMemFactorDurations, mMemFactor,
@@ -1543,10 +1586,70 @@
proc.dumpInternalLocked(pw, " ", dumpAll);
}
}
+
if (dumpAll) {
- pw.println();
+ if (sepNeeded) {
+ pw.println();
+ }
+ sepNeeded = true;
pw.print(" Total procs: "); pw.print(numShownProcs);
pw.print(" shown of "); pw.print(numTotalProcs); pw.println(" total");
+ if (mTrackingAssociations.size() > 0) {
+ pw.println();
+ pw.println("Tracking associations:");
+ for (int i = 0; i < mTrackingAssociations.size(); i++) {
+ final AssociationState.SourceState src = mTrackingAssociations.get(i);
+ final AssociationState asc = src.getAssociationState();
+ pw.print(" #");
+ pw.print(i);
+ pw.print(": ");
+ pw.print(asc.getProcessName());
+ pw.print("/");
+ UserHandle.formatUid(pw, asc.getUid());
+ pw.print(" <- ");
+ pw.print(src.getProcessName());
+ pw.print("/");
+ UserHandle.formatUid(pw, src.getUid());
+ pw.println(":");
+ pw.print(" Tracking for: ");
+ TimeUtils.formatDuration(now - src.mTrackingUptime, pw);
+ pw.println();
+ pw.print(" Component: ");
+ pw.print(new ComponentName(asc.getPackage(), asc.getName())
+ .flattenToShortString());
+ pw.println();
+ pw.print(" Proc state: ");
+ if (src.mProcState != ProcessStats.STATE_NOTHING) {
+ pw.print(DumpUtils.STATE_NAMES[src.mProcState]);
+ } else {
+ pw.print("--");
+ }
+ pw.print(" #");
+ pw.println(src.mProcStateSeq);
+ pw.print(" Process: ");
+ pw.println(asc.getProcess());
+ if (src.mActiveCount > 0) {
+ pw.print(" Active count ");
+ pw.print(src.mActiveCount);
+ long duration = src.mActiveDuration;
+ if (src.mActiveStartUptime > 0) {
+ duration += now - src.mActiveStartUptime;
+ }
+ if (dumpAll) {
+ pw.print(" / Duration ");
+ TimeUtils.formatDuration(duration, pw);
+ pw.print(" / ");
+ } else {
+ pw.print(" / time ");
+ }
+ DumpUtils.printPercent(pw, (double)duration/(double)totalTime);
+ if (src.mActiveStartUptime > 0) {
+ pw.print(" (running)");
+ }
+ pw.println();
+ }
+ }
+ }
}
if (sepNeeded) {
@@ -1985,15 +2088,19 @@
mVersionCode = versionCode;
}
- public AssociationState getAssociationStateLocked(String processName, String className) {
+ public AssociationState getAssociationStateLocked(ProcessState proc, String className) {
AssociationState as = mAssociations.get(className);
if (as != null) {
if (DEBUG) Slog.d(TAG, "GETASC: returning existing " + as);
+ if (proc != null) {
+ as.setProcess(proc);
+ }
return as;
}
- as = new AssociationState(mProcessStats, mPackageName, className, processName);
+ as = new AssociationState(mProcessStats, this, className, proc.getName(),
+ proc);
mAssociations.put(className, as);
- if (DEBUG) Slog.d(TAG, "GETASC: creating " + as + " in " + processName);
+ if (DEBUG) Slog.d(TAG, "GETASC: creating " + as + " in " + proc.getName());
return as;
}
}
diff --git a/core/java/com/android/internal/app/procstats/ServiceState.java b/core/java/com/android/internal/app/procstats/ServiceState.java
index 53ed5c0..04e61e0 100644
--- a/core/java/com/android/internal/app/procstats/ServiceState.java
+++ b/core/java/com/android/internal/app/procstats/ServiceState.java
@@ -554,6 +554,6 @@
public String toString() {
return "ServiceState{" + Integer.toHexString(System.identityHashCode(this))
+ " " + mName + " pkg=" + mPackage + " proc="
- + Integer.toHexString(System.identityHashCode(this)) + "}";
+ + Integer.toHexString(System.identityHashCode(mProc)) + "}";
}
}
diff --git a/core/java/com/android/internal/net/NetworkStatsFactory.java b/core/java/com/android/internal/net/NetworkStatsFactory.java
index c4d08c7..d1c2799 100644
--- a/core/java/com/android/internal/net/NetworkStatsFactory.java
+++ b/core/java/com/android/internal/net/NetworkStatsFactory.java
@@ -194,7 +194,7 @@
reader.finishLine();
}
} catch (NullPointerException|NumberFormatException e) {
- throw new ProtocolException("problem parsing stats", e);
+ throw protocolExceptionWithCause("problem parsing stats", e);
} finally {
IoUtils.closeQuietly(reader);
StrictMode.setThreadPolicy(savedPolicy);
@@ -244,7 +244,7 @@
reader.finishLine();
}
} catch (NullPointerException|NumberFormatException e) {
- throw new ProtocolException("problem parsing stats", e);
+ throw protocolExceptionWithCause("problem parsing stats", e);
} finally {
IoUtils.closeQuietly(reader);
StrictMode.setThreadPolicy(savedPolicy);
@@ -341,7 +341,7 @@
reader.finishLine();
}
} catch (NullPointerException|NumberFormatException e) {
- throw new ProtocolException("problem parsing idx " + idx, e);
+ throw protocolExceptionWithCause("problem parsing idx " + idx, e);
} finally {
IoUtils.closeQuietly(reader);
StrictMode.setThreadPolicy(savedPolicy);
@@ -378,4 +378,10 @@
@VisibleForTesting
public static native int nativeReadNetworkStatsDev(NetworkStats stats);
+
+ private static ProtocolException protocolExceptionWithCause(String message, Throwable cause) {
+ ProtocolException pe = new ProtocolException(message);
+ pe.initCause(cause);
+ return pe;
+ }
}
diff --git a/core/java/com/android/internal/os/BatteryStatsImpl.java b/core/java/com/android/internal/os/BatteryStatsImpl.java
index 79d2570..df59f79 100644
--- a/core/java/com/android/internal/os/BatteryStatsImpl.java
+++ b/core/java/com/android/internal/os/BatteryStatsImpl.java
@@ -12709,7 +12709,7 @@
if (mMinLearnedBatteryCapacity == -1) {
mMinLearnedBatteryCapacity = chargeFullUAh;
} else {
- Math.min(mMinLearnedBatteryCapacity, chargeFullUAh);
+ mMinLearnedBatteryCapacity = Math.min(mMinLearnedBatteryCapacity, chargeFullUAh);
}
mMaxLearnedBatteryCapacity = Math.max(mMaxLearnedBatteryCapacity, chargeFullUAh);
}
diff --git a/core/java/com/android/internal/os/BinderCallsStats.java b/core/java/com/android/internal/os/BinderCallsStats.java
index 75d714f..6177923 100644
--- a/core/java/com/android/internal/os/BinderCallsStats.java
+++ b/core/java/com/android/internal/os/BinderCallsStats.java
@@ -16,11 +16,14 @@
package com.android.internal.os;
+import android.annotation.Nullable;
import android.os.Binder;
import android.os.SystemClock;
import android.os.UserHandle;
import android.text.format.DateFormat;
import android.util.ArrayMap;
+import android.util.Log;
+import android.util.Pair;
import android.util.SparseArray;
import com.android.internal.annotations.GuardedBy;
@@ -29,10 +32,12 @@
import java.io.PrintWriter;
import java.util.ArrayList;
+import java.util.Collections;
import java.util.Comparator;
import java.util.List;
import java.util.Map;
import java.util.Queue;
+import java.util.Set;
import java.util.concurrent.ConcurrentLinkedQueue;
import java.util.function.ToDoubleFunction;
@@ -41,38 +46,52 @@
* per thread, uid or call description.
*/
public class BinderCallsStats {
+ public static final boolean ENABLED_DEFAULT = true;
+ public static final boolean DETAILED_TRACKING_DEFAULT = true;
+ public static final int PERIODIC_SAMPLING_INTERVAL_DEFAULT = 10;
+
+ private static final String TAG = "BinderCallsStats";
private static final int CALL_SESSIONS_POOL_SIZE = 100;
private static final int PERIODIC_SAMPLING_INTERVAL = 10;
+ private static final int MAX_EXCEPTION_COUNT_SIZE = 50;
+ private static final String EXCEPTION_COUNT_OVERFLOW_NAME = "overflow";
+ private static final CallSession NOT_ENABLED = new CallSession();
private static final BinderCallsStats sInstance = new BinderCallsStats();
- private volatile boolean mDetailedTracking = false;
+ private volatile boolean mEnabled = ENABLED_DEFAULT;
+ private volatile boolean mDetailedTracking = DETAILED_TRACKING_DEFAULT;
+ private volatile int mPeriodicSamplingInterval = PERIODIC_SAMPLING_INTERVAL_DEFAULT;
@GuardedBy("mLock")
private final SparseArray<UidEntry> mUidEntries = new SparseArray<>();
+ @GuardedBy("mLock")
+ private final ArrayMap<String, Integer> mExceptionCounts = new ArrayMap<>();
private final Queue<CallSession> mCallSessionsPool = new ConcurrentLinkedQueue<>();
private final Object mLock = new Object();
private long mStartTime = System.currentTimeMillis();
@GuardedBy("mLock")
private UidEntry mSampledEntries = new UidEntry(-1);
- private BinderCallsStats() {
- }
-
- @VisibleForTesting
- public BinderCallsStats(boolean detailedTracking) {
- mDetailedTracking = detailedTracking;
+ @VisibleForTesting // Use getInstance() instead.
+ public BinderCallsStats() {
}
public CallSession callStarted(Binder binder, int code) {
- return callStarted(binder.getClass().getName(), code);
+ return callStarted(binder.getClass().getName(), code, binder.getTransactionName(code));
}
- private CallSession callStarted(String className, int code) {
+ private CallSession callStarted(String className, int code, @Nullable String methodName) {
+ if (!mEnabled) {
+ return NOT_ENABLED;
+ }
+
CallSession s = mCallSessionsPool.poll();
if (s == null) {
s = new CallSession();
}
+
s.callStat.className = className;
s.callStat.msg = code;
+ s.callStat.methodName = methodName;
s.exceptionThrown = false;
s.cpuTimeStarted = -1;
s.timeStarted = -1;
@@ -83,7 +102,7 @@
s.timeStarted = getElapsedRealtimeMicro();
} else {
s.sampledCallStat = mSampledEntries.getOrCreate(s.callStat);
- if (s.sampledCallStat.callCount % PERIODIC_SAMPLING_INTERVAL == 0) {
+ if (s.sampledCallStat.callCount % mPeriodicSamplingInterval == 0) {
s.cpuTimeStarted = getThreadTimeMicro();
s.timeStarted = getElapsedRealtimeMicro();
}
@@ -94,7 +113,23 @@
public void callEnded(CallSession s, int parcelRequestSize, int parcelReplySize) {
Preconditions.checkNotNull(s);
+ if (s == NOT_ENABLED) {
+ return;
+ }
+
+ processCallEnded(s, parcelRequestSize, parcelReplySize);
+
+ if (mCallSessionsPool.size() < CALL_SESSIONS_POOL_SIZE) {
+ mCallSessionsPool.add(s);
+ }
+ }
+
+ private void processCallEnded(CallSession s, int parcelRequestSize, int parcelReplySize) {
synchronized (mLock) {
+ if (!mEnabled) {
+ return;
+ }
+
long duration;
long latencyDuration;
if (mDetailedTracking) {
@@ -108,7 +143,7 @@
latencyDuration = getElapsedRealtimeMicro() - s.timeStarted;
} else {
// callCount is always incremented, but time only once per sampling interval
- long samplesCount = cs.callCount / PERIODIC_SAMPLING_INTERVAL + 1;
+ long samplesCount = cs.callCount / mPeriodicSamplingInterval + 1;
duration = cs.cpuTimeMicros / samplesCount;
latencyDuration = cs.latencyMicros / samplesCount;
}
@@ -136,6 +171,7 @@
callStat = s.sampledCallStat;
}
callStat.callCount++;
+ callStat.methodName = s.callStat.methodName;
if (s.cpuTimeStarted >= 0) {
callStat.cpuTimeMicros += duration;
callStat.maxCpuTimeMicros = Math.max(callStat.maxCpuTimeMicros, duration);
@@ -146,9 +182,6 @@
uidEntry.cpuTimeMicros += duration;
uidEntry.callCount++;
}
- if (mCallSessionsPool.size() < CALL_SESSIONS_POOL_SIZE) {
- mCallSessionsPool.add(s);
- }
}
/**
@@ -158,9 +191,25 @@
* <li>Do not throw an exception in this method, it will swallow the original exception thrown
* by the binder transaction.
*/
- public void callThrewException(CallSession s) {
+ public void callThrewException(CallSession s, Exception exception) {
Preconditions.checkNotNull(s);
+ if (!mEnabled) {
+ return;
+ }
s.exceptionThrown = true;
+ try {
+ String className = exception.getClass().getName();
+ synchronized (mLock) {
+ if (mExceptionCounts.size() >= MAX_EXCEPTION_COUNT_SIZE) {
+ className = EXCEPTION_COUNT_OVERFLOW_NAME;
+ }
+ Integer count = mExceptionCounts.get(className);
+ mExceptionCounts.put(className, count == null ? 1 : count + 1);
+ }
+ } catch (RuntimeException e) {
+ // Do not propagate the exception. We do not want to swallow original exception.
+ Log.wtf(TAG, "Unexpected exception while updating mExceptionCounts", e);
+ }
}
public void dump(PrintWriter pw, Map<Integer,String> appIdToPkgNameMap, boolean verbose) {
@@ -170,6 +219,11 @@
}
private void dumpLocked(PrintWriter pw, Map<Integer,String> appIdToPkgNameMap, boolean verbose) {
+ if (!mEnabled) {
+ pw.println("Binder calls stats disabled.");
+ return;
+ }
+
long totalCallsCount = 0;
long totalCpuTime = 0;
pw.print("Start time: ");
@@ -189,16 +243,17 @@
StringBuilder sb = new StringBuilder();
if (mDetailedTracking) {
pw.println("Per-UID raw data " + datasetSizeDesc
- + "(uid, call_desc, cpu_time_micros, max_cpu_time_micros, latency_time_micros, "
- + "max_latency_time_micros, exception_count, max_request_size_bytes, "
- + "max_reply_size_bytes, call_count):");
+ + "(package/uid, call_desc, cpu_time_micros, max_cpu_time_micros, "
+ + "latency_time_micros, max_latency_time_micros, exception_count, "
+ + "max_request_size_bytes, max_reply_size_bytes, call_count):");
List<UidEntry> topEntries = verbose ? entries
: getHighestValues(entries, value -> value.cpuTimeMicros, 0.9);
for (UidEntry uidEntry : topEntries) {
for (CallStat e : uidEntry.getCallStatsList()) {
sb.setLength(0);
sb.append(" ")
- .append(uidEntry.uid).append(",").append(e)
+ .append(uidToString(uidEntry.uid, appIdToPkgNameMap))
+ .append(",").append(e)
.append(',').append(e.cpuTimeMicros)
.append(',').append(e.maxCpuTimeMicros)
.append(',').append(e.latencyMicros)
@@ -223,7 +278,7 @@
for (CallStat e : sampledStatsList) {
sb.setLength(0);
sb.append(" ").append(e)
- .append(',').append(e.cpuTimeMicros * PERIODIC_SAMPLING_INTERVAL)
+ .append(',').append(e.cpuTimeMicros * mPeriodicSamplingInterval)
.append(',').append(e.callCount)
.append(',').append(e.exceptionCount);
pw.println(sb);
@@ -244,6 +299,18 @@
pw.println(String.format(" Summary: total_cpu_time=%d, "
+ "calls_count=%d, avg_call_cpu_time=%.0f",
totalCpuTime, totalCallsCount, (double)totalCpuTime / totalCallsCount));
+ pw.println();
+
+ pw.println("Exceptions thrown (exception_count, class_name):");
+ List<Pair<String, Integer>> exceptionEntries = new ArrayList<>();
+ // We cannot use new ArrayList(Collection) constructor because MapCollections does not
+ // implement toArray method.
+ mExceptionCounts.entrySet().iterator().forEachRemaining(
+ (e) -> exceptionEntries.add(Pair.create(e.getKey(), e.getValue())));
+ exceptionEntries.sort((e1, e2) -> Integer.compare(e2.second, e1.second));
+ for (Pair<String, Integer> entry : exceptionEntries) {
+ pw.println(String.format(" %6d %s", entry.second, entry.first));
+ }
}
private static String uidToString(int uid, Map<Integer, String> pkgNameMap) {
@@ -270,15 +337,36 @@
}
public void setDetailedTracking(boolean enabled) {
- if (enabled != mDetailedTracking) {
- reset();
- mDetailedTracking = enabled;
+ synchronized (mLock) {
+ if (enabled != mDetailedTracking) {
+ mDetailedTracking = enabled;
+ reset();
+ }
+ }
+ }
+
+ public void setEnabled(boolean enabled) {
+ synchronized (mLock) {
+ if (enabled != mEnabled) {
+ mEnabled = enabled;
+ reset();
+ }
+ }
+ }
+
+ public void setSamplingInterval(int samplingInterval) {
+ synchronized (mLock) {
+ if (samplingInterval != mPeriodicSamplingInterval) {
+ mPeriodicSamplingInterval = samplingInterval;
+ reset();
+ }
}
}
public void reset() {
synchronized (mLock) {
mUidEntries.clear();
+ mExceptionCounts.clear();
mSampledEntries.mCallStats.clear();
mStartTime = System.currentTimeMillis();
}
@@ -288,6 +376,9 @@
public static class CallStat {
public String className;
public int msg;
+ // Method name might be null when we cannot resolve the transaction code. For instance, if
+ // the binder was not generated by AIDL.
+ public @Nullable String methodName;
public long cpuTimeMicros;
public long maxCpuTimeMicros;
public long latencyMicros;
@@ -326,7 +417,7 @@
@Override
public String toString() {
- return className + "/" + msg;
+ return className + "#" + (methodName == null ? msg : methodName);
}
}
@@ -414,6 +505,11 @@
}
@VisibleForTesting
+ public ArrayMap<String, Integer> getExceptionCounts() {
+ return mExceptionCounts;
+ }
+
+ @VisibleForTesting
public static <T> List<T> getHighestValues(List<T> list, ToDoubleFunction<T> toDouble,
double percentile) {
List<T> sortedList = new ArrayList<>(list);
diff --git a/core/java/com/android/internal/util/ArrayUtils.java b/core/java/com/android/internal/util/ArrayUtils.java
index 621619c..be645fe 100644
--- a/core/java/com/android/internal/util/ArrayUtils.java
+++ b/core/java/com/android/internal/util/ArrayUtils.java
@@ -626,4 +626,17 @@
public static @NonNull String[] defeatNullable(@Nullable String[] val) {
return (val != null) ? val : EmptyArray.STRING;
}
+
+ /**
+ * Throws {@link ArrayIndexOutOfBoundsException} if the index is out of bounds.
+ *
+ * @param len length of the array. Must be non-negative
+ * @param index the index to check
+ * @throws ArrayIndexOutOfBoundsException if the {@code index} is out of bounds of the array
+ */
+ public static void checkBounds(int len, int index) {
+ if (index < 0 || len <= index) {
+ throw new ArrayIndexOutOfBoundsException("length=" + len + "; index=" + index);
+ }
+ }
}
diff --git a/core/java/com/android/internal/util/DumpUtils.java b/core/java/com/android/internal/util/DumpUtils.java
index 7fd83bc..f6d80a5 100644
--- a/core/java/com/android/internal/util/DumpUtils.java
+++ b/core/java/com/android/internal/util/DumpUtils.java
@@ -34,9 +34,18 @@
/**
* Helper functions for dumping the state of system services.
* Test:
- atest /android/pi-dev/frameworks/base/core/tests/coretests/src/com/android/internal/util/DumpUtilsTest.java
+ atest FrameworksCoreTests:DumpUtilsTest
*/
public final class DumpUtils {
+
+ /**
+ * List of component names that should be dumped in the bug report critical section.
+ *
+ * @hide
+ */
+ public static final ComponentName[] CRITICAL_SECTION_COMPONENTS = {
+ new ComponentName("com.android.systemui", "com.android.systemui.SystemUIService")
+ };
private static final String TAG = "DumpUtils";
private static final boolean DEBUG = false;
@@ -213,6 +222,45 @@
}
/**
+ * Return whether a package should be dumped in the critical section.
+ */
+ private static boolean isCriticalPackage(@Nullable ComponentName cname) {
+ if (cname == null) {
+ return false;
+ }
+
+ for (int i = 0; i < CRITICAL_SECTION_COMPONENTS.length; i++) {
+ if (cname.equals(CRITICAL_SECTION_COMPONENTS[i])) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ /**
+ * Return whether a package name is considered to be part of the platform and in the critical
+ * section.
+ *
+ * @hide
+ */
+ public static boolean isPlatformCriticalPackage(@Nullable ComponentName.WithComponentName wcn) {
+ return (wcn != null) && isPlatformPackage(wcn.getComponentName()) &&
+ isCriticalPackage(wcn.getComponentName());
+ }
+
+ /**
+ * Return whether a package name is considered to be part of the platform but not in the the
+ * critical section.
+ *
+ * @hide
+ */
+ public static boolean isPlatformNonCriticalPackage(
+ @Nullable ComponentName.WithComponentName wcn) {
+ return (wcn != null) && isPlatformPackage(wcn.getComponentName()) &&
+ !isCriticalPackage(wcn.getComponentName());
+ }
+
+ /**
* Used for dumping providers and services. Return a predicate for a given filter string.
* @hide
*/
@@ -238,6 +286,16 @@
return DumpUtils::isNonPlatformPackage;
}
+ // Dump all platform-critical?
+ if ("all-platform-critical".equals(filterString)) {
+ return DumpUtils::isPlatformCriticalPackage;
+ }
+
+ // Dump all platform-non-critical?
+ if ("all-platform-non-critical".equals(filterString)) {
+ return DumpUtils::isPlatformNonCriticalPackage;
+ }
+
// Is the filter a component name? If so, do an exact match.
final ComponentName filterCname = ComponentName.unflattenFromString(filterString);
if (filterCname != null) {
diff --git a/core/jni/android_media_MediaMetricsJNI.h b/core/jni/android_media_MediaMetricsJNI.h
index 16081b4..b3cb4d2 100644
--- a/core/jni/android_media_MediaMetricsJNI.h
+++ b/core/jni/android_media_MediaMetricsJNI.h
@@ -17,7 +17,6 @@
#ifndef _ANDROID_MEDIA_MEDIAMETRICSJNI_H_
#define _ANDROID_MEDIA_MEDIAMETRICSJNI_H_
-#include <android_runtime/AndroidRuntime.h>
#include <jni.h>
#include <nativehelper/JNIHelp.h>
#include <media/MediaAnalyticsItem.h>
diff --git a/core/jni/android_util_Binder.cpp b/core/jni/android_util_Binder.cpp
index c3ba9ba..7e2bad2 100644
--- a/core/jni/android_util_Binder.cpp
+++ b/core/jni/android_util_Binder.cpp
@@ -155,9 +155,8 @@
static constexpr int32_t PROXY_WARN_INTERVAL = 5000;
static constexpr uint32_t GC_INTERVAL = 1000;
-// Protected by gProxyLock. We warn if this gets too large.
-static int32_t gNumProxies = 0;
-static int32_t gProxiesWarned = 0;
+static std::atomic<uint32_t> gNumProxies(0);
+static std::atomic<uint32_t> gProxiesWarned(0);
// Number of GlobalRefs held by JavaBBinders.
static std::atomic<uint32_t> gNumLocalRefsCreated(0);
@@ -632,12 +631,6 @@
return (BinderProxyNativeData *) env->GetLongField(obj, gBinderProxyOffsets.mNativeData);
}
-static Mutex gProxyLock;
-
-// We may cache a single BinderProxyNativeData node to avoid repeat allocation.
-// All fields are null. Protected by gProxyLock.
-static BinderProxyNativeData *gNativeDataCache;
-
// If the argument is a JavaBBinder, return the Java object that was used to create it.
// Otherwise return a BinderProxy for the IBinder. If a previous call was passed the
// same IBinder, and the original BinderProxy is still alive, return the same BinderProxy.
@@ -652,36 +645,31 @@
return object;
}
- // For the rest of the function we will hold this lock, to serialize
- // looking/creation/destruction of Java proxies for native Binder proxies.
- AutoMutex _l(gProxyLock);
+ BinderProxyNativeData* nativeData = new BinderProxyNativeData();
+ nativeData->mOrgue = new DeathRecipientList;
+ nativeData->mObject = val;
- BinderProxyNativeData* nativeData = gNativeDataCache;
- if (nativeData == nullptr) {
- nativeData = new BinderProxyNativeData();
- }
- // gNativeDataCache is now logically empty.
jobject object = env->CallStaticObjectMethod(gBinderProxyOffsets.mClass,
gBinderProxyOffsets.mGetInstance, (jlong) nativeData, (jlong) val.get());
if (env->ExceptionCheck()) {
// In the exception case, getInstance still took ownership of nativeData.
- gNativeDataCache = nullptr;
return NULL;
}
BinderProxyNativeData* actualNativeData = getBPNativeData(env, object);
if (actualNativeData == nativeData) {
- // New BinderProxy; we still have exclusive access.
- nativeData->mOrgue = new DeathRecipientList;
- nativeData->mObject = val;
- gNativeDataCache = nullptr;
- ++gNumProxies;
- if (gNumProxies >= gProxiesWarned + PROXY_WARN_INTERVAL) {
- ALOGW("Unexpectedly many live BinderProxies: %d\n", gNumProxies);
- gProxiesWarned = gNumProxies;
+ // Created a new Proxy
+ uint32_t numProxies = gNumProxies.fetch_add(1, std::memory_order_relaxed);
+ uint32_t numLastWarned = gProxiesWarned.load(std::memory_order_relaxed);
+ if (numProxies >= numLastWarned + PROXY_WARN_INTERVAL) {
+ // Multiple threads can get here, make sure only one of them gets to
+ // update the warn counter.
+ if (gProxiesWarned.compare_exchange_strong(numLastWarned,
+ numLastWarned + PROXY_WARN_INTERVAL, std::memory_order_relaxed)) {
+ ALOGW("Unexpectedly many live BinderProxies: %d\n", numProxies);
+ }
}
} else {
- // nativeData wasn't used. Reuse it the next time.
- gNativeDataCache = nativeData;
+ delete nativeData;
}
return object;
@@ -959,8 +947,7 @@
jint android_os_Debug_getProxyObjectCount(JNIEnv* env, jobject clazz)
{
- AutoMutex _l(gProxyLock);
- return gNumProxies;
+ return gNumProxies.load();
}
jint android_os_Debug_getDeathObjectCount(JNIEnv* env, jobject clazz)
@@ -1008,8 +995,6 @@
{
JNIEnv *env = AndroidRuntime::getJNIEnv();
{
- // Calls into BinderProxy must be serialized
- AutoMutex _l(gProxyLock);
env->CallStaticObjectMethod(gBinderProxyOffsets.mClass,
gBinderProxyOffsets.mDumpProxyDebugInfo);
}
@@ -1367,9 +1352,6 @@
static void BinderProxy_destroy(void* rawNativeData)
{
- // Don't race with construction/initialization
- AutoMutex _l(gProxyLock);
-
BinderProxyNativeData * nativeData = (BinderProxyNativeData *) rawNativeData;
LOGDEATH("Destroying BinderProxy: binder=%p drl=%p\n",
nativeData->mObject.get(), nativeData->mOrgue.get());
diff --git a/core/jni/android_view_InputEventSender.cpp b/core/jni/android_view_InputEventSender.cpp
index 095252c..10da892 100644
--- a/core/jni/android_view_InputEventSender.cpp
+++ b/core/jni/android_view_InputEventSender.cpp
@@ -114,8 +114,8 @@
uint32_t publishedSeq = mNextPublishedSeq++;
status_t status = mInputPublisher.publishKeyEvent(publishedSeq,
- event->getDeviceId(), event->getSource(), event->getAction(), event->getFlags(),
- event->getKeyCode(), event->getScanCode(), event->getMetaState(),
+ event->getDeviceId(), event->getSource(), event->getDisplayId(), event->getAction(),
+ event->getFlags(), event->getKeyCode(), event->getScanCode(), event->getMetaState(),
event->getRepeatCount(), event->getDownTime(), event->getEventTime());
if (status) {
ALOGW("Failed to send key event on channel '%s'. status=%d",
@@ -135,8 +135,7 @@
for (size_t i = 0; i <= event->getHistorySize(); i++) {
publishedSeq = mNextPublishedSeq++;
status_t status = mInputPublisher.publishMotionEvent(publishedSeq,
- event->getDeviceId(), event->getSource(),
- event->getDisplayId(),
+ event->getDeviceId(), event->getSource(), event->getDisplayId(),
event->getAction(), event->getActionButton(), event->getFlags(),
event->getEdgeFlags(), event->getMetaState(), event->getButtonState(),
event->getXOffset(), event->getYOffset(),
diff --git a/core/jni/android_view_KeyEvent.cpp b/core/jni/android_view_KeyEvent.cpp
index 8a6e745..f010772 100644
--- a/core/jni/android_view_KeyEvent.cpp
+++ b/core/jni/android_view_KeyEvent.cpp
@@ -39,6 +39,7 @@
jfieldID mDeviceId;
jfieldID mSource;
+ jfieldID mDisplayId;
jfieldID mMetaState;
jfieldID mAction;
jfieldID mKeyCode;
@@ -65,6 +66,7 @@
event->getScanCode(),
event->getFlags(),
event->getSource(),
+ event->getDisplayId(),
NULL);
if (env->ExceptionCheck()) {
ALOGE("An exception occurred while obtaining a key event.");
@@ -79,6 +81,7 @@
KeyEvent* event) {
jint deviceId = env->GetIntField(eventObj, gKeyEventClassInfo.mDeviceId);
jint source = env->GetIntField(eventObj, gKeyEventClassInfo.mSource);
+ jint displayId = env->GetIntField(eventObj, gKeyEventClassInfo.mDisplayId);
jint metaState = env->GetIntField(eventObj, gKeyEventClassInfo.mMetaState);
jint action = env->GetIntField(eventObj, gKeyEventClassInfo.mAction);
jint keyCode = env->GetIntField(eventObj, gKeyEventClassInfo.mKeyCode);
@@ -88,7 +91,8 @@
jlong downTime = env->GetLongField(eventObj, gKeyEventClassInfo.mDownTime);
jlong eventTime = env->GetLongField(eventObj, gKeyEventClassInfo.mEventTime);
- event->initialize(deviceId, source, action, flags, keyCode, scanCode, metaState, repeatCount,
+ event->initialize(deviceId, source, displayId, action, flags, keyCode, scanCode, metaState,
+ repeatCount,
milliseconds_to_nanoseconds(downTime),
milliseconds_to_nanoseconds(eventTime));
return OK;
@@ -131,12 +135,14 @@
gKeyEventClassInfo.clazz = MakeGlobalRefOrDie(env, clazz);
gKeyEventClassInfo.obtain = GetStaticMethodIDOrDie(env, gKeyEventClassInfo.clazz,
- "obtain", "(JJIIIIIIIILjava/lang/String;)Landroid/view/KeyEvent;");
+ "obtain", "(JJIIIIIIIIILjava/lang/String;)Landroid/view/KeyEvent;");
gKeyEventClassInfo.recycle = GetMethodIDOrDie(env, gKeyEventClassInfo.clazz,
"recycle", "()V");
gKeyEventClassInfo.mDeviceId = GetFieldIDOrDie(env, gKeyEventClassInfo.clazz, "mDeviceId", "I");
gKeyEventClassInfo.mSource = GetFieldIDOrDie(env, gKeyEventClassInfo.clazz, "mSource", "I");
+ gKeyEventClassInfo.mDisplayId = GetFieldIDOrDie(env, gKeyEventClassInfo.clazz, "mDisplayId",
+ "I");
gKeyEventClassInfo.mMetaState = GetFieldIDOrDie(env, gKeyEventClassInfo.clazz, "mMetaState",
"I");
gKeyEventClassInfo.mAction = GetFieldIDOrDie(env, gKeyEventClassInfo.clazz, "mAction", "I");
diff --git a/core/jni/android_view_RenderNode.cpp b/core/jni/android_view_RenderNode.cpp
index 22bbc3c..46b19bd 100644
--- a/core/jni/android_view_RenderNode.cpp
+++ b/core/jni/android_view_RenderNode.cpp
@@ -222,6 +222,11 @@
RenderNode::GENERIC);
}
+static void android_view_RenderNode_setUsageHint(jlong renderNodePtr, jint usageHint) {
+ RenderNode* renderNode = reinterpret_cast<RenderNode*>(renderNodePtr);
+ renderNode->setUsageHint(static_cast<UsageHint>(usageHint));
+}
+
static jboolean android_view_RenderNode_setElevation(jlong renderNodePtr, float elevation) {
return SET_AND_DIRTY(setElevation, elevation, RenderNode::Z);
}
@@ -614,6 +619,7 @@
{ "nSetAlpha", "(JF)Z", (void*) android_view_RenderNode_setAlpha },
{ "nSetHasOverlappingRendering", "(JZ)Z",
(void*) android_view_RenderNode_setHasOverlappingRendering },
+ { "nSetUsageHint", "(JI)V", (void*) android_view_RenderNode_setUsageHint },
{ "nSetElevation", "(JF)Z", (void*) android_view_RenderNode_setElevation },
{ "nSetTranslationX", "(JF)Z", (void*) android_view_RenderNode_setTranslationX },
{ "nSetTranslationY", "(JF)Z", (void*) android_view_RenderNode_setTranslationY },
diff --git a/core/jni/com_android_internal_os_Zygote.cpp b/core/jni/com_android_internal_os_Zygote.cpp
index caf4e4b4..e30a3e7 100644
--- a/core/jni/com_android_internal_os_Zygote.cpp
+++ b/core/jni/com_android_internal_os_Zygote.cpp
@@ -45,6 +45,7 @@
#include <unistd.h>
#include "android-base/logging.h"
+#include <android-base/properties.h>
#include <android-base/file.h>
#include <android-base/stringprintf.h>
#include <cutils/fs.h>
@@ -70,6 +71,7 @@
using android::String8;
using android::base::StringPrintf;
using android::base::WriteStringToFile;
+using android::base::GetBoolProperty;
#define CREATE_ERROR(...) StringPrintf("%s:%d: ", __FILE__, __LINE__). \
append(StringPrintf(__VA_ARGS__))
@@ -931,12 +933,16 @@
RuntimeAbort(env, __LINE__, "System server process has died. Restarting Zygote!");
}
- // Assign system_server to the correct memory cgroup.
- // Not all devices mount /dev/memcg so check for the file first
- // to avoid unnecessarily printing errors and denials in the logs.
- if (!access("/dev/memcg/system/tasks", F_OK) &&
+ bool low_ram_device = GetBoolProperty("ro.config.low_ram", false);
+ bool per_app_memcg = GetBoolProperty("ro.config.per_app_memcg", low_ram_device);
+ if (per_app_memcg) {
+ // Assign system_server to the correct memory cgroup.
+ // Not all devices mount /dev/memcg so check for the file first
+ // to avoid unnecessarily printing errors and denials in the logs.
+ if (!access("/dev/memcg/system/tasks", F_OK) &&
!WriteStringToFile(StringPrintf("%d", pid), "/dev/memcg/system/tasks")) {
- ALOGE("couldn't write %d to /dev/memcg/system/tasks", pid);
+ ALOGE("couldn't write %d to /dev/memcg/system/tasks", pid);
+ }
}
}
return pid;
diff --git a/core/proto/android/server/windowmanagerservice.proto b/core/proto/android/server/windowmanagerservice.proto
index 7467d8f..2de53b9 100644
--- a/core/proto/android/server/windowmanagerservice.proto
+++ b/core/proto/android/server/windowmanagerservice.proto
@@ -319,6 +319,8 @@
optional bool removed = 36;
optional bool is_on_screen = 37;
optional bool is_visible = 38;
+ optional bool pending_forced_seamless_rotation = 39;
+ optional int64 finished_forced_seamless_rotation_frame = 40;
}
message IdentifierProto {
diff --git a/core/res/res/anim/lock_screen_behind_enter_fade_in.xml b/core/res/res/anim/lock_screen_behind_enter_fade_in.xml
index e9475f5..ff95aea 100644
--- a/core/res/res/anim/lock_screen_behind_enter_fade_in.xml
+++ b/core/res/res/anim/lock_screen_behind_enter_fade_in.xml
@@ -16,7 +16,6 @@
-->
<alpha xmlns:android="http://schemas.android.com/apk/res/android"
- android:background="#ff000000"
android:detachWallpaper="true"
android:shareInterpolator="false"
android:interpolator="@interpolator/linear"
diff --git a/core/res/res/drawable-hdpi/ic_grayedout_printer.png b/core/res/res/drawable-hdpi/ic_grayedout_printer.png
deleted file mode 100644
index 5e54970..0000000
--- a/core/res/res/drawable-hdpi/ic_grayedout_printer.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-mdpi/ic_grayedout_printer.png b/core/res/res/drawable-mdpi/ic_grayedout_printer.png
deleted file mode 100644
index 5e54970..0000000
--- a/core/res/res/drawable-mdpi/ic_grayedout_printer.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/ic_grayedout_printer.png b/core/res/res/drawable-xhdpi/ic_grayedout_printer.png
deleted file mode 100644
index 5e54970..0000000
--- a/core/res/res/drawable-xhdpi/ic_grayedout_printer.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/values-night/values.xml b/core/res/res/values-night/values.xml
new file mode 100644
index 0000000..23b0a24
--- /dev/null
+++ b/core/res/res/values-night/values.xml
@@ -0,0 +1,34 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ ~ Copyright (C) 2018 The Android Open Source Project
+ ~
+ ~ Licensed under the Apache License, Version 2.0 (the "License");
+ ~ you may not use this file except in compliance with the License.
+ ~ You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ Unless required by applicable law or agreed to in writing, software
+ ~ distributed under the License is distributed on an "AS IS" BASIS,
+ ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ~ See the License for the specific language governing permissions and
+ ~ limitations under the License
+ -->
+
+<resources>
+ <style name="Theme.DeviceDefault.QuickSettings" parent="android:Theme.DeviceDefault">
+ <!-- Color palette -->
+ <item name="colorPrimaryDark">@color/primary_dark_device_default_settings</item>
+ <item name="colorSecondary">@color/secondary_device_default_settings</item>
+ <item name="colorAccent">@color/accent_device_default_dark</item>
+ <item name="colorError">@color/error_color_device_default_dark</item>
+ <item name="colorControlNormal">?attr/textColorPrimary</item>
+ <item name="alertDialogTheme">@style/Theme.DeviceDefault.Dialog.Alert</item>
+
+ <!-- QS panel background -->
+ <item name="colorBackgroundFloating">@color/material_grey_900</item>
+
+ <!-- volume background -->
+ <item name="panelColorBackground">@color/material_grey_800</item>
+ </style>
+</resources>
\ No newline at end of file
diff --git a/core/res/res/values/attrs.xml b/core/res/res/values/attrs.xml
index d2684ce..44eea30c 100644
--- a/core/res/res/values/attrs.xml
+++ b/core/res/res/values/attrs.xml
@@ -1477,7 +1477,7 @@
used for, typically, account ID or password input. It is expected that IMEs
normally are able to input ASCII even without being told so (such IMEs
already respect this flag in a sense), but there could be some cases they
- aren't when, for instance, only non-ASCII input languagaes like Arabic,
+ aren't when, for instance, only non-ASCII input languages like Arabic,
Greek, Hebrew, Russian are enabled in the IME. Applications need to be
aware that the flag is not a guarantee, and not all IMEs will respect it.
However, it is strongly recommended for IME authors to respect this flag
@@ -3161,7 +3161,7 @@
enabled by a ViewGroup for all its children in specific situations (for
instance during a scrolling.) This property lets you persist the cache
in memory after its initial usage. Persisting the cache consumes more
- memory but may prevent frequent garbage collection is the cache is created
+ memory but may prevent frequent garbage collection if the cache is created
over and over again. By default the persistence is set to scrolling.
Deprecated: The view drawing cache was largely made obsolete with the introduction of
hardware-accelerated rendering in API 11. -->
diff --git a/core/res/res/values/config.xml b/core/res/res/values/config.xml
index fae4b10b..1862437 100644
--- a/core/res/res/values/config.xml
+++ b/core/res/res/values/config.xml
@@ -583,12 +583,14 @@
<integer translatable="false" name="config_wifi_framework_min_rx_rate_for_staying_on_network">16</integer>
<!-- Integer parameters of the wifi to cellular handover feature
wifi should not stick to bad networks -->
- <integer translatable="false" name="config_wifi_framework_wifi_score_bad_rssi_threshold_5GHz">-82</integer>
- <integer translatable="false" name="config_wifi_framework_wifi_score_entry_rssi_threshold_5GHz">-82</integer>
+ <!-- Integer threshold for low network score, should be somewhat less than the entry threshhold -->
+ <integer translatable="false" name="config_wifi_framework_wifi_score_bad_rssi_threshold_5GHz">-80</integer>
+ <!-- Integer threshold, do not connect to APs with RSSI lower than the entry threshold -->
+ <integer translatable="false" name="config_wifi_framework_wifi_score_entry_rssi_threshold_5GHz">-77</integer>
<integer translatable="false" name="config_wifi_framework_wifi_score_low_rssi_threshold_5GHz">-70</integer>
<integer translatable="false" name="config_wifi_framework_wifi_score_good_rssi_threshold_5GHz">-57</integer>
- <integer translatable="false" name="config_wifi_framework_wifi_score_bad_rssi_threshold_24GHz">-85</integer>
- <integer translatable="false" name="config_wifi_framework_wifi_score_entry_rssi_threshold_24GHz">-85</integer>
+ <integer translatable="false" name="config_wifi_framework_wifi_score_bad_rssi_threshold_24GHz">-83</integer>
+ <integer translatable="false" name="config_wifi_framework_wifi_score_entry_rssi_threshold_24GHz">-80</integer>
<integer translatable="false" name="config_wifi_framework_wifi_score_low_rssi_threshold_24GHz">-73</integer>
<integer translatable="false" name="config_wifi_framework_wifi_score_good_rssi_threshold_24GHz">-60</integer>
<integer translatable="false" name="config_wifi_framework_wifi_score_bad_link_speed_24">6</integer>
diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml
index 99001e3..6a58b67 100644
--- a/core/res/res/values/symbols.xml
+++ b/core/res/res/values/symbols.xml
@@ -1339,7 +1339,6 @@
<java-symbol type="drawable" name="ic_text_dot" />
<java-symbol type="drawable" name="ic_print" />
<java-symbol type="drawable" name="ic_print_error" />
- <java-symbol type="drawable" name="ic_grayedout_printer" />
<java-symbol type="drawable" name="jog_dial_arrow_long_left_green" />
<java-symbol type="drawable" name="jog_dial_arrow_long_right_red" />
<java-symbol type="drawable" name="jog_dial_arrow_short_left_and_right" />
diff --git a/core/tests/coretests/src/android/provider/SettingsBackupTest.java b/core/tests/coretests/src/android/provider/SettingsBackupTest.java
index 7d48987..f91d149 100644
--- a/core/tests/coretests/src/android/provider/SettingsBackupTest.java
+++ b/core/tests/coretests/src/android/provider/SettingsBackupTest.java
@@ -124,6 +124,7 @@
Settings.Global.BATTERY_DISCHARGE_THRESHOLD,
Settings.Global.BATTERY_SAVER_DEVICE_SPECIFIC_CONSTANTS,
Settings.Global.BATTERY_STATS_CONSTANTS,
+ Settings.Global.BINDER_CALLS_STATS,
Settings.Global.BLE_SCAN_ALWAYS_AVAILABLE,
Settings.Global.BLE_SCAN_LOW_POWER_WINDOW_MS,
Settings.Global.BLE_SCAN_LOW_POWER_INTERVAL_MS,
@@ -596,13 +597,15 @@
Settings.Secure.SEARCH_THREAD_KEEPALIVE_SECONDS,
Settings.Secure.SEARCH_WEB_RESULTS_OVERRIDE_LIMIT,
Settings.Secure.SELECTED_INPUT_METHOD_SUBTYPE,
+ Settings.Secure.SELECTED_SPELL_CHECKER, // Intentionally removed in Q
+ Settings.Secure.SELECTED_SPELL_CHECKER_SUBTYPE, // Intentionally removed in Q
Settings.Secure.SETTINGS_CLASSNAME,
Settings.Secure.SHOW_NOTE_ABOUT_NOTIFICATION_HIDING, // candidate?
Settings.Secure.SHOW_ROTATION_SUGGESTIONS,
Settings.Secure.SKIP_FIRST_USE_HINTS, // candidate?
Settings.Secure.SLEEP_TIMEOUT,
Settings.Secure.SMS_DEFAULT_APPLICATION,
- Settings.Secure.THEME_MODE,
+ Settings.Secure.SPELL_CHECKER_ENABLED, // Intentionally removed in Q
Settings.Secure.TRUST_AGENTS_INITIALIZED,
Settings.Secure.TV_INPUT_CUSTOM_LABELS,
Settings.Secure.TV_INPUT_HIDDEN_INPUTS,
diff --git a/core/tests/coretests/src/android/text/TextUtilsTest.java b/core/tests/coretests/src/android/text/TextUtilsTest.java
index 870d6b2..72290bf 100644
--- a/core/tests/coretests/src/android/text/TextUtilsTest.java
+++ b/core/tests/coretests/src/android/text/TextUtilsTest.java
@@ -785,4 +785,11 @@
assertEquals(2, TextUtils.length(" "));
assertEquals(6, TextUtils.length("Hello!"));
}
+
+ @Test
+ public void testTrimToLengthWithEllipsis() {
+ assertEquals("ABC...", TextUtils.trimToLengthWithEllipsis("ABCDEF", 3));
+ assertEquals("ABC", TextUtils.trimToLengthWithEllipsis("ABC", 3));
+ assertEquals("", TextUtils.trimToLengthWithEllipsis("", 3));
+ }
}
diff --git a/core/tests/coretests/src/android/view/KeyEventTest.java b/core/tests/coretests/src/android/view/KeyEventTest.java
index aabf816..b9d95e5 100644
--- a/core/tests/coretests/src/android/view/KeyEventTest.java
+++ b/core/tests/coretests/src/android/view/KeyEventTest.java
@@ -16,6 +16,8 @@
package android.view;
+import static android.view.Display.INVALID_DISPLAY;
+
import static org.junit.Assert.assertEquals;
import android.support.test.filters.SmallTest;
@@ -28,12 +30,71 @@
@RunWith(AndroidJUnit4.class)
public class KeyEventTest {
+ private static final int DOWN_TIME = 50;
+ private static final long EVENT_TIME = 100;
+ private static final int ACTION = KeyEvent.ACTION_DOWN;
+ private static final int KEYCODE = KeyEvent.KEYCODE_0;
+ private static final int REPEAT = 0;
+ private static final int METASTATE = 0;
+ private static final int DEVICE_ID = 0;
+ private static final int SCAN_CODE = 0;
+ private static final int FLAGS = 0;
+ private static final int SOURCE = InputDevice.SOURCE_KEYBOARD;
+ private static final String CHARACTERS = null;
+
@Test
public void testObtain() {
- KeyEvent keyEvent = KeyEvent.obtain(0, 0, KeyEvent.ACTION_DOWN, KeyEvent.KEYCODE_0,
- 0, 0, 0, 0, 0, InputDevice.SOURCE_KEYBOARD, null);
- assertEquals(KeyEvent.ACTION_DOWN, keyEvent.getAction());
- assertEquals(KeyEvent.KEYCODE_0, keyEvent.getKeyCode());
- assertEquals(InputDevice.SOURCE_KEYBOARD, keyEvent.getSource());
+ KeyEvent keyEvent = KeyEvent.obtain(DOWN_TIME, EVENT_TIME, ACTION, KEYCODE, REPEAT,
+ METASTATE, DEVICE_ID, SCAN_CODE, FLAGS, SOURCE, CHARACTERS);
+ assertEquals(DOWN_TIME, keyEvent.getDownTime());
+ assertEquals(EVENT_TIME, keyEvent.getEventTime());
+ assertEquals(ACTION, keyEvent.getAction());
+ assertEquals(KEYCODE, keyEvent.getKeyCode());
+ assertEquals(REPEAT, keyEvent.getRepeatCount());
+ assertEquals(METASTATE, keyEvent.getMetaState());
+ assertEquals(DEVICE_ID, keyEvent.getDeviceId());
+ assertEquals(SCAN_CODE, keyEvent.getScanCode());
+ assertEquals(FLAGS, keyEvent.getFlags());
+ assertEquals(SOURCE, keyEvent.getSource());
+ assertEquals(INVALID_DISPLAY, keyEvent.getDisplayId());
+ assertEquals(CHARACTERS, keyEvent.getCharacters());
+ }
+
+ @Test
+ public void testObtainFromKeyEvent() {
+ KeyEvent keyEvent = KeyEvent.obtain(DOWN_TIME, EVENT_TIME, ACTION, KEYCODE, REPEAT,
+ METASTATE, DEVICE_ID, SCAN_CODE, FLAGS, SOURCE, CHARACTERS);
+ KeyEvent keyEvent2 = KeyEvent.obtain(keyEvent);
+ assertEquals(keyEvent.getDownTime(), keyEvent2.getDownTime());
+ assertEquals(keyEvent.getEventTime(), keyEvent2.getEventTime());
+ assertEquals(keyEvent.getAction(), keyEvent2.getAction());
+ assertEquals(keyEvent.getKeyCode(), keyEvent2.getKeyCode());
+ assertEquals(keyEvent.getRepeatCount(), keyEvent2.getRepeatCount());
+ assertEquals(keyEvent.getMetaState(), keyEvent2.getMetaState());
+ assertEquals(keyEvent.getDeviceId(), keyEvent2.getDeviceId());
+ assertEquals(keyEvent.getScanCode(), keyEvent2.getScanCode());
+ assertEquals(keyEvent.getFlags(), keyEvent2.getFlags());
+ assertEquals(keyEvent.getSource(), keyEvent2.getSource());
+ assertEquals(keyEvent.getDisplayId(), keyEvent2.getDisplayId());
+ assertEquals(keyEvent.getCharacters(), keyEvent2.getCharacters());
+ }
+
+ @Test
+ public void testObtainWithDisplayId() {
+ final int displayId = 5;
+ KeyEvent keyEvent = KeyEvent.obtain(DOWN_TIME, EVENT_TIME, ACTION, KEYCODE, REPEAT,
+ METASTATE, DEVICE_ID, SCAN_CODE, FLAGS, SOURCE, displayId, CHARACTERS);
+ assertEquals(DOWN_TIME, keyEvent.getDownTime());
+ assertEquals(EVENT_TIME, keyEvent.getEventTime());
+ assertEquals(ACTION, keyEvent.getAction());
+ assertEquals(KEYCODE, keyEvent.getKeyCode());
+ assertEquals(REPEAT, keyEvent.getRepeatCount());
+ assertEquals(METASTATE, keyEvent.getMetaState());
+ assertEquals(DEVICE_ID, keyEvent.getDeviceId());
+ assertEquals(SCAN_CODE, keyEvent.getScanCode());
+ assertEquals(FLAGS, keyEvent.getFlags());
+ assertEquals(SOURCE, keyEvent.getSource());
+ assertEquals(displayId, keyEvent.getDisplayId());
+ assertEquals(CHARACTERS, keyEvent.getCharacters());
}
}
diff --git a/core/tests/coretests/src/com/android/internal/os/BinderCallsStatsTest.java b/core/tests/coretests/src/com/android/internal/os/BinderCallsStatsTest.java
index 18263ab..3d34880 100644
--- a/core/tests/coretests/src/com/android/internal/os/BinderCallsStatsTest.java
+++ b/core/tests/coretests/src/com/android/internal/os/BinderCallsStatsTest.java
@@ -20,14 +20,19 @@
import android.platform.test.annotations.Presubmit;
import android.support.test.filters.SmallTest;
import android.support.test.runner.AndroidJUnit4;
+import android.util.ArrayMap;
import android.util.SparseArray;
import org.junit.Assert;
import org.junit.Test;
import org.junit.runner.RunWith;
+import java.io.PrintWriter;
+import java.io.StringWriter;
import java.util.Arrays;
+import java.util.HashMap;
import java.util.List;
+import java.util.Map;
import static org.junit.Assert.assertEquals;
@@ -41,7 +46,9 @@
@Test
public void testDetailedOff() {
- TestBinderCallsStats bcs = new TestBinderCallsStats(false);
+ TestBinderCallsStats bcs = new TestBinderCallsStats();
+ bcs.setDetailedTracking(false);
+
Binder binder = new Binder();
BinderCallsStats.CallSession callSession = bcs.callStarted(binder, 1);
bcs.time += 10;
@@ -93,7 +100,9 @@
@Test
public void testDetailedOn() {
- TestBinderCallsStats bcs = new TestBinderCallsStats(true);
+ TestBinderCallsStats bcs = new TestBinderCallsStats();
+ bcs.setDetailedTracking(true);
+
Binder binder = new Binder();
BinderCallsStats.CallSession callSession = bcs.callStarted(binder, 1);
bcs.time += 10;
@@ -140,8 +149,106 @@
}
@Test
+ public void testDisabled() {
+ TestBinderCallsStats bcs = new TestBinderCallsStats();
+ bcs.setEnabled(false);
+
+ Binder binder = new Binder();
+ BinderCallsStats.CallSession callSession = bcs.callStarted(binder, 1);
+ bcs.time += 10;
+ bcs.callEnded(callSession, REQUEST_SIZE, REPLY_SIZE);
+
+ SparseArray<BinderCallsStats.UidEntry> uidEntries = bcs.getUidEntries();
+ assertEquals(0, uidEntries.size());
+ }
+
+ @Test
+ public void testDisableInBetweenCall() {
+ TestBinderCallsStats bcs = new TestBinderCallsStats();
+ bcs.setEnabled(true);
+
+ Binder binder = new Binder();
+ BinderCallsStats.CallSession callSession = bcs.callStarted(binder, 1);
+ bcs.time += 10;
+ bcs.setEnabled(false);
+ bcs.callEnded(callSession, REQUEST_SIZE, REPLY_SIZE);
+
+ SparseArray<BinderCallsStats.UidEntry> uidEntries = bcs.getUidEntries();
+ assertEquals(0, uidEntries.size());
+ }
+
+ @Test
+ public void testEnableInBetweenCall() {
+ TestBinderCallsStats bcs = new TestBinderCallsStats();
+ bcs.setEnabled(false);
+
+ Binder binder = new Binder();
+ BinderCallsStats.CallSession callSession = bcs.callStarted(binder, 1);
+ bcs.time += 10;
+ bcs.setEnabled(true);
+ bcs.callEnded(callSession, REQUEST_SIZE, REPLY_SIZE);
+
+ SparseArray<BinderCallsStats.UidEntry> uidEntries = bcs.getUidEntries();
+ assertEquals(0, uidEntries.size());
+ }
+
+ @Test
+ public void testSampling() {
+ TestBinderCallsStats bcs = new TestBinderCallsStats();
+ bcs.setDetailedTracking(false);
+ bcs.setSamplingInterval(2);
+
+ Binder binder = new Binder();
+ BinderCallsStats.CallSession callSession = bcs.callStarted(binder, 1);
+ bcs.time += 10;
+ bcs.callEnded(callSession, REQUEST_SIZE, REPLY_SIZE);
+
+ callSession = bcs.callStarted(binder, 1);
+ bcs.time += 1000; // shoud be ignored.
+ bcs.callEnded(callSession, REQUEST_SIZE, REPLY_SIZE);
+
+ callSession = bcs.callStarted(binder, 1);
+ bcs.time += 50;
+ bcs.callEnded(callSession, REQUEST_SIZE, REPLY_SIZE);
+
+ SparseArray<BinderCallsStats.UidEntry> uidEntries = bcs.getUidEntries();
+ assertEquals(1, uidEntries.size());
+ BinderCallsStats.UidEntry uidEntry = uidEntries.get(TEST_UID);
+ Assert.assertNotNull(uidEntry);
+ assertEquals(3, uidEntry.callCount);
+ assertEquals(70, uidEntry.cpuTimeMicros);
+ assertEquals("Detailed tracking off - no entries should be returned",
+ 0, uidEntry.getCallStatsList().size());
+
+ BinderCallsStats.UidEntry sampledEntries = bcs.getSampledEntries();
+ List<BinderCallsStats.CallStat> sampledCallStatsList = sampledEntries.getCallStatsList();
+ assertEquals(1, sampledCallStatsList.size());
+ }
+
+ @Test
+ public void testTransactionCodeResolved() {
+ TestBinderCallsStats bcs = new TestBinderCallsStats();
+ bcs.setDetailedTracking(true);
+ Binder binder = new Binder() {
+ @Override
+ public String getTransactionName(int code) {
+ return "resolved";
+ }
+ };
+ BinderCallsStats.CallSession callSession = bcs.callStarted(binder, 1);
+ bcs.time += 10;
+ bcs.callEnded(callSession, REQUEST_SIZE, REPLY_SIZE);
+
+ List<BinderCallsStats.CallStat> callStatsList =
+ bcs.getUidEntries().get(TEST_UID).getCallStatsList();
+ assertEquals(1, callStatsList.get(0).msg);
+ assertEquals("resolved", callStatsList.get(0).methodName);
+ }
+
+ @Test
public void testParcelSize() {
- TestBinderCallsStats bcs = new TestBinderCallsStats(true);
+ TestBinderCallsStats bcs = new TestBinderCallsStats();
+ bcs.setDetailedTracking(true);
Binder binder = new Binder();
BinderCallsStats.CallSession callSession = bcs.callStarted(binder, 1);
bcs.time += 10;
@@ -156,7 +263,8 @@
@Test
public void testMaxCpu() {
- TestBinderCallsStats bcs = new TestBinderCallsStats(true);
+ TestBinderCallsStats bcs = new TestBinderCallsStats();
+ bcs.setDetailedTracking(true);
Binder binder = new Binder();
BinderCallsStats.CallSession callSession = bcs.callStarted(binder, 1);
bcs.time += 50;
@@ -174,7 +282,8 @@
@Test
public void testMaxLatency() {
- TestBinderCallsStats bcs = new TestBinderCallsStats(true);
+ TestBinderCallsStats bcs = new TestBinderCallsStats();
+ bcs.setDetailedTracking(true);
Binder binder = new Binder();
BinderCallsStats.CallSession callSession = bcs.callStarted(binder, 1);
bcs.elapsedTime += 5;
@@ -198,13 +307,48 @@
assertEquals(Arrays.asList(4, 3, 2), highestValues);
}
+ @Test
+ public void testExceptionCount() {
+ TestBinderCallsStats bcs = new TestBinderCallsStats();
+ bcs.setDetailedTracking(true);
+ Binder binder = new Binder();
+ BinderCallsStats.CallSession callSession = bcs.callStarted(binder, 1);
+ bcs.callThrewException(callSession, new IllegalStateException());
+ bcs.callEnded(callSession, REQUEST_SIZE, REPLY_SIZE);
+
+ callSession = bcs.callStarted(binder, 1);
+ bcs.callThrewException(callSession, new IllegalStateException());
+ bcs.callEnded(callSession, REQUEST_SIZE, REPLY_SIZE);
+
+ callSession = bcs.callStarted(binder, 1);
+ bcs.callThrewException(callSession, new RuntimeException());
+ bcs.callEnded(callSession, REQUEST_SIZE, REPLY_SIZE);
+
+ ArrayMap<String, Integer> expected = new ArrayMap<>();
+ expected.put("java.lang.IllegalStateException", 2);
+ expected.put("java.lang.RuntimeException", 1);
+ assertEquals(expected, bcs.getExceptionCounts());
+ }
+
+ @Test
+ public void testDumpDoesNotThrowException() {
+ TestBinderCallsStats bcs = new TestBinderCallsStats();
+ bcs.setDetailedTracking(true);
+ Binder binder = new Binder();
+ BinderCallsStats.CallSession callSession = bcs.callStarted(binder, 1);
+ bcs.callThrewException(callSession, new IllegalStateException());
+ bcs.callEnded(callSession, REQUEST_SIZE, REPLY_SIZE);
+
+ PrintWriter pw = new PrintWriter(new StringWriter());
+ bcs.dump(pw, new HashMap<>(), true);
+ }
+
static class TestBinderCallsStats extends BinderCallsStats {
int callingUid = TEST_UID;
long time = 1234;
long elapsedTime = 0;
- TestBinderCallsStats(boolean detailedTracking) {
- super(detailedTracking);
+ TestBinderCallsStats() {
}
@Override
diff --git a/core/tests/coretests/src/com/android/internal/util/DumpUtilsTest.java b/core/tests/coretests/src/com/android/internal/util/DumpUtilsTest.java
index 45b19bc..a44b860 100644
--- a/core/tests/coretests/src/com/android/internal/util/DumpUtilsTest.java
+++ b/core/tests/coretests/src/com/android/internal/util/DumpUtilsTest.java
@@ -15,8 +15,11 @@
*/
package com.android.internal.util;
+import static com.android.internal.util.DumpUtils.CRITICAL_SECTION_COMPONENTS;
import static com.android.internal.util.DumpUtils.filterRecord;
import static com.android.internal.util.DumpUtils.isNonPlatformPackage;
+import static com.android.internal.util.DumpUtils.isPlatformCriticalPackage;
+import static com.android.internal.util.DumpUtils.isPlatformNonCriticalPackage;
import static com.android.internal.util.DumpUtils.isPlatformPackage;
import android.content.ComponentName;
@@ -25,7 +28,7 @@
/**
* Run with:
- atest /android/pi-dev/frameworks/base/core/tests/coretests/src/com/android/internal/util/DumpTest.java
+ atest FrameworksCoreTests:DumpUtilsTest
*/
public class DumpUtilsTest extends TestCase {
@@ -89,6 +92,32 @@
assertTrue(isNonPlatformPackage(wcn("com.google.def/abc")));
}
+ public void testIsPlatformCriticalPackage() {
+ for (final ComponentName componentName : CRITICAL_SECTION_COMPONENTS) {
+ assertTrue(isPlatformCriticalPackage(() -> componentName));
+ assertTrue(isPlatformPackage(componentName));
+ }
+ assertFalse(isPlatformCriticalPackage(wcn("com.google.p/abc")));
+ assertFalse(isPlatformCriticalPackage(wcn("com.android.def/abc")));
+ assertFalse(isPlatformCriticalPackage(wcn("com.android.abc")));
+ assertFalse(isPlatformCriticalPackage(wcn("com.android")));
+ assertFalse(isPlatformCriticalPackage(wcn(null)));
+ assertFalse(isPlatformCriticalPackage(null));
+ }
+
+ public void testIsPlatformNonCriticalPackage() {
+ for (final ComponentName componentName : CRITICAL_SECTION_COMPONENTS) {
+ assertFalse(isPlatformNonCriticalPackage(() -> componentName));
+ }
+ assertTrue(isPlatformNonCriticalPackage(wcn("android/abc")));
+ assertTrue(isPlatformNonCriticalPackage(wcn("android.abc/abc")));
+ assertTrue(isPlatformNonCriticalPackage(wcn("com.android.def/abc")));
+
+ assertFalse(isPlatformNonCriticalPackage(wcn("com.google.def/abc")));
+ assertFalse(isPlatformNonCriticalPackage(wcn(null)));
+ assertFalse(isPlatformNonCriticalPackage(null));
+ }
+
public void testFilterRecord() {
assertFalse(filterRecord(null).test(wcn("com.google.p/abc")));
assertFalse(filterRecord(null).test(wcn("com.android.p/abc")));
@@ -105,6 +134,19 @@
assertFalse(filterRecord("all-non-platform").test(wcn("com.android.p/abc")));
assertFalse(filterRecord("all-non-platform").test(wcn(null)));
+ for (final ComponentName componentName : CRITICAL_SECTION_COMPONENTS) {
+ assertTrue(filterRecord("all-platform-critical").test((() -> componentName)));
+ assertFalse(filterRecord("all-platform-non-critical").test((() -> componentName)));
+ assertTrue(filterRecord("all-platform").test((() -> componentName)));
+ }
+ assertFalse(filterRecord("all-platform-critical").test(wcn("com.google.p/abc")));
+ assertFalse(filterRecord("all-platform-critical").test(wcn("com.android.p/abc")));
+ assertFalse(filterRecord("all-platform-critical").test(wcn(null)));
+
+ assertTrue(filterRecord("all-platform-non-critical").test(wcn("com.android.p/abc")));
+ assertFalse(filterRecord("all-platform-non-critical").test(wcn("com.google.p/abc")));
+ assertFalse(filterRecord("all-platform-non-critical").test(wcn(null)));
+
// Partial string match.
assertTrue(filterRecord("abc").test(wcn("com.google.p/.abc")));
assertFalse(filterRecord("abc").test(wcn("com.google.p/.def")));
diff --git a/keystore/java/android/security/keystore/KeyGenParameterSpec.java b/keystore/java/android/security/keystore/KeyGenParameterSpec.java
index 452024c..89d370f 100644
--- a/keystore/java/android/security/keystore/KeyGenParameterSpec.java
+++ b/keystore/java/android/security/keystore/KeyGenParameterSpec.java
@@ -268,6 +268,11 @@
private final boolean mIsStrongBoxBacked;
private final boolean mUserConfirmationRequired;
private final boolean mUnlockedDeviceRequired;
+ /*
+ * ***NOTE***: All new fields MUST also be added to the following:
+ * ParcelableKeyGenParameterSpec class.
+ * The KeyGenParameterSpec.Builder constructor that takes a KeyGenParameterSpec
+ */
/**
* @hide should be built with Builder
@@ -791,6 +796,9 @@
mUniqueIdIncluded = sourceSpec.isUniqueIdIncluded();
mUserAuthenticationValidWhileOnBody = sourceSpec.isUserAuthenticationValidWhileOnBody();
mInvalidatedByBiometricEnrollment = sourceSpec.isInvalidatedByBiometricEnrollment();
+ mIsStrongBoxBacked = sourceSpec.isStrongBoxBacked();
+ mUserConfirmationRequired = sourceSpec.isUserConfirmationRequired();
+ mUnlockedDeviceRequired = sourceSpec.isUnlockedDeviceRequired();
}
/**
diff --git a/keystore/java/android/security/keystore/ParcelableKeyGenParameterSpec.java b/keystore/java/android/security/keystore/ParcelableKeyGenParameterSpec.java
index 911bbf8..8231dc9 100644
--- a/keystore/java/android/security/keystore/ParcelableKeyGenParameterSpec.java
+++ b/keystore/java/android/security/keystore/ParcelableKeyGenParameterSpec.java
@@ -97,11 +97,14 @@
out.writeBoolean(mSpec.isRandomizedEncryptionRequired());
out.writeBoolean(mSpec.isUserAuthenticationRequired());
out.writeInt(mSpec.getUserAuthenticationValidityDurationSeconds());
+ out.writeBoolean(mSpec.isUserPresenceRequired());
out.writeByteArray(mSpec.getAttestationChallenge());
out.writeBoolean(mSpec.isUniqueIdIncluded());
out.writeBoolean(mSpec.isUserAuthenticationValidWhileOnBody());
out.writeBoolean(mSpec.isInvalidatedByBiometricEnrollment());
- out.writeBoolean(mSpec.isUserPresenceRequired());
+ out.writeBoolean(mSpec.isStrongBoxBacked());
+ out.writeBoolean(mSpec.isUserConfirmationRequired());
+ out.writeBoolean(mSpec.isUnlockedDeviceRequired());
}
private static Date readDateOrNull(Parcel in) {
@@ -114,19 +117,12 @@
}
private ParcelableKeyGenParameterSpec(Parcel in) {
- String keystoreAlias = in.readString();
- int purposes = in.readInt();
- KeyGenParameterSpec.Builder builder = new KeyGenParameterSpec.Builder(
- keystoreAlias, purposes);
- builder.setUid(in.readInt());
- // KeySize is -1 by default, if the KeyGenParameterSpec previously parcelled had the default
- // value, do not set it as this will cause setKeySize to throw.
- int keySize = in.readInt();
- if (keySize >= 0) {
- builder.setKeySize(keySize);
- }
+ final String keystoreAlias = in.readString();
+ final int purposes = in.readInt();
+ final int uid = in.readInt();
+ final int keySize = in.readInt();
- int keySpecType = in.readInt();
+ final int keySpecType = in.readInt();
AlgorithmParameterSpec algorithmSpec = null;
if (keySpecType == ALGORITHM_PARAMETER_SPEC_NONE) {
algorithmSpec = null;
@@ -141,32 +137,60 @@
throw new IllegalArgumentException(
String.format("Unknown algorithm parameter spec: %d", keySpecType));
}
- if (algorithmSpec != null) {
- builder.setAlgorithmParameterSpec(algorithmSpec);
- }
- builder.setCertificateSubject(new X500Principal(in.createByteArray()));
- builder.setCertificateSerialNumber(new BigInteger(in.createByteArray()));
- builder.setCertificateNotBefore(new Date(in.readLong()));
- builder.setCertificateNotAfter(new Date(in.readLong()));
- builder.setKeyValidityStart(readDateOrNull(in));
- builder.setKeyValidityForOriginationEnd(readDateOrNull(in));
- builder.setKeyValidityForConsumptionEnd(readDateOrNull(in));
- String[] digests = in.createStringArray();
- if (digests != null) {
- builder.setDigests(digests);
- }
- builder.setEncryptionPaddings(in.createStringArray());
- builder.setSignaturePaddings(in.createStringArray());
- builder.setBlockModes(in.createStringArray());
- builder.setRandomizedEncryptionRequired(in.readBoolean());
- builder.setUserAuthenticationRequired(in.readBoolean());
- builder.setUserAuthenticationValidityDurationSeconds(in.readInt());
- builder.setAttestationChallenge(in.createByteArray());
- builder.setUniqueIdIncluded(in.readBoolean());
- builder.setUserAuthenticationValidWhileOnBody(in.readBoolean());
- builder.setInvalidatedByBiometricEnrollment(in.readBoolean());
- builder.setUserPresenceRequired(in.readBoolean());
- mSpec = builder.build();
+
+ final X500Principal certificateSubject = new X500Principal(in.createByteArray());
+ final BigInteger certificateSerialNumber = new BigInteger(in.createByteArray());
+ final Date certificateNotBefore = new Date(in.readLong());
+ final Date certificateNotAfter = new Date(in.readLong());
+ final Date keyValidityStartDate = readDateOrNull(in);
+ final Date keyValidityForOriginationEnd = readDateOrNull(in);
+ final Date keyValidityForConsumptionEnd = readDateOrNull(in);
+ final String[] digests = in.createStringArray();
+ final String[] encryptionPaddings = in.createStringArray();
+ final String[] signaturePaddings = in.createStringArray();
+ final String[] blockModes = in.createStringArray();
+ final boolean randomizedEncryptionRequired = in.readBoolean();
+ final boolean userAuthenticationRequired = in.readBoolean();
+ final int userAuthenticationValidityDurationSeconds = in.readInt();
+ final boolean userPresenceRequired = in.readBoolean();
+ final byte[] attestationChallenge = in.createByteArray();
+ final boolean uniqueIdIncluded = in.readBoolean();
+ final boolean userAuthenticationValidWhileOnBody = in.readBoolean();
+ final boolean invalidatedByBiometricEnrollment = in.readBoolean();
+ final boolean isStrongBoxBacked = in.readBoolean();
+ final boolean userConfirmationRequired = in.readBoolean();
+ final boolean unlockedDeviceRequired = in.readBoolean();
+ // The KeyGenParameterSpec is intentionally not constructed using a Builder here:
+ // The intention is for this class to break if new parameters are added to the
+ // KeyGenParameterSpec constructor (whereas using a builder would silently drop them).
+ mSpec = new KeyGenParameterSpec(
+ keystoreAlias,
+ uid,
+ keySize,
+ algorithmSpec,
+ certificateSubject,
+ certificateSerialNumber,
+ certificateNotBefore,
+ certificateNotAfter,
+ keyValidityStartDate,
+ keyValidityForOriginationEnd,
+ keyValidityForConsumptionEnd,
+ purposes,
+ digests,
+ encryptionPaddings,
+ signaturePaddings,
+ blockModes,
+ randomizedEncryptionRequired,
+ userAuthenticationRequired,
+ userAuthenticationValidityDurationSeconds,
+ userPresenceRequired,
+ attestationChallenge,
+ uniqueIdIncluded,
+ userAuthenticationValidWhileOnBody,
+ invalidatedByBiometricEnrollment,
+ isStrongBoxBacked,
+ userConfirmationRequired,
+ unlockedDeviceRequired);
}
public static final Creator<ParcelableKeyGenParameterSpec> CREATOR = new Creator<ParcelableKeyGenParameterSpec>() {
diff --git a/keystore/tests/src/android/security/ParcelableKeyGenParameterSpecTest.java b/keystore/tests/src/android/security/ParcelableKeyGenParameterSpecTest.java
index 254b6be..32f8ec4 100644
--- a/keystore/tests/src/android/security/ParcelableKeyGenParameterSpecTest.java
+++ b/keystore/tests/src/android/security/ParcelableKeyGenParameterSpecTest.java
@@ -77,6 +77,9 @@
.setUniqueIdIncluded(true)
.setUserAuthenticationValidWhileOnBody(true)
.setInvalidatedByBiometricEnrollment(true)
+ .setIsStrongBoxBacked(true)
+ .setUserConfirmationRequired(true)
+ .setUnlockedDeviceRequired(true)
.build();
}
@@ -105,6 +108,9 @@
assertThat(spec.isUniqueIdIncluded(), is(true));
assertThat(spec.isUserAuthenticationValidWhileOnBody(), is(true));
assertThat(spec.isInvalidatedByBiometricEnrollment(), is(true));
+ assertThat(spec.isStrongBoxBacked(), is(true));
+ assertThat(spec.isUserConfirmationRequired(), is(true));
+ assertThat(spec.isUnlockedDeviceRequired(), is(true));
}
private Parcel parcelForReading(ParcelableKeyGenParameterSpec spec) {
diff --git a/libs/hwui/Android.bp b/libs/hwui/Android.bp
index 0db7799..111094b 100644
--- a/libs/hwui/Android.bp
+++ b/libs/hwui/Android.bp
@@ -198,6 +198,7 @@
"AnimatorManager.cpp",
"Caches.cpp",
"CanvasState.cpp",
+ "CanvasTransform.cpp",
"ClipArea.cpp",
"DamageAccumulator.cpp",
"DeferredLayerUpdater.cpp",
diff --git a/libs/hwui/CanvasTransform.cpp b/libs/hwui/CanvasTransform.cpp
new file mode 100644
index 0000000..bac7a4d
--- /dev/null
+++ b/libs/hwui/CanvasTransform.cpp
@@ -0,0 +1,113 @@
+/*
+ * Copyright (C) 2018 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 "CanvasTransform.h"
+#include "Properties.h"
+
+#include <SkColorFilter.h>
+#include <SkPaint.h>
+#include <log/log.h>
+
+namespace android::uirenderer {
+
+static SkColor makeLight(SkColor color) {
+ SkScalar hsv[3];
+ SkColorToHSV(color, hsv);
+ if (hsv[1] > .2f) return color;
+ // hsv[1] *= .85f;
+ // hsv[2] = std::min(1.0f, std::max(hsv[2], 1 - hsv[2]) * 1.3f);
+ hsv[2] = std::max(hsv[2], 1.1f - hsv[2]);
+ return SkHSVToColor(SkColorGetA(color), hsv);
+}
+
+static SkColor makeDark(SkColor color) {
+ SkScalar hsv[3];
+ SkColorToHSV(color, hsv);
+ if (hsv[1] > .2f) return color;
+ // hsv[1] *= .85f;
+ // hsv[2] = std::max(0.0f, std::min(hsv[2], 1 - hsv[2]) * .7f);
+ hsv[2] = std::min(hsv[2], 1.1f - hsv[2]);
+ return SkHSVToColor(SkColorGetA(color), hsv);
+}
+
+static SkColor transformColor(ColorTransform transform, SkColor color) {
+ switch (transform) {
+ case ColorTransform::Light:
+ return makeLight(color);
+ case ColorTransform::Dark:
+ return makeDark(color);
+ default:
+ return color;
+ }
+}
+
+static void applyColorTransform(ColorTransform transform, SkPaint& paint) {
+ if (transform == ColorTransform::None) return;
+
+ SkColor newColor = transformColor(transform, paint.getColor());
+ paint.setColor(newColor);
+
+ if (paint.getColorFilter()) {
+ SkBlendMode mode;
+ SkColor color;
+ // TODO: LRU this or something to avoid spamming new color mode filters
+ if (paint.getColorFilter()->asColorMode(&color, &mode)) {
+ color = transformColor(transform, color);
+ paint.setColorFilter(SkColorFilter::MakeModeFilter(color, mode));
+ }
+ }
+}
+
+class ColorFilterCanvas : public SkPaintFilterCanvas {
+public:
+ ColorFilterCanvas(ColorTransform transform, SkCanvas* canvas)
+ : SkPaintFilterCanvas(canvas), mTransform(transform) {}
+
+ bool onFilter(SkTCopyOnFirstWrite<SkPaint>* paint, Type type) const override {
+ if (*paint) {
+ applyColorTransform(mTransform, *(paint->writable()));
+ }
+ return true;
+ }
+
+private:
+ ColorTransform mTransform;
+};
+
+std::unique_ptr<SkCanvas> makeTransformCanvas(SkCanvas* inCanvas, ColorTransform transform) {
+ switch (transform) {
+ case ColorTransform::Light:
+ return std::make_unique<ColorFilterCanvas>(ColorTransform::Light, inCanvas);
+ case ColorTransform::Dark:
+ return std::make_unique<ColorFilterCanvas>(ColorTransform::Dark, inCanvas);
+ default:
+ return nullptr;
+ }
+}
+
+std::unique_ptr<SkCanvas> makeTransformCanvas(SkCanvas* inCanvas, UsageHint usageHint) {
+ if (Properties::forceDarkMode) {
+ switch (usageHint) {
+ case UsageHint::Unknown:
+ return makeTransformCanvas(inCanvas, ColorTransform::Light);
+ case UsageHint::Background:
+ return makeTransformCanvas(inCanvas, ColorTransform::Dark);
+ }
+ }
+ return nullptr;
+}
+
+}; // namespace android::uirenderer
\ No newline at end of file
diff --git a/libs/hwui/CanvasTransform.h b/libs/hwui/CanvasTransform.h
new file mode 100644
index 0000000..f71fdfa
--- /dev/null
+++ b/libs/hwui/CanvasTransform.h
@@ -0,0 +1,40 @@
+/*
+ * Copyright (C) 2018 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 <SkCanvas.h>
+#include <SkPaintFilterCanvas.h>
+
+#include <memory>
+
+namespace android::uirenderer {
+
+enum class UsageHint {
+ Unknown = 0,
+ Background = 1,
+};
+
+enum class ColorTransform {
+ None,
+ Light,
+ Dark,
+};
+
+std::unique_ptr<SkCanvas> makeTransformCanvas(SkCanvas* inCanvas, ColorTransform transform);
+std::unique_ptr<SkCanvas> makeTransformCanvas(SkCanvas* inCanvas, UsageHint usageHint);
+
+} // namespace android::uirenderer;
\ No newline at end of file
diff --git a/libs/hwui/Properties.cpp b/libs/hwui/Properties.cpp
index 0338a3a..17bec19 100644
--- a/libs/hwui/Properties.cpp
+++ b/libs/hwui/Properties.cpp
@@ -60,6 +60,7 @@
bool Properties::filterOutTestOverhead = false;
bool Properties::disableVsync = false;
bool Properties::skpCaptureEnabled = false;
+bool Properties::forceDarkMode = false;
bool Properties::enableRTAnimations = true;
bool Properties::runningInEmulator = false;
@@ -146,6 +147,8 @@
runningInEmulator = property_get_bool(PROPERTY_QEMU_KERNEL, false);
+ forceDarkMode = property_get_bool(PROPERTY_FORCE_DARK, false);
+
return (prevDebugLayersUpdates != debugLayersUpdates) || (prevDebugOverdraw != debugOverdraw) ||
(prevDebugStencilClip != debugStencilClip);
}
diff --git a/libs/hwui/Properties.h b/libs/hwui/Properties.h
index d640c74..ea017a7 100644
--- a/libs/hwui/Properties.h
+++ b/libs/hwui/Properties.h
@@ -190,6 +190,8 @@
*/
#define PROPERTY_QEMU_KERNEL "ro.kernel.qemu"
+#define PROPERTY_FORCE_DARK "debug.hwui.force_dark"
+
///////////////////////////////////////////////////////////////////////////////
// Misc
///////////////////////////////////////////////////////////////////////////////
@@ -263,6 +265,7 @@
static bool disableVsync;
static bool skpCaptureEnabled;
+ static bool forceDarkMode;
// For experimentation b/68769804
ANDROID_API static bool enableRTAnimations;
diff --git a/libs/hwui/RenderNode.h b/libs/hwui/RenderNode.h
index dc962f3..8393288 100644
--- a/libs/hwui/RenderNode.h
+++ b/libs/hwui/RenderNode.h
@@ -28,6 +28,7 @@
#include <androidfw/ResourceTypes.h>
#include "AnimatorManager.h"
+#include "CanvasTransform.h"
#include "Debug.h"
#include "DisplayList.h"
#include "Matrix.h"
@@ -208,6 +209,14 @@
void output(std::ostream& output, uint32_t level);
+ void setUsageHint(UsageHint usageHint) {
+ mUsageHint = usageHint;
+ }
+
+ UsageHint usageHint() const {
+ return mUsageHint;
+ }
+
private:
void computeOrderingImpl(RenderNodeOp* opState,
std::vector<RenderNodeOp*>* compositedChildrenOfProjectionSurface,
@@ -263,6 +272,8 @@
sp<PositionListener> mPositionListener;
+ UsageHint mUsageHint = UsageHint::Unknown;
+
// METHODS & FIELDS ONLY USED BY THE SKIA RENDERER
public:
/**
diff --git a/libs/hwui/pipeline/skia/SkiaRecordingCanvas.cpp b/libs/hwui/pipeline/skia/SkiaRecordingCanvas.cpp
index f0da660..441fa11 100644
--- a/libs/hwui/pipeline/skia/SkiaRecordingCanvas.cpp
+++ b/libs/hwui/pipeline/skia/SkiaRecordingCanvas.cpp
@@ -17,6 +17,7 @@
#include "SkiaRecordingCanvas.h"
#include <SkImagePriv.h>
+#include "CanvasTransform.h"
#include "Layer.h"
#include "LayerDrawable.h"
#include "NinePatchUtils.h"
@@ -44,13 +45,21 @@
}
mDisplayList->attachRecorder(&mRecorder, SkIRect::MakeWH(width, height));
- SkiaCanvas::reset(&mRecorder);
+ SkCanvas* canvas = &mRecorder;
+ if (renderNode) {
+ mWrappedCanvas = makeTransformCanvas(&mRecorder, renderNode->usageHint());
+ if (mWrappedCanvas) {
+ canvas = mWrappedCanvas.get();
+ }
+ }
+ SkiaCanvas::reset(canvas);
}
uirenderer::DisplayList* SkiaRecordingCanvas::finishRecording() {
// close any existing chunks if necessary
insertReorderBarrier(false);
mRecorder.restoreToCount(1);
+ mWrappedCanvas = nullptr;
return mDisplayList.release();
}
diff --git a/libs/hwui/pipeline/skia/SkiaRecordingCanvas.h b/libs/hwui/pipeline/skia/SkiaRecordingCanvas.h
index 93807a5..b69acbf 100644
--- a/libs/hwui/pipeline/skia/SkiaRecordingCanvas.h
+++ b/libs/hwui/pipeline/skia/SkiaRecordingCanvas.h
@@ -78,6 +78,7 @@
private:
SkLiteRecorder mRecorder;
std::unique_ptr<SkiaDisplayList> mDisplayList;
+ std::unique_ptr<SkCanvas> mWrappedCanvas;
StartReorderBarrierDrawable* mCurrentBarrier;
/**
diff --git a/libs/hwui/renderthread/CacheManager.cpp b/libs/hwui/renderthread/CacheManager.cpp
index b07fb2d..bec80b1e 100644
--- a/libs/hwui/renderthread/CacheManager.cpp
+++ b/libs/hwui/renderthread/CacheManager.cpp
@@ -134,6 +134,7 @@
}
contextOptions->fPersistentCache = &skiapipeline::ShaderCache::get();
+ contextOptions->fGpuPathRenderers &= ~GpuPathRenderers::kCoverageCounting;
}
void CacheManager::trimMemory(TrimMemoryMode mode) {
diff --git a/libs/hwui/tests/macrobench/main.cpp b/libs/hwui/tests/macrobench/main.cpp
index b74d359..e3c97ce 100644
--- a/libs/hwui/tests/macrobench/main.cpp
+++ b/libs/hwui/tests/macrobench/main.cpp
@@ -136,8 +136,6 @@
gBenchmarkReporter.reset(new benchmark::ConsoleReporter());
} else if (!strcmp(format, "json")) {
gBenchmarkReporter.reset(new benchmark::JSONReporter());
- } else if (!strcmp(format, "csv")) {
- gBenchmarkReporter.reset(new benchmark::CSVReporter());
} else {
fprintf(stderr, "Unknown format '%s'", format);
return false;
diff --git a/media/java/android/media/MediaPlayer2.java b/media/java/android/media/MediaPlayer2.java
index 70ef81f..b747291 100644
--- a/media/java/android/media/MediaPlayer2.java
+++ b/media/java/android/media/MediaPlayer2.java
@@ -883,15 +883,6 @@
// This is a synchronous call.
public abstract void clearPendingCommands();
- /**
- * Stops playback after playback has been started or paused.
- *
- * @throws IllegalStateException if the internal player engine has not been
- * initialized.
- * @hide
- */
- public void stop() { }
-
//--------------------------------------------------------------------------
// Explicit Routing
//--------------------
@@ -1714,7 +1705,7 @@
* @param dsd the DataSourceDesc of this data source
* @param timestamp the new media clock.
*/
- public void onMediaTimeChanged(
+ public void onMediaTimeDiscontinuity(
MediaPlayer2 mp, DataSourceDesc dsd, MediaTimestamp timestamp) { }
/**
@@ -1725,44 +1716,34 @@
* {@link #notifyWhenCommandLabelReached(Object)}.
*/
public void onCommandLabelReached(MediaPlayer2 mp, @NonNull Object label) { }
+
+ /**
+ * Called when when a player subtitle track has new subtitle data available.
+ * @param mp the player that reports the new subtitle data
+ * @param dsd the DataSourceDesc of this data source
+ * @param data the subtitle data
+ */
+ public void onSubtitleData(
+ MediaPlayer2 mp, DataSourceDesc dsd, @NonNull SubtitleData data) { }
}
/**
* Sets the callback to be invoked when the media source is ready for playback.
*
- * @param eventCallback the callback that will be run
* @param executor the executor through which the callback should be invoked
+ * @param eventCallback the callback that will be run
*/
// This is a synchronous call.
- public abstract void setEventCallback(@NonNull @CallbackExecutor Executor executor,
+ public abstract void registerEventCallback(@NonNull @CallbackExecutor Executor executor,
@NonNull EventCallback eventCallback);
/**
- * Clears the {@link EventCallback}.
+ * Unregisters the {@link EventCallback}.
+ *
+ * @param eventCallback the callback to be unregistered
*/
// This is a synchronous call.
- public abstract void clearEventCallback();
-
- /**
- * Interface definition of a callback to be invoked when a
- * track has data available.
- *
- * @hide
- */
- public interface OnSubtitleDataListener
- {
- public void onSubtitleData(MediaPlayer2 mp, SubtitleData data);
- }
-
- /**
- * Register a callback to be invoked when a track has data available.
- *
- * @param listener the callback that will be run
- *
- * @hide
- */
- // This is a synchronous call.
- public void setOnSubtitleDataListener(OnSubtitleDataListener listener) { }
+ public abstract void unregisterEventCallback(EventCallback eventCallback);
/* Do not change these values without updating their counterparts
@@ -2056,11 +2037,6 @@
*/
public static final int CALL_COMPLETED_SET_PLAYBACK_PARAMS = 24;
- /** The player just completed a call {@link #setPlaybackSpeed}.
- * @see android.media.MediaPlayer2.EventCallback#onCallCompleted
- */
- public static final int CALL_COMPLETED_SET_PLAYBACK_SPEED = 25;
-
/** The player just completed a call {@link #setPlayerVolume}.
* @see android.media.MediaPlayer2.EventCallback#onCallCompleted
*/
diff --git a/media/java/android/media/MediaPlayer2Impl.java b/media/java/android/media/MediaPlayer2Impl.java
index 2b61b2e..5a71afd 100644
--- a/media/java/android/media/MediaPlayer2Impl.java
+++ b/media/java/android/media/MediaPlayer2Impl.java
@@ -97,7 +97,6 @@
private long mNativeSurfaceTexture; // accessed by native methods
private int mListenerContext; // accessed by native methods
private SurfaceHolder mSurfaceHolder;
- private EventHandler mEventHandler;
private PowerManager.WakeLock mWakeLock = null;
private boolean mScreenOnWhilePlaying;
private boolean mStayAwake;
@@ -135,7 +134,7 @@
//--- guarded by |mDrmLock| end
private HandlerThread mHandlerThread;
- private final Handler mTaskHandler;
+ private final TaskHandler mTaskHandler;
private final Object mTaskLock = new Object();
@GuardedBy("mTaskLock")
private final List<Task> mPendingTasks = new LinkedList<>();
@@ -149,19 +148,10 @@
* result in an exception.</p>
*/
public MediaPlayer2Impl() {
- Looper looper;
- if ((looper = Looper.myLooper()) != null) {
- mEventHandler = new EventHandler(this, looper);
- } else if ((looper = Looper.getMainLooper()) != null) {
- mEventHandler = new EventHandler(this, looper);
- } else {
- mEventHandler = null;
- }
-
mHandlerThread = new HandlerThread("MediaPlayer2TaskThread");
mHandlerThread.start();
- looper = mHandlerThread.getLooper();
- mTaskHandler = new Handler(looper);
+ Looper looper = mHandlerThread.getLooper();
+ mTaskHandler = new TaskHandler(this, looper);
mTimeProvider = new TimeProvider(this);
mOpenSubtitleSources = new Vector<InputStream>();
@@ -934,13 +924,13 @@
mNextSourceState = NEXT_SOURCE_STATE_PREPARING;
handleDataSource(false /* isCurrent */, mNextDSDs.get(0), mNextSrcId);
} catch (Exception e) {
- Message msg2 = mEventHandler.obtainMessage(
+ Message msg2 = mTaskHandler.obtainMessage(
MEDIA_ERROR, MEDIA_ERROR_UNKNOWN, MEDIA_ERROR_UNSUPPORTED, null);
final long nextSrcId = mNextSrcId;
- mEventHandler.post(new Runnable() {
+ mTaskHandler.post(new Runnable() {
@Override
public void run() {
- mEventHandler.handleMessage(msg2, nextSrcId);
+ mTaskHandler.handleMessage(msg2, nextSrcId);
}
});
}
@@ -967,12 +957,12 @@
try {
nativePlayNextDataSource(srcId);
} catch (Exception e) {
- Message msg2 = mEventHandler.obtainMessage(
+ Message msg2 = mTaskHandler.obtainMessage(
MEDIA_ERROR, MEDIA_ERROR_UNKNOWN, MEDIA_ERROR_UNSUPPORTED, null);
- mEventHandler.post(new Runnable() {
+ mTaskHandler.post(new Runnable() {
@Override
public void run() {
- mEventHandler.handleMessage(msg2, srcId);
+ mTaskHandler.handleMessage(msg2, srcId);
}
});
}
@@ -998,20 +988,6 @@
private native int _getAudioStreamType() throws IllegalStateException;
- /**
- * Stops playback after playback has been started or paused.
- *
- * @throws IllegalStateException if the internal player engine has not been
- * initialized.
- * #hide
- */
- @Override
- public void stop() {
- stayAwake(false);
- _stop();
- }
-
- private native void _stop() throws IllegalStateException;
//--------------------------------------------------------------------------
// Explicit Routing
@@ -1109,7 +1085,7 @@
enableNativeRoutingCallbacksLocked(true);
mRoutingChangeListeners.put(
listener, new NativeRoutingEventHandlerDelegate(this, listener,
- handler != null ? handler : mEventHandler));
+ handler != null ? handler : mTaskHandler));
}
}
}
@@ -1633,8 +1609,8 @@
stayAwake(false);
_reset();
// make sure none of the listeners get called anymore
- if (mEventHandler != null) {
- mEventHandler.removeCallbacksAndMessages(null);
+ if (mTaskHandler != null) {
+ mTaskHandler.removeCallbacksAndMessages(null);
}
synchronized (mIndexTrackPairs) {
@@ -2059,9 +2035,9 @@
private int mSelectedSubtitleTrackIndex = -1;
private Vector<InputStream> mOpenSubtitleSources;
- private OnSubtitleDataListener mSubtitleDataListener = new OnSubtitleDataListener() {
+ private EventCallback mSubtitleDataCallback = new EventCallback() {
@Override
- public void onSubtitleData(MediaPlayer2 mp, SubtitleData data) {
+ public void onSubtitleData(MediaPlayer2 mp, DataSourceDesc dsd, SubtitleData data) {
int index = data.getTrackIndex();
synchronized (mIndexTrackPairs) {
for (Pair<Integer, SubtitleTrack> p : mIndexTrackPairs) {
@@ -2085,7 +2061,7 @@
}
mSelectedSubtitleTrackIndex = -1;
}
- setOnSubtitleDataListener(null);
+ unregisterEventCallback(mSubtitleDataCallback);
if (track == null) {
return;
}
@@ -2105,7 +2081,8 @@
selectOrDeselectInbandTrack(mSelectedSubtitleTrackIndex, true);
} catch (IllegalStateException e) {
}
- setOnSubtitleDataListener(mSubtitleDataListener);
+ final Executor executor = (runnable) -> mTaskHandler.post(runnable);
+ registerEventCallback(executor, mSubtitleDataCallback);
}
// no need to select out-of-band tracks
}
@@ -2167,9 +2144,9 @@
public void run() {
int res = addTrack();
- if (mEventHandler != null) {
- Message m = mEventHandler.obtainMessage(MEDIA_INFO, res, 0, null);
- mEventHandler.sendMessage(m);
+ if (mTaskHandler != null) {
+ Message m = mTaskHandler.obtainMessage(MEDIA_INFO, res, 0, null);
+ mTaskHandler.sendMessage(m);
}
thread.getLooper().quitSafely();
}
@@ -2357,7 +2334,7 @@
if (!mSubtitleController.hasRendererFor(fFormat)) {
// test and add not atomic
Context context = ActivityThread.currentApplication();
- mSubtitleController.registerRenderer(new SRTRenderer(context, mEventHandler));
+ mSubtitleController.registerRenderer(new SRTRenderer(context, mTaskHandler));
}
final SubtitleTrack track = mSubtitleController.addTrack(fFormat);
synchronized (mIndexTrackPairs) {
@@ -2410,9 +2387,9 @@
public void run() {
int res = addTrack();
- if (mEventHandler != null) {
- Message m = mEventHandler.obtainMessage(MEDIA_INFO, res, 0, null);
- mEventHandler.sendMessage(m);
+ if (mTaskHandler != null) {
+ Message m = mTaskHandler.obtainMessage(MEDIA_INFO, res, 0, null);
+ mTaskHandler.sendMessage(m);
}
thread.getLooper().quitSafely();
}
@@ -2628,7 +2605,6 @@
mTimeProvider.close();
mTimeProvider = null;
}
- mOnSubtitleDataListener = null;
// Modular DRM clean up
mOnDrmConfigHelper = null;
@@ -2675,10 +2651,10 @@
return mTimeProvider;
}
- private class EventHandler extends Handler {
+ private class TaskHandler extends Handler {
private MediaPlayer2Impl mMediaPlayer;
- public EventHandler(MediaPlayer2Impl mp, Looper looper) {
+ public TaskHandler(MediaPlayer2Impl mp, Looper looper) {
super(looper);
mMediaPlayer = mp;
}
@@ -2969,7 +2945,8 @@
synchronized (mEventCbLock) {
for (Pair<Executor, EventCallback> cb : mEventCallbackRecords) {
- cb.first.execute(() -> cb.second.onTimedText(mMediaPlayer, mCurrentDSD, text));
+ cb.first.execute(() -> cb.second.onTimedText(
+ mMediaPlayer, mCurrentDSD, text));
}
}
return;
@@ -2977,15 +2954,16 @@
case MEDIA_SUBTITLE_DATA:
{
- OnSubtitleDataListener onSubtitleDataListener = mOnSubtitleDataListener;
- if (onSubtitleDataListener == null) {
- return;
- }
if (msg.obj instanceof Parcel) {
Parcel parcel = (Parcel) msg.obj;
SubtitleData data = new SubtitleData(parcel);
parcel.recycle();
- onSubtitleDataListener.onSubtitleData(mMediaPlayer, data);
+ synchronized (mEventCbLock) {
+ for (Pair<Executor, EventCallback> cb : mEventCallbackRecords) {
+ cb.first.execute(() -> cb.second.onSubtitleData(
+ mMediaPlayer, mCurrentDSD, data));
+ }
+ }
}
return;
}
@@ -3038,7 +3016,7 @@
/*
* Called from native code when an interesting event happens. This method
- * just uses the EventHandler system to post the event back to the main app thread.
+ * just uses the TaskHandler system to post the event back to the main app thread.
* We use a weak reference to the original MediaPlayer2 object so that the native
* code is safe from the object disappearing from underneath it. (This is
* the cookie passed to native_setup().)
@@ -3067,7 +3045,7 @@
case MEDIA_DRM_INFO:
// We need to derive mDrmInfoImpl before prepare() returns so processing it here
- // before the notification is sent to EventHandler below. EventHandler runs in the
+ // before the notification is sent to TaskHandler below. TaskHandler runs in the
// notification looper so its handleMessage might process the event after prepare()
// has returned.
Log.v(TAG, "postEventFromNative MEDIA_DRM_INFO");
@@ -3094,13 +3072,13 @@
}
- if (mp.mEventHandler != null) {
- Message m = mp.mEventHandler.obtainMessage(what, arg1, arg2, obj);
+ if (mp.mTaskHandler != null) {
+ Message m = mp.mTaskHandler.obtainMessage(what, arg1, arg2, obj);
- mp.mEventHandler.post(new Runnable() {
+ mp.mTaskHandler.post(new Runnable() {
@Override
public void run() {
- mp.mEventHandler.handleMessage(m, srcId);
+ mp.mTaskHandler.handleMessage(m, srcId);
}
});
}
@@ -3118,7 +3096,7 @@
* @param executor the executor through which the callback should be invoked
*/
@Override
- public void setEventCallback(@NonNull @CallbackExecutor Executor executor,
+ public void registerEventCallback(@NonNull @CallbackExecutor Executor executor,
@NonNull EventCallback eventCallback) {
if (eventCallback == null) {
throw new IllegalArgumentException("Illegal null EventCallback");
@@ -3136,27 +3114,16 @@
* Clears the {@link EventCallback}.
*/
@Override
- public void clearEventCallback() {
+ public void unregisterEventCallback(EventCallback eventCallback) {
synchronized (mEventCbLock) {
- mEventCallbackRecords.clear();
+ for (Pair<Executor, EventCallback> cb : mEventCallbackRecords) {
+ if (cb.second == eventCallback) {
+ mEventCallbackRecords.remove(cb);
+ }
+ }
}
}
- /**
- * Register a callback to be invoked when a track has data available.
- *
- * @param listener the callback that will be run
- *
- * @hide
- */
- @Override
- public void setOnSubtitleDataListener(OnSubtitleDataListener listener) {
- mOnSubtitleDataListener = listener;
- }
-
- private OnSubtitleDataListener mOnSubtitleDataListener;
-
-
// Modular DRM begin
/**
diff --git a/media/java/android/media/tv/TvInputManager.java b/media/java/android/media/tv/TvInputManager.java
index 143182f..ec2d9ba 100644
--- a/media/java/android/media/tv/TvInputManager.java
+++ b/media/java/android/media/tv/TvInputManager.java
@@ -888,6 +888,8 @@
if (token != null) {
session = new Session(token, channel, mService, mUserId, seq,
mSessionCallbackRecordMap);
+ } else {
+ mSessionCallbackRecordMap.delete(seq);
}
record.postSessionCreated(session);
}
@@ -2487,7 +2489,7 @@
}
}
synchronized (mSessionCallbackRecordMap) {
- mSessionCallbackRecordMap.remove(mSeq);
+ mSessionCallbackRecordMap.delete(mSeq);
}
}
diff --git a/media/jni/android_media_Media2DataSource.cpp b/media/jni/android_media_Media2DataSource.cpp
index bc3f6bd..b3434e9 100644
--- a/media/jni/android_media_Media2DataSource.cpp
+++ b/media/jni/android_media_Media2DataSource.cpp
@@ -20,12 +20,12 @@
#include "android_media_Media2DataSource.h"
-#include "android_runtime/AndroidRuntime.h"
-#include "android_runtime/Log.h"
+#include "log/log.h"
#include "jni.h"
#include <nativehelper/JNIHelp.h>
#include <drm/drm_framework_common.h>
+#include <mediaplayer2/JavaVMHelper.h>
#include <media/stagefright/foundation/ADebug.h>
#include <nativehelper/ScopedLocalRef.h>
@@ -56,7 +56,7 @@
}
JMedia2DataSource::~JMedia2DataSource() {
- JNIEnv* env = AndroidRuntime::getJNIEnv();
+ JNIEnv* env = JavaVMHelper::getJNIEnv();
env->DeleteGlobalRef(mMedia2DataSourceObj);
env->DeleteGlobalRef(mByteArrayObj);
}
@@ -75,12 +75,12 @@
size = kBufferSize;
}
- JNIEnv* env = AndroidRuntime::getJNIEnv();
+ JNIEnv* env = JavaVMHelper::getJNIEnv();
jint numread = env->CallIntMethod(mMedia2DataSourceObj, mReadAtMethod,
(jlong)offset, mByteArrayObj, (jint)0, (jint)size);
if (env->ExceptionCheck()) {
ALOGW("An exception occurred in readAt()");
- LOGW_EX(env);
+ jniLogException(env, ANDROID_LOG_WARN, LOG_TAG);
env->ExceptionClear();
mJavaObjStatus = UNKNOWN_ERROR;
return -1;
@@ -117,11 +117,11 @@
return OK;
}
- JNIEnv* env = AndroidRuntime::getJNIEnv();
+ JNIEnv* env = JavaVMHelper::getJNIEnv();
*size = env->CallLongMethod(mMedia2DataSourceObj, mGetSizeMethod);
if (env->ExceptionCheck()) {
ALOGW("An exception occurred in getSize()");
- LOGW_EX(env);
+ jniLogException(env, ANDROID_LOG_WARN, LOG_TAG);
env->ExceptionClear();
// After returning an error, size shouldn't be used by callers.
*size = UNKNOWN_ERROR;
@@ -142,7 +142,7 @@
void JMedia2DataSource::close() {
Mutex::Autolock lock(mLock);
- JNIEnv* env = AndroidRuntime::getJNIEnv();
+ JNIEnv* env = JavaVMHelper::getJNIEnv();
env->CallVoidMethod(mMedia2DataSourceObj, mCloseMethod);
// The closed state is effectively the same as an error state.
mJavaObjStatus = UNKNOWN_ERROR;
diff --git a/media/jni/android_media_Media2HTTPConnection.cpp b/media/jni/android_media_Media2HTTPConnection.cpp
index 60176e3..d02ee06 100644
--- a/media/jni/android_media_Media2HTTPConnection.cpp
+++ b/media/jni/android_media_Media2HTTPConnection.cpp
@@ -18,14 +18,14 @@
#define LOG_TAG "Media2HTTPConnection-JNI"
#include <utils/Log.h>
+#include <mediaplayer2/JavaVMHelper.h>
#include <media/stagefright/foundation/ADebug.h>
#include <nativehelper/ScopedLocalRef.h>
#include "android_media_Media2HTTPConnection.h"
#include "android_util_Binder.h"
-#include "android_runtime/AndroidRuntime.h"
-#include "android_runtime/Log.h"
+#include "log/log.h"
#include "jni.h"
#include <nativehelper/JNIHelp.h>
@@ -84,7 +84,7 @@
}
JMedia2HTTPConnection::~JMedia2HTTPConnection() {
- JNIEnv *env = AndroidRuntime::getJNIEnv();
+ JNIEnv *env = JavaVMHelper::getJNIEnv();
env->DeleteGlobalRef(mMedia2HTTPConnectionObj);
env->DeleteGlobalRef(mByteArrayObj);
}
@@ -101,7 +101,7 @@
}
}
- JNIEnv* env = AndroidRuntime::getJNIEnv();
+ JNIEnv* env = JavaVMHelper::getJNIEnv();
jstring juri = env->NewStringUTF(uri);
jstring jheaders = env->NewStringUTF(tmp.string());
@@ -115,12 +115,12 @@
}
void JMedia2HTTPConnection::disconnect() {
- JNIEnv* env = AndroidRuntime::getJNIEnv();
+ JNIEnv* env = JavaVMHelper::getJNIEnv();
env->CallVoidMethod(mMedia2HTTPConnectionObj, mDisconnectMethod);
}
ssize_t JMedia2HTTPConnection::readAt(off64_t offset, void *data, size_t size) {
- JNIEnv* env = AndroidRuntime::getJNIEnv();
+ JNIEnv* env = JavaVMHelper::getJNIEnv();
if (size > kBufferSize) {
size = kBufferSize;
@@ -141,12 +141,12 @@
}
off64_t JMedia2HTTPConnection::getSize() {
- JNIEnv* env = AndroidRuntime::getJNIEnv();
+ JNIEnv* env = JavaVMHelper::getJNIEnv();
return (off64_t)(env->CallLongMethod(mMedia2HTTPConnectionObj, mGetSizeMethod));
}
status_t JMedia2HTTPConnection::getMIMEType(String8 *mimeType) {
- JNIEnv* env = AndroidRuntime::getJNIEnv();
+ JNIEnv* env = JavaVMHelper::getJNIEnv();
jstring jmime = (jstring)env->CallObjectMethod(mMedia2HTTPConnectionObj, mGetMIMETypeMethod);
jboolean flag = env->ExceptionCheck();
if (flag) {
@@ -165,7 +165,7 @@
}
status_t JMedia2HTTPConnection::getUri(String8 *uri) {
- JNIEnv* env = AndroidRuntime::getJNIEnv();
+ JNIEnv* env = JavaVMHelper::getJNIEnv();
jstring juri = (jstring)env->CallObjectMethod(mMedia2HTTPConnectionObj, mGetUriMethod);
jboolean flag = env->ExceptionCheck();
if (flag) {
diff --git a/media/jni/android_media_Media2HTTPService.cpp b/media/jni/android_media_Media2HTTPService.cpp
index 382f099..1c63889 100644
--- a/media/jni/android_media_Media2HTTPService.cpp
+++ b/media/jni/android_media_Media2HTTPService.cpp
@@ -21,11 +21,11 @@
#include "android_media_Media2HTTPConnection.h"
#include "android_media_Media2HTTPService.h"
-#include "android_runtime/AndroidRuntime.h"
-#include "android_runtime/Log.h"
+#include "log/log.h"
#include "jni.h"
#include <nativehelper/JNIHelp.h>
+#include <mediaplayer2/JavaVMHelper.h>
#include <media/stagefright/foundation/ADebug.h>
#include <nativehelper/ScopedLocalRef.h>
@@ -46,12 +46,12 @@
}
JMedia2HTTPService::~JMedia2HTTPService() {
- JNIEnv *env = AndroidRuntime::getJNIEnv();
+ JNIEnv *env = JavaVMHelper::getJNIEnv();
env->DeleteGlobalRef(mMedia2HTTPServiceObj);
}
sp<MediaHTTPConnection> JMedia2HTTPService::makeHTTPConnection() {
- JNIEnv* env = AndroidRuntime::getJNIEnv();
+ JNIEnv* env = JavaVMHelper::getJNIEnv();
jobject media2HTTPConnectionObj =
env->CallObjectMethod(mMedia2HTTPServiceObj, mMakeHTTPConnectionMethod);
diff --git a/media/jni/android_media_MediaPlayer2.cpp b/media/jni/android_media_MediaPlayer2.cpp
index d166cc3..4265987 100644
--- a/media/jni/android_media_MediaPlayer2.cpp
+++ b/media/jni/android_media_MediaPlayer2.cpp
@@ -29,6 +29,7 @@
#include <media/stagefright/Utils.h>
#include <media/stagefright/foundation/ByteUtils.h> // for FOURCC definition
#include <mediaplayer2/JAudioTrack.h>
+#include <mediaplayer2/JavaVMHelper.h>
#include <mediaplayer2/mediaplayer2.h>
#include <stdio.h>
#include <assert.h>
@@ -39,7 +40,7 @@
#include "jni.h"
#include <nativehelper/JNIHelp.h>
#include "android/native_window_jni.h"
-#include "android_runtime/Log.h"
+#include "log/log.h"
#include "utils/Errors.h" // for status_t
#include "utils/KeyedVector.h"
#include "utils/String8.h"
@@ -184,14 +185,14 @@
JNIMediaPlayer2Listener::~JNIMediaPlayer2Listener()
{
// remove global references
- JNIEnv *env = AndroidRuntime::getJNIEnv();
+ JNIEnv *env = JavaVMHelper::getJNIEnv();
env->DeleteGlobalRef(mObject);
env->DeleteGlobalRef(mClass);
}
void JNIMediaPlayer2Listener::notify(int64_t srcId, int msg, int ext1, int ext2, const Parcel *obj)
{
- JNIEnv *env = AndroidRuntime::getJNIEnv();
+ JNIEnv *env = JavaVMHelper::getJNIEnv();
if (obj && obj->dataSize() > 0) {
jobject jParcel = createJavaParcelObject(env);
if (jParcel != NULL) {
@@ -207,7 +208,7 @@
}
if (env->ExceptionCheck()) {
ALOGW("An exception occurred while notifying an event.");
- LOGW_EX(env);
+ jniLogException(env, ANDROID_LOG_WARN, LOG_TAG);
env->ExceptionClear();
}
}
@@ -568,18 +569,6 @@
}
static void
-android_media_MediaPlayer2_stop(JNIEnv *env, jobject thiz)
-{
- ALOGV("stop");
- sp<MediaPlayer2> mp = getMediaPlayer(env, thiz);
- if (mp == NULL ) {
- jniThrowException(env, "java/lang/IllegalStateException", NULL);
- return;
- }
- process_media_player_call( env, thiz, mp->stop(), NULL, NULL );
-}
-
-static void
android_media_MediaPlayer2_pause(JNIEnv *env, jobject thiz)
{
ALOGV("pause");
@@ -1501,7 +1490,6 @@
{"_setBufferingParams", "(Landroid/media/BufferingParams;)V", (void *)android_media_MediaPlayer2_setBufferingParams},
{"_prepare", "()V", (void *)android_media_MediaPlayer2_prepare},
{"_start", "()V", (void *)android_media_MediaPlayer2_start},
- {"_stop", "()V", (void *)android_media_MediaPlayer2_stop},
{"native_getState", "()I", (void *)android_media_MediaPlayer2_getState},
{"getVideoWidth", "()I", (void *)android_media_MediaPlayer2_getVideoWidth},
{"getVideoHeight", "()I", (void *)android_media_MediaPlayer2_getVideoHeight},
@@ -1552,8 +1540,7 @@
// This function only registers the native methods
static int register_android_media_MediaPlayer2Impl(JNIEnv *env)
{
- return AndroidRuntime::registerNativeMethods(env,
- "android/media/MediaPlayer2Impl", gMethods, NELEM(gMethods));
+ return jniRegisterNativeMethods(env, "android/media/MediaPlayer2Impl", gMethods, NELEM(gMethods));
}
jint JNI_OnLoad(JavaVM* vm, void* /* reserved */)
@@ -1572,6 +1559,8 @@
goto bail;
}
+ JavaVMHelper::setJavaVM(vm);
+
/* success -- return valid version number */
result = JNI_VERSION_1_4;
diff --git a/packages/PrintSpooler/res/drawable-hdpi/ic_expand_less.png b/packages/PrintSpooler/res/drawable-hdpi/ic_expand_less.png
deleted file mode 100644
index b6a5eb5..0000000
--- a/packages/PrintSpooler/res/drawable-hdpi/ic_expand_less.png
+++ /dev/null
Binary files differ
diff --git a/packages/PrintSpooler/res/drawable-hdpi/ic_expand_more.png b/packages/PrintSpooler/res/drawable-hdpi/ic_expand_more.png
deleted file mode 100644
index 4e36bd2..0000000
--- a/packages/PrintSpooler/res/drawable-hdpi/ic_expand_more.png
+++ /dev/null
Binary files differ
diff --git a/packages/PrintSpooler/res/drawable-hdpi/ic_grayedout_printer.png b/packages/PrintSpooler/res/drawable-hdpi/ic_grayedout_printer.png
deleted file mode 100644
index 5e54970..0000000
--- a/packages/PrintSpooler/res/drawable-hdpi/ic_grayedout_printer.png
+++ /dev/null
Binary files differ
diff --git a/packages/PrintSpooler/res/drawable-hdpi/ic_restart.png b/packages/PrintSpooler/res/drawable-hdpi/ic_restart.png
deleted file mode 100644
index bb9d855..0000000
--- a/packages/PrintSpooler/res/drawable-hdpi/ic_restart.png
+++ /dev/null
Binary files differ
diff --git a/packages/PrintSpooler/res/drawable-hdpi/stat_notify_cancelling.png b/packages/PrintSpooler/res/drawable-hdpi/stat_notify_cancelling.png
deleted file mode 100644
index 2757db0..0000000
--- a/packages/PrintSpooler/res/drawable-hdpi/stat_notify_cancelling.png
+++ /dev/null
Binary files differ
diff --git a/packages/PrintSpooler/res/drawable-mdpi/ic_expand_less.png b/packages/PrintSpooler/res/drawable-mdpi/ic_expand_less.png
deleted file mode 100644
index 428a946..0000000
--- a/packages/PrintSpooler/res/drawable-mdpi/ic_expand_less.png
+++ /dev/null
Binary files differ
diff --git a/packages/PrintSpooler/res/drawable-mdpi/ic_expand_less_24dp.png b/packages/PrintSpooler/res/drawable-mdpi/ic_expand_less_24dp.png
deleted file mode 100644
index 3220eea..0000000
--- a/packages/PrintSpooler/res/drawable-mdpi/ic_expand_less_24dp.png
+++ /dev/null
Binary files differ
diff --git a/packages/PrintSpooler/res/drawable-mdpi/ic_expand_more.png b/packages/PrintSpooler/res/drawable-mdpi/ic_expand_more.png
deleted file mode 100644
index fbbd094..0000000
--- a/packages/PrintSpooler/res/drawable-mdpi/ic_expand_more.png
+++ /dev/null
Binary files differ
diff --git a/packages/PrintSpooler/res/drawable-mdpi/ic_expand_more_24dp.png b/packages/PrintSpooler/res/drawable-mdpi/ic_expand_more_24dp.png
deleted file mode 100644
index 5530f52..0000000
--- a/packages/PrintSpooler/res/drawable-mdpi/ic_expand_more_24dp.png
+++ /dev/null
Binary files differ
diff --git a/packages/PrintSpooler/res/drawable-mdpi/ic_grayedout_printer.png b/packages/PrintSpooler/res/drawable-mdpi/ic_grayedout_printer.png
deleted file mode 100644
index 5e54970..0000000
--- a/packages/PrintSpooler/res/drawable-mdpi/ic_grayedout_printer.png
+++ /dev/null
Binary files differ
diff --git a/packages/PrintSpooler/res/drawable-mdpi/ic_restart.png b/packages/PrintSpooler/res/drawable-mdpi/ic_restart.png
deleted file mode 100644
index bd611e8..0000000
--- a/packages/PrintSpooler/res/drawable-mdpi/ic_restart.png
+++ /dev/null
Binary files differ
diff --git a/packages/PrintSpooler/res/drawable-mdpi/stat_notify_cancelling.png b/packages/PrintSpooler/res/drawable-mdpi/stat_notify_cancelling.png
deleted file mode 100644
index c1b380a..0000000
--- a/packages/PrintSpooler/res/drawable-mdpi/stat_notify_cancelling.png
+++ /dev/null
Binary files differ
diff --git a/packages/PrintSpooler/res/drawable-xhdpi/ic_expand_less.png b/packages/PrintSpooler/res/drawable-xhdpi/ic_expand_less.png
deleted file mode 100644
index 6161c20..0000000
--- a/packages/PrintSpooler/res/drawable-xhdpi/ic_expand_less.png
+++ /dev/null
Binary files differ
diff --git a/packages/PrintSpooler/res/drawable-xhdpi/ic_expand_more.png b/packages/PrintSpooler/res/drawable-xhdpi/ic_expand_more.png
deleted file mode 100644
index 3a89805..0000000
--- a/packages/PrintSpooler/res/drawable-xhdpi/ic_expand_more.png
+++ /dev/null
Binary files differ
diff --git a/packages/PrintSpooler/res/drawable-xhdpi/ic_grayedout_printer.png b/packages/PrintSpooler/res/drawable-xhdpi/ic_grayedout_printer.png
deleted file mode 100644
index 5e54970..0000000
--- a/packages/PrintSpooler/res/drawable-xhdpi/ic_grayedout_printer.png
+++ /dev/null
Binary files differ
diff --git a/packages/PrintSpooler/res/drawable-xhdpi/ic_restart.png b/packages/PrintSpooler/res/drawable-xhdpi/ic_restart.png
deleted file mode 100644
index a7fdc0d..0000000
--- a/packages/PrintSpooler/res/drawable-xhdpi/ic_restart.png
+++ /dev/null
Binary files differ
diff --git a/packages/PrintSpooler/res/drawable-xhdpi/stat_notify_cancelling.png b/packages/PrintSpooler/res/drawable-xhdpi/stat_notify_cancelling.png
deleted file mode 100644
index fedc00e..0000000
--- a/packages/PrintSpooler/res/drawable-xhdpi/stat_notify_cancelling.png
+++ /dev/null
Binary files differ
diff --git a/packages/PrintSpooler/res/drawable-xxhdpi/ic_expand_less.png b/packages/PrintSpooler/res/drawable-xxhdpi/ic_expand_less.png
deleted file mode 100644
index 52a52d9..0000000
--- a/packages/PrintSpooler/res/drawable-xxhdpi/ic_expand_less.png
+++ /dev/null
Binary files differ
diff --git a/packages/PrintSpooler/res/drawable-xxhdpi/ic_expand_more.png b/packages/PrintSpooler/res/drawable-xxhdpi/ic_expand_more.png
deleted file mode 100644
index 15e6abd..0000000
--- a/packages/PrintSpooler/res/drawable-xxhdpi/ic_expand_more.png
+++ /dev/null
Binary files differ
diff --git a/packages/PrintSpooler/res/drawable-xxxhdpi/ic_expand_less.png b/packages/PrintSpooler/res/drawable-xxxhdpi/ic_expand_less.png
deleted file mode 100644
index 46811a1..0000000
--- a/packages/PrintSpooler/res/drawable-xxxhdpi/ic_expand_less.png
+++ /dev/null
Binary files differ
diff --git a/packages/PrintSpooler/res/drawable-xxxhdpi/ic_expand_more.png b/packages/PrintSpooler/res/drawable-xxxhdpi/ic_expand_more.png
deleted file mode 100644
index 141f28b..0000000
--- a/packages/PrintSpooler/res/drawable-xxxhdpi/ic_expand_more.png
+++ /dev/null
Binary files differ
diff --git a/packages/PrintSpooler/res/drawable/ic_clear.xml b/packages/PrintSpooler/res/drawable/ic_clear.xml
new file mode 100644
index 0000000..076e8ef
--- /dev/null
+++ b/packages/PrintSpooler/res/drawable/ic_clear.xml
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ Copyright (C) 2018 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ -->
+
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:width="24dp"
+ android:height="24dp"
+ android:viewportWidth="24.0"
+ android:viewportHeight="24.0">
+ <path
+ android:pathData="M19,6.41L17.59,5 12,10.59 6.41,5 5,6.41 10.59,12 5,17.59 6.41,19 12,13.41 17.59,19 19,17.59 13.41,12z"
+ android:fillColor="?android:colorForeground"/>
+</vector>
diff --git a/packages/PrintSpooler/res/drawable/ic_expand_less.xml b/packages/PrintSpooler/res/drawable/ic_expand_less.xml
index 6f1ece1..c3e87dc 100644
--- a/packages/PrintSpooler/res/drawable/ic_expand_less.xml
+++ b/packages/PrintSpooler/res/drawable/ic_expand_less.xml
@@ -1,43 +1,26 @@
<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2014 The Android Open Source Project
+<!--
+ Copyright (C) 2018 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
+ 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
+ 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.
--->
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ -->
-<selector xmlns:android="http://schemas.android.com/apk/res/android"
- android:autoMirrored="true">
-
- <item
- android:state_checked="true">
- <bitmap
- android:src="@drawable/ic_expand_less"
- android:tint="?android:attr/colorControlActivated">
- </bitmap>
- </item>
-
- <item
- android:state_pressed="true">
- <bitmap
- android:src="@drawable/ic_expand_less"
- android:tint="?android:attr/colorControlActivated">
- </bitmap>
- </item>
-
- <item>
- <bitmap
- android:src="@drawable/ic_expand_less"
- android:tint="?android:attr/colorControlNormal">
- </bitmap>
- </item>
-
-</selector>
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:width="24dp"
+ android:height="24dp"
+ android:viewportWidth="24.0"
+ android:viewportHeight="24.0">
+ <path
+ android:pathData="M7.41,15.41L12,10.83l4.59,4.58L18,14l-6,-6 -6,6z"
+ android:fillColor="?android:colorForeground" />
+</vector>
\ No newline at end of file
diff --git a/packages/PrintSpooler/res/drawable/ic_expand_more.xml b/packages/PrintSpooler/res/drawable/ic_expand_more.xml
index 8d71452..3895144 100644
--- a/packages/PrintSpooler/res/drawable/ic_expand_more.xml
+++ b/packages/PrintSpooler/res/drawable/ic_expand_more.xml
@@ -1,43 +1,26 @@
<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2014 The Android Open Source Project
+<!--
+ Copyright (C) 2018 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
+ 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
+ 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.
--->
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ -->
-<selector xmlns:android="http://schemas.android.com/apk/res/android"
- android:autoMirrored="true">
-
- <item
- android:state_checked="true">
- <bitmap
- android:src="@drawable/ic_expand_more"
- android:tint="?android:attr/colorControlActivated">
- </bitmap>
- </item>
-
- <item
- android:state_pressed="true">
- <bitmap
- android:src="@drawable/ic_expand_more"
- android:tint="?android:attr/colorControlActivated">
- </bitmap>
- </item>
-
- <item>
- <bitmap
- android:src="@drawable/ic_expand_more"
- android:tint="?android:attr/colorControlNormal">
- </bitmap>
- </item>
-
-</selector>
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:width="24dp"
+ android:height="24dp"
+ android:viewportWidth="24.0"
+ android:viewportHeight="24.0">
+ <path
+ android:pathData="M7.41,8.59L12,13.17l4.59,-4.58L18,10l-6,6l-6,-6L7.41,8.59z"
+ android:fillColor="?android:colorForeground" />
+</vector>
\ No newline at end of file
diff --git a/packages/PrintSpooler/res/drawable/print_warning.xml b/packages/PrintSpooler/res/drawable/print_warning.xml
deleted file mode 100644
index 35f0fed..0000000
--- a/packages/PrintSpooler/res/drawable/print_warning.xml
+++ /dev/null
@@ -1,25 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2016 The Android Open Source Project
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
--->
-
-<vector xmlns:android="http://schemas.android.com/apk/res/android"
- android:width="96dp"
- android:height="96dp"
- android:viewportWidth="96.0"
- android:viewportHeight="96.0">
- <path
- android:fillColor="#C8CCCE"
- android:pathData="M4,84H92L48,8 4,84zM52,72h-8v-8h8v8zM52,56H44V40h8v16z"/>
-</vector>
diff --git a/packages/PrintSpooler/res/layout/preview_page.xml b/packages/PrintSpooler/res/layout/preview_page.xml
index aafdd8f..8db347e 100644
--- a/packages/PrintSpooler/res/layout/preview_page.xml
+++ b/packages/PrintSpooler/res/layout/preview_page.xml
@@ -44,7 +44,7 @@
android:layout_height="wrap_content"
android:layout_centerInParent="true"
android:textAppearance="?android:attr/textAppearanceSmall"
- android:textColor="?android:attr/textColorPrimary">
+ android:textColor="@android:color/white">
</TextView>
<ImageView
diff --git a/packages/PrintSpooler/res/layout/preview_page_error.xml b/packages/PrintSpooler/res/layout/preview_page_error.xml
index 4e9fb77..99ab99d 100644
--- a/packages/PrintSpooler/res/layout/preview_page_error.xml
+++ b/packages/PrintSpooler/res/layout/preview_page_error.xml
@@ -21,11 +21,14 @@
android:gravity="center">
<ImageView
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:layout_marginBottom="12dip"
- android:src="@drawable/print_warning"
- android:contentDescription="@null" />
+ android:layout_width="120dp"
+ android:layout_height="110dp"
+ android:layout_marginBottom="12dip"
+ android:src="@*android:drawable/ic_print_error"
+ android:scaleType="fitEnd"
+ android:alpha="0.1"
+ android:tint="@android:color/black"
+ android:importantForAccessibility="no" />
<TextView
android:layout_width="wrap_content"
diff --git a/packages/PrintSpooler/res/layout/preview_page_loading.xml b/packages/PrintSpooler/res/layout/preview_page_loading.xml
index 1af3a17..918edd9 100644
--- a/packages/PrintSpooler/res/layout/preview_page_loading.xml
+++ b/packages/PrintSpooler/res/layout/preview_page_loading.xml
@@ -19,14 +19,13 @@
android:layout_height="fill_parent">
<ImageView
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:layout_margin="36dip"
+ android:layout_width="120dp"
+ android:layout_height="110dp"
android:layout_gravity="center"
- android:src="@drawable/ic_grayedout_printer"
- android:contentDescription="@null"
- android:scaleType="centerInside"
- android:adjustViewBounds="true">
- </ImageView>
+ android:src="@*android:drawable/ic_print"
+ android:scaleType="fitCenter"
+ android:alpha="0.1"
+ android:tint="@android:color/black"
+ android:importantForAccessibility="no" />
</FrameLayout>
diff --git a/packages/PrintSpooler/res/layout/preview_page_selected.xml b/packages/PrintSpooler/res/layout/preview_page_selected.xml
index 77f4727..6727142 100644
--- a/packages/PrintSpooler/res/layout/preview_page_selected.xml
+++ b/packages/PrintSpooler/res/layout/preview_page_selected.xml
@@ -42,7 +42,7 @@
android:layout_height="wrap_content"
android:layout_centerInParent="true"
android:textAppearance="?android:attr/textAppearanceSmall"
- android:textColor="?android:attr/textColorPrimary">
+ android:textColor="@android:color/white">
</TextView>
<ImageView
diff --git a/packages/PrintSpooler/res/layout/print_activity.xml b/packages/PrintSpooler/res/layout/print_activity.xml
index 774f320..212f398 100644
--- a/packages/PrintSpooler/res/layout/print_activity.xml
+++ b/packages/PrintSpooler/res/layout/print_activity.xml
@@ -29,7 +29,7 @@
android:paddingStart="8dip"
android:layout_marginEnd="16dp"
android:elevation="@dimen/preview_controls_elevation"
- android:background="?android:attr/colorPrimary">
+ style="?android:actionBarStyle">
<com.android.printspooler.widget.ClickInterceptSpinner
android:id="@+id/destination_spinner"
@@ -55,7 +55,7 @@
android:paddingBottom="8dip"
android:orientation="horizontal"
android:elevation="@dimen/preview_controls_elevation"
- android:background="?android:attr/colorPrimary">
+ style="?android:actionBarStyle">
<TextView
android:layout_width="wrap_content"
@@ -121,7 +121,6 @@
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:animateLayoutChanges="true"
- android:background="@color/print_preview_background_color"
android:gravity="center">
<!-- Error message added here -->
diff --git a/packages/PrintSpooler/res/layout/print_activity_controls.xml b/packages/PrintSpooler/res/layout/print_activity_controls.xml
index 69d4f91..3aafc99 100644
--- a/packages/PrintSpooler/res/layout/print_activity_controls.xml
+++ b/packages/PrintSpooler/res/layout/print_activity_controls.xml
@@ -22,7 +22,7 @@
android:layout_height="wrap_content"
android:orientation="vertical"
android:elevation="@dimen/preview_controls_elevation"
- android:background="?android:attr/colorPrimary">
+ style="?android:actionBarStyle">
<LinearLayout
android:id="@+id/draggable_content"
diff --git a/packages/PrintSpooler/res/layout/print_error_fragment.xml b/packages/PrintSpooler/res/layout/print_error_fragment.xml
index 3ea2abd..9d9dd01 100644
--- a/packages/PrintSpooler/res/layout/print_error_fragment.xml
+++ b/packages/PrintSpooler/res/layout/print_error_fragment.xml
@@ -16,35 +16,39 @@
-->
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
- android:layout_width="fill_parent"
- android:layout_height="fill_parent"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:layout_marginStart="16dip"
+ android:layout_marginEnd="16dip"
android:gravity="center"
android:orientation="vertical">
<ImageView
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:layout_marginBottom="12dip"
- android:src="@drawable/ic_grayedout_printer"
- android:contentDescription="@null">
- </ImageView>
+ android:layout_width="120dp"
+ android:layout_height="110dp"
+ android:layout_marginBottom="12dp"
+ android:src="@*android:drawable/ic_print_error"
+ android:scaleType="fitEnd"
+ android:alpha="0.1"
+ android:tint="?android:colorForeground"
+ android:importantForAccessibility="no" />
<TextView
android:id="@+id/message"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
- android:layout_marginStart="16dip"
- android:layout_marginEnd="16dip"
- android:gravity="center_horizontal"
- android:text="@string/print_error_default_message"
- android:textAppearance="?android:attr/textAppearanceLargeInverse">
- </TextView>
+ android:layout_marginBottom="16dp"
+ android:gravity="center"
+ android:textAppearance="?android:attr/textAppearanceLarge"
+ android:textColor="?android:attr/textColorSecondary"
+ android:text="@string/print_error_default_message" />
<Button
android:id="@+id/action_button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
- android:text="@string/print_error_retry">
- </Button>
+ style="?android:attr/borderlessButtonStyle"
+ android:textColor="?android:attr/textColorSecondary"
+ android:text="@string/print_add_printer" />
</LinearLayout>
diff --git a/packages/PrintSpooler/res/layout/print_progress_fragment.xml b/packages/PrintSpooler/res/layout/print_progress_fragment.xml
index 3b010f8..89071605 100644
--- a/packages/PrintSpooler/res/layout/print_progress_fragment.xml
+++ b/packages/PrintSpooler/res/layout/print_progress_fragment.xml
@@ -15,34 +15,39 @@
-->
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:layout_gravity="center"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:layout_marginStart="16dp"
+ android:layout_marginEnd="16dp"
android:gravity="center"
android:orientation="vertical">
<ImageView
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:layout_marginBottom="12dip"
- android:src="@drawable/ic_grayedout_printer"
- android:contentDescription="@null">
- </ImageView>
-
- <ProgressBar
- android:layout_width="fill_parent"
- android:layout_height="wrap_content"
- android:indeterminate="true"
- style="?android:attr/progressBarStyleHorizontal">
- </ProgressBar>
+ android:layout_width="120dp"
+ android:layout_height="110dp"
+ android:layout_marginBottom="12dp"
+ android:src="@*android:drawable/ic_print"
+ android:scaleType="fitEnd"
+ android:alpha="0.1"
+ android:tint="?android:colorForeground"
+ android:importantForAccessibility="no" />
<TextView
android:id="@+id/message"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
- android:textAppearance="?android:attr/textAppearanceLargeInverse"
- android:text="@string/print_preparing_preview">
- </TextView>
+ android:layout_marginBottom="16dp"
+ android:gravity="center"
+ android:textAppearance="?android:attr/textAppearanceLarge"
+ android:textColor="?android:attr/textColorSecondary"
+ android:text="@string/print_preparing_preview" />
+
+ <ProgressBar
+ android:layout_width="300dp"
+ android:layout_height="wrap_content"
+ android:indeterminate="true"
+ android:importantForAccessibility="no"
+ style="?android:attr/progressBarStyleHorizontal" />
</LinearLayout>
diff --git a/packages/PrintSpooler/res/layout/select_printer_activity.xml b/packages/PrintSpooler/res/layout/select_printer_activity.xml
index 91beff6..681924b 100644
--- a/packages/PrintSpooler/res/layout/select_printer_activity.xml
+++ b/packages/PrintSpooler/res/layout/select_printer_activity.xml
@@ -31,45 +31,48 @@
android:visibility="gone">
<LinearLayout
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:layout_gravity="center"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:layout_marginStart="16dp"
+ android:layout_marginEnd="16dp"
android:gravity="center"
android:orientation="vertical">
<ImageView
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:layout_marginBottom="12dip"
- android:src="@*android:drawable/ic_grayedout_printer"
- android:importantForAccessibility="no">
- </ImageView>
+ android:layout_width="120dp"
+ android:layout_height="110dp"
+ android:layout_marginBottom="12dp"
+ android:src="@*android:drawable/ic_print"
+ android:scaleType="fitEnd"
+ android:alpha="0.1"
+ android:tint="?android:colorForeground"
+ android:importantForAccessibility="no" />
<TextView
android:id="@+id/title"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
+ android:layout_marginBottom="16dp"
+ android:gravity="center"
android:textAppearance="?android:attr/textAppearanceLarge"
android:textColor="?android:attr/textColorSecondary"
- android:text="@string/print_searching_for_printers">
- </TextView>
+ android:text="@string/print_searching_for_printers" />
<ProgressBar
android:id="@+id/progress_bar"
- android:layout_width="fill_parent"
+ android:layout_width="300dp"
android:layout_height="wrap_content"
android:indeterminate="true"
- style="?android:attr/progressBarStyleHorizontal">
- </ProgressBar>
+ android:importantForAccessibility="no"
+ style="?android:attr/progressBarStyleHorizontal" />
<Button
- android:id="@+id/button"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- style="?android:attr/buttonBarButtonStyle"
- android:textAppearance="?android:attr/textAppearanceSmall"
- android:text="@string/print_add_printer"
- android:textAllCaps="true" />
+ android:id="@+id/button"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ style="?android:attr/borderlessButtonStyle"
+ android:textColor="?android:attr/textColorSecondary"
+ android:text="@string/print_add_printer" />
</LinearLayout>
diff --git a/packages/PrintSpooler/res/values/colors.xml b/packages/PrintSpooler/res/values/colors.xml
index 68bc6f2..cb9e886 100644
--- a/packages/PrintSpooler/res/values/colors.xml
+++ b/packages/PrintSpooler/res/values/colors.xml
@@ -18,8 +18,6 @@
<color name="print_preview_scrim_color">#99000000</color>
- <color name="print_preview_background_color">#F2F1F2</color>
-
<color name="unselected_page_background_color">#C0C0C0</color>
<color name="material_grey_500">#ffa3a3a3</color>
diff --git a/packages/PrintSpooler/res/values/themes.xml b/packages/PrintSpooler/res/values/themes.xml
index a968ffa..844e9c9 100644
--- a/packages/PrintSpooler/res/values/themes.xml
+++ b/packages/PrintSpooler/res/values/themes.xml
@@ -21,17 +21,14 @@
</style>
<style name="Theme.SelectPrinterActivity"
- parent="android:style/Theme.DeviceDefault.Light.DarkActionBar">
+ parent="android:style/Theme.DeviceDefault.Light">
<item name="android:textAppearanceListItemSecondary">@style/ListItemSecondary</item>
</style>
- <style name="Theme.PrintActivity" parent="@android:style/Theme.DeviceDefault">
+ <style name="Theme.PrintActivity" parent="@android:style/Theme.DeviceDefault.Light">
<item name="android:windowIsTranslucent">true</item>
- <item name="android:windowBackground">@android:color/transparent</item>
- <item name="android:windowContentOverlay">@null</item>
<item name="android:windowActionBar">false</item>
<item name="android:windowNoTitle">true</item>
- <item name="android:backgroundDimEnabled">false</item>
</style>
</resources>
diff --git a/packages/PrintSpooler/src/com/android/printspooler/model/NotificationController.java b/packages/PrintSpooler/src/com/android/printspooler/model/NotificationController.java
index 9d737e0..abdfad5 100644
--- a/packages/PrintSpooler/src/com/android/printspooler/model/NotificationController.java
+++ b/packages/PrintSpooler/src/com/android/printspooler/model/NotificationController.java
@@ -166,7 +166,7 @@
*/
private Action createCancelAction(PrintJobInfo printJob) {
return new Action.Builder(
- Icon.createWithResource(mContext, R.drawable.stat_notify_cancelling),
+ Icon.createWithResource(mContext, R.drawable.ic_clear),
mContext.getString(R.string.cancel), createCancelIntent(printJob)).build();
}
@@ -225,7 +225,7 @@
private void createFailedNotification(PrintJobInfo printJob) {
Action.Builder restartActionBuilder = new Action.Builder(
- Icon.createWithResource(mContext, R.drawable.ic_restart),
+ Icon.createWithResource(mContext, com.android.internal.R.drawable.ic_restart),
mContext.getString(R.string.restart), createRestartIntent(printJob.getId()));
createNotification(printJob, createCancelAction(printJob), restartActionBuilder.build());
@@ -317,7 +317,7 @@
if (!printJob.isCancelling()) {
return com.android.internal.R.drawable.ic_print;
} else {
- return R.drawable.stat_notify_cancelling;
+ return R.drawable.ic_clear;
}
}
}
diff --git a/packages/SettingsLib/res/values-bs/arrays.xml b/packages/SettingsLib/res/values-bs/arrays.xml
index 8577779..9b3c38c 100644
--- a/packages/SettingsLib/res/values-bs/arrays.xml
+++ b/packages/SettingsLib/res/values-bs/arrays.xml
@@ -27,7 +27,7 @@
<item msgid="515055375277271756">"Autentifikacija…"</item>
<item msgid="1943354004029184381">"Dobivanje IP adrese…"</item>
<item msgid="4221763391123233270">"Povezano"</item>
- <item msgid="624838831631122137">"Suspendiran"</item>
+ <item msgid="624838831631122137">"Suspendirano"</item>
<item msgid="7979680559596111948">"Prekidanje veze…"</item>
<item msgid="1634960474403853625">"Isključen"</item>
<item msgid="746097431216080650">"Neuspješno"</item>
@@ -38,11 +38,11 @@
<item msgid="7714855332363650812"></item>
<item msgid="8878186979715711006">"Skeniranje…"</item>
<item msgid="355508996603873860">"Povezivanje na mrežu <xliff:g id="NETWORK_NAME">%1$s</xliff:g>..."</item>
- <item msgid="554971459996405634">"Autentifikacija sa mrežom <xliff:g id="NETWORK_NAME">%1$s</xliff:g>…"</item>
+ <item msgid="554971459996405634">"Autentifikacija s mrežom <xliff:g id="NETWORK_NAME">%1$s</xliff:g>…"</item>
<item msgid="7928343808033020343">"Dobivanje IP adrese iz mreže <xliff:g id="NETWORK_NAME">%1$s</xliff:g>…"</item>
- <item msgid="8937994881315223448">"Povezan na mrežu <xliff:g id="NETWORK_NAME">%1$s</xliff:g>"</item>
- <item msgid="1330262655415760617">"Suspendiran"</item>
- <item msgid="7698638434317271902">"Prekidanje veze sa mrežom <xliff:g id="NETWORK_NAME">%1$s</xliff:g>…"</item>
+ <item msgid="8937994881315223448">"Povezano na mrežu <xliff:g id="NETWORK_NAME">%1$s</xliff:g>"</item>
+ <item msgid="1330262655415760617">"Suspendirano"</item>
+ <item msgid="7698638434317271902">"Prekidanje veze s mrežom <xliff:g id="NETWORK_NAME">%1$s</xliff:g>…"</item>
<item msgid="197508606402264311">"Isključen"</item>
<item msgid="8578370891960825148">"Neuspješno"</item>
<item msgid="5660739516542454527">"Blokirano"</item>
@@ -59,7 +59,7 @@
<item msgid="45075631231212732">"Uvijek koristi HDCP provjeru"</item>
</string-array>
<string-array name="bluetooth_avrcp_versions">
- <item msgid="5347678900838034763">"AVRCP 1.4 (Zadano)"</item>
+ <item msgid="5347678900838034763">"AVRCP 1.4 (zadano)"</item>
<item msgid="2809759619990248160">"AVRCP 1.3"</item>
<item msgid="6199178154704729352">"AVRCP 1.5"</item>
<item msgid="5172170854953034852">"AVRCP 1.6"</item>
@@ -71,58 +71,58 @@
<item msgid="3422726142222090896">"avrcp16"</item>
</string-array>
<string-array name="bluetooth_a2dp_codec_titles">
- <item msgid="7065842274271279580">"Koristi odabir sistema (Zadano)"</item>
+ <item msgid="7065842274271279580">"Koristi odabir sistema (zadano)"</item>
<item msgid="7539690996561263909">"SBC"</item>
<item msgid="686685526567131661">"AAC"</item>
<item msgid="5254942598247222737">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX">aptX™</xliff:g> audio"</item>
<item msgid="2091430979086738145">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_HD">aptX™ HD</xliff:g> audio"</item>
<item msgid="6751080638867012696">"LDAC"</item>
- <item msgid="723675059572222462">"Omogućite opcionalne kodeke"</item>
- <item msgid="3304843301758635896">"Onemogućite opcionalne kodeke"</item>
+ <item msgid="723675059572222462">"Omogući opcionalne kodeke"</item>
+ <item msgid="3304843301758635896">"Onemogući opcionalne kodeke"</item>
</string-array>
<string-array name="bluetooth_a2dp_codec_summaries">
- <item msgid="5062108632402595000">"Koristi odabir sistema (Zadano)"</item>
+ <item msgid="5062108632402595000">"Koristi odabir sistema (zadano)"</item>
<item msgid="6898329690939802290">"SBC"</item>
<item msgid="6839647709301342559">"AAC"</item>
<item msgid="7848030269621918608">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX">aptX™</xliff:g> audio"</item>
<item msgid="298198075927343893">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_HD">aptX™ HD</xliff:g> audio"</item>
<item msgid="7950781694447359344">"LDAC"</item>
- <item msgid="2209680154067241740">"Omogućite opcionalne kodeke"</item>
- <item msgid="741805482892725657">"Onemogućite opcionalne kodeke"</item>
+ <item msgid="2209680154067241740">"Omogući opcionalne kodeke"</item>
+ <item msgid="741805482892725657">"Onemogući opcionalne kodeke"</item>
</string-array>
<string-array name="bluetooth_a2dp_codec_sample_rate_titles">
- <item msgid="3093023430402746802">"Koristi odabir sistema (Zadano)"</item>
+ <item msgid="3093023430402746802">"Koristi odabir sistema (zadano)"</item>
<item msgid="8895532488906185219">"44,1 kHz"</item>
<item msgid="2909915718994807056">"48,0 kHz"</item>
<item msgid="3347287377354164611">"88,2 kHz"</item>
<item msgid="1234212100239985373">"96,0 kHz"</item>
</string-array>
<string-array name="bluetooth_a2dp_codec_sample_rate_summaries">
- <item msgid="3214516120190965356">"Koristi odabir sistema (Zadano)"</item>
+ <item msgid="3214516120190965356">"Koristi odabir sistema (zadano)"</item>
<item msgid="4482862757811638365">"44,1 kHz"</item>
<item msgid="354495328188724404">"48,0 kHz"</item>
<item msgid="7329816882213695083">"88,2 kHz"</item>
<item msgid="6967397666254430476">"96,0 kHz"</item>
</string-array>
<string-array name="bluetooth_a2dp_codec_bits_per_sample_titles">
- <item msgid="2684127272582591429">"Koristi odabir sistema (Zadano)"</item>
+ <item msgid="2684127272582591429">"Koristi odabir sistema (zadano)"</item>
<item msgid="5618929009984956469">"16 bitova/uzorak"</item>
<item msgid="3412640499234627248">"24 bitova/uzorak"</item>
<item msgid="121583001492929387">"32 bitova/uzorak"</item>
</string-array>
<string-array name="bluetooth_a2dp_codec_bits_per_sample_summaries">
- <item msgid="1081159789834584363">"Koristi odabir sistema (Zadano)"</item>
+ <item msgid="1081159789834584363">"Koristi odabir sistema (zadano)"</item>
<item msgid="4726688794884191540">"16 bitova/uzorak"</item>
<item msgid="305344756485516870">"24 bitova/uzorak"</item>
<item msgid="244568657919675099">"32 bitova/uzorak"</item>
</string-array>
<string-array name="bluetooth_a2dp_codec_channel_mode_titles">
- <item msgid="5226878858503393706">"Koristi odabir sistema (Zadano)"</item>
+ <item msgid="5226878858503393706">"Koristi odabir sistema (zadano)"</item>
<item msgid="4106832974775067314">"Mono"</item>
<item msgid="5571632958424639155">"Stereo"</item>
</string-array>
<string-array name="bluetooth_a2dp_codec_channel_mode_summaries">
- <item msgid="4118561796005528173">"Koristi odabir sistema (Zadano)"</item>
+ <item msgid="4118561796005528173">"Koristi odabir sistema (zadano)"</item>
<item msgid="8900559293912978337">"Mono"</item>
<item msgid="8883739882299884241">"Stereo"</item>
</string-array>
@@ -130,13 +130,13 @@
<item msgid="7158319962230727476">"Optimizirano za kvalitet zvuka (990 kbps/909 kbps)"</item>
<item msgid="2921767058740704969">"Uravnotežen kvalitet zvuka i veze (660kbps/606kbps)"</item>
<item msgid="8860982705384396512">"Optimizirano za kvalitet veze (330 kbps/303 kbps)"</item>
- <item msgid="4414060457677684127">"Maksimalan napor (Prilagodljiva brzina prijenosa)"</item>
+ <item msgid="4414060457677684127">"Maksimalan napor (prilagodljiva brzina prijenosa)"</item>
</string-array>
<string-array name="bluetooth_a2dp_codec_ldac_playback_quality_summaries">
<item msgid="6398189564246596868">"Optimizirano za kvalitet zvuka"</item>
<item msgid="4327143584633311908">"Uravnotežen kvalitet zvuka i veze"</item>
<item msgid="4681409244565426925">"Optimizirano za kvalitet veze"</item>
- <item msgid="364670732877872677">"Maksimalan napor (Prilagodljiva brzina prijenosa)"</item>
+ <item msgid="364670732877872677">"Maksimalan napor (prilagodljiva brzina prijenosa)"</item>
</string-array>
<string-array name="bluetooth_audio_active_device_summaries">
<item msgid="4862957058729193940"></item>
@@ -169,7 +169,7 @@
<string-array name="select_logpersist_titles">
<item msgid="1744840221860799971">"Isključeno"</item>
<item msgid="3054662377365844197">"Sve"</item>
- <item msgid="688870735111627832">"Svi osim radija"</item>
+ <item msgid="688870735111627832">"Sve osim radija"</item>
<item msgid="2850427388488887328">"samo kernel"</item>
</string-array>
<string-array name="select_logpersist_summaries">
@@ -208,13 +208,13 @@
<string-array name="overlay_display_devices_entries">
<item msgid="1606809880904982133">"Nema"</item>
<item msgid="9033194758688161545">"480p"</item>
- <item msgid="1025306206556583600">"480p (osiguran)"</item>
+ <item msgid="1025306206556583600">"480p (sigurno)"</item>
<item msgid="1853913333042744661">"720p"</item>
- <item msgid="3414540279805870511">"720p (osiguran)"</item>
+ <item msgid="3414540279805870511">"720p (sigurno)"</item>
<item msgid="9039818062847141551">"1080p"</item>
- <item msgid="4939496949750174834">"1080p (osiguran)"</item>
+ <item msgid="4939496949750174834">"1080p (sigurno)"</item>
<item msgid="1833612718524903568">"4K"</item>
- <item msgid="238303513127879234">"4K (osiguran)"</item>
+ <item msgid="238303513127879234">"4K (sigurno)"</item>
<item msgid="3547211260846843098">"4K (povećava rezoluciju)"</item>
<item msgid="5411365648951414254">"4K (povećava rezoluciju, osiguran)"</item>
<item msgid="1311305077526792901">"720p, 1080p (dupli ekran)"</item>
diff --git a/packages/SettingsLib/res/values-bs/strings.xml b/packages/SettingsLib/res/values-bs/strings.xml
index b8195b1..e049f6f 100644
--- a/packages/SettingsLib/res/values-bs/strings.xml
+++ b/packages/SettingsLib/res/values-bs/strings.xml
@@ -43,7 +43,7 @@
<string name="wifi_status_no_internet" msgid="5784710974669608361">"Nema internetske veze"</string>
<string name="wifi_status_sign_in_required" msgid="123517180404752756">"Potrebna je prijava"</string>
<string name="wifi_ap_unable_to_handle_new_sta" msgid="5348824313514404541">"Pristupna tačka je privremeno puna"</string>
- <string name="connected_via_carrier" msgid="7583780074526041912">"Povezana koristeći %1$s"</string>
+ <string name="connected_via_carrier" msgid="7583780074526041912">"Povezano koristeći %1$s"</string>
<string name="available_via_carrier" msgid="1469036129740799053">"Dostupna koristeći %1$s"</string>
<string name="speed_label_very_slow" msgid="1867055264243608530">"Veoma sporo"</string>
<string name="speed_label_slow" msgid="813109590815810235">"Sporo"</string>
@@ -84,11 +84,11 @@
<string name="bluetooth_hearing_aid_profile_summary_connected" msgid="7188282786730266159">"Povezano na slušni aparat"</string>
<string name="bluetooth_a2dp_profile_summary_connected" msgid="963376081347721598">"Povezano sa zvukom medija"</string>
<string name="bluetooth_headset_profile_summary_connected" msgid="7661070206715520671">"Povezano na zvuk telefona"</string>
- <string name="bluetooth_opp_profile_summary_connected" msgid="2611913495968309066">"Povezan na server za prijenos podataka"</string>
+ <string name="bluetooth_opp_profile_summary_connected" msgid="2611913495968309066">"Povezano sa serverom za prijenos podataka"</string>
<string name="bluetooth_map_profile_summary_connected" msgid="8191407438851351713">"Povezano na mapu"</string>
<string name="bluetooth_sap_profile_summary_connected" msgid="8561765057453083838">"Povezan na SAP"</string>
- <string name="bluetooth_opp_profile_summary_not_connected" msgid="1267091356089086285">"Nije povezan na server za prijenos podataka"</string>
- <string name="bluetooth_hid_profile_summary_connected" msgid="3381760054215168689">"Spojen na ulazni uređaj"</string>
+ <string name="bluetooth_opp_profile_summary_not_connected" msgid="1267091356089086285">"Nije povezano sa serverom za prijenos podataka"</string>
+ <string name="bluetooth_hid_profile_summary_connected" msgid="3381760054215168689">"Povezano s ulaznim uređajem"</string>
<string name="bluetooth_pan_user_profile_summary_connected" msgid="6436258151814414028">"Povezano na uređaj za pristup internetu"</string>
<string name="bluetooth_pan_nap_profile_summary_connected" msgid="1322694224800769308">"Dijeljenje lokalne internetske veze s uređajem"</string>
<string name="bluetooth_pan_profile_summary_use_for" msgid="5736111170225304239">"Koristi za pristup internetu"</string>
@@ -102,10 +102,10 @@
<string name="bluetooth_pairing_accept" msgid="6163520056536604875">"Upari"</string>
<string name="bluetooth_pairing_accept_all_caps" msgid="6061699265220789149">"UPARI"</string>
<string name="bluetooth_pairing_decline" msgid="4185420413578948140">"Otkaži"</string>
- <string name="bluetooth_pairing_will_share_phonebook" msgid="4982239145676394429">"Uparivanje odobrava pristup kontaktima i istoriji poziva kada je uspostavljeno."</string>
- <string name="bluetooth_pairing_error_message" msgid="3748157733635947087">"Nije se moguće upariti s uređajem <xliff:g id="DEVICE_NAME">%1$s</xliff:g>."</string>
- <string name="bluetooth_pairing_pin_error_message" msgid="8337234855188925274">"Nije se moguće upariti s uređajem <xliff:g id="DEVICE_NAME">%1$s</xliff:g> zbog pogrešnog PIN-a ili pristupnog koda."</string>
- <string name="bluetooth_pairing_device_down_error_message" msgid="7870998403045801381">"Ne može komunicirati sa uređajem <xliff:g id="DEVICE_NAME">%1$s</xliff:g>."</string>
+ <string name="bluetooth_pairing_will_share_phonebook" msgid="4982239145676394429">"Uparivanje odobrava pristup kontaktima i historiji poziva kada je uspostavljeno."</string>
+ <string name="bluetooth_pairing_error_message" msgid="3748157733635947087">"Nije moguće upariti s uređajem <xliff:g id="DEVICE_NAME">%1$s</xliff:g>."</string>
+ <string name="bluetooth_pairing_pin_error_message" msgid="8337234855188925274">"Nije moguće upariti s uređajem <xliff:g id="DEVICE_NAME">%1$s</xliff:g> zbog pogrešnog PIN-a ili pristupnog koda."</string>
+ <string name="bluetooth_pairing_device_down_error_message" msgid="7870998403045801381">"Nije moguće komunicirati s uređajem <xliff:g id="DEVICE_NAME">%1$s</xliff:g>."</string>
<string name="bluetooth_pairing_rejected_error_message" msgid="1648157108520832454">"Uređaj <xliff:g id="DEVICE_NAME">%1$s</xliff:g> je odbio uparivanje."</string>
<string name="bluetooth_talkback_computer" msgid="4875089335641234463">"Računar"</string>
<string name="bluetooth_talkback_headset" msgid="5140152177885220949">"Slušalice s mikrofonom"</string>
@@ -118,12 +118,12 @@
<string name="bluetooth_hearingaid_right_pairing_message" msgid="1550373802309160891">"Uparivanje desnog slušnog aparata…"</string>
<string name="bluetooth_hearingaid_left_battery_level" msgid="8797811465352097562">"Lijevi - <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> baterije"</string>
<string name="bluetooth_hearingaid_right_battery_level" msgid="7309476148173459677">"Desni - <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> baterije"</string>
- <string name="accessibility_wifi_off" msgid="1166761729660614716">"WiFi isključen."</string>
+ <string name="accessibility_wifi_off" msgid="1166761729660614716">"WiFi je isključen."</string>
<string name="accessibility_no_wifi" msgid="8834610636137374508">"WiFi nije povezan."</string>
- <string name="accessibility_wifi_one_bar" msgid="4869376278894301820">"WiFi jedna crtica."</string>
- <string name="accessibility_wifi_two_bars" msgid="3569851234710034416">"WiFi dvije crtice."</string>
- <string name="accessibility_wifi_three_bars" msgid="8134185644861380311">"WiFi tri crtice."</string>
- <string name="accessibility_wifi_signal_full" msgid="7061045677694702">"WiFi puni signal."</string>
+ <string name="accessibility_wifi_one_bar" msgid="4869376278894301820">"WiFi signal ima jednu crtu."</string>
+ <string name="accessibility_wifi_two_bars" msgid="3569851234710034416">"WiFi signal ima dvije crte."</string>
+ <string name="accessibility_wifi_three_bars" msgid="8134185644861380311">"WiFi signal ima tri crte."</string>
+ <string name="accessibility_wifi_signal_full" msgid="7061045677694702">"WiFi signal je pun."</string>
<string name="accessibility_wifi_security_type_none" msgid="1223747559986205423">"Otvorena mreža"</string>
<string name="accessibility_wifi_security_type_secured" msgid="862921720418885331">"Sigurna mreža"</string>
<string name="process_kernel_label" msgid="3916858646836739323">"Android OS"</string>
@@ -132,7 +132,7 @@
<string name="tether_settings_title_usb" msgid="6688416425801386511">"Povezivanje mobitela USB-om"</string>
<string name="tether_settings_title_wifi" msgid="3277144155960302049">"Prijenosna pristupna tačka"</string>
<string name="tether_settings_title_bluetooth" msgid="355855408317564420">"Dijeljenje Bluetooth veze"</string>
- <string name="tether_settings_title_usb_bluetooth" msgid="5355828977109785001">"Dijeljenje veze"</string>
+ <string name="tether_settings_title_usb_bluetooth" msgid="5355828977109785001">"Povezivanje putem mobitela"</string>
<string name="tether_settings_title_all" msgid="8356136101061143841">"Povezivanje putem mobitela i prijenosna pristupna tačka"</string>
<string name="managed_user_title" msgid="8109605045406748842">"Sve radne aplikacije"</string>
<string name="user_guest" msgid="8475274842845401871">"Gost"</string>
@@ -145,7 +145,7 @@
<string name="tts_default_rate_title" msgid="6030550998379310088">"Brzina govora"</string>
<string name="tts_default_rate_summary" msgid="4061815292287182801">"Brzina kojom se izgovara tekst"</string>
<string name="tts_default_pitch_title" msgid="6135942113172488671">"Visina"</string>
- <string name="tts_default_pitch_summary" msgid="1944885882882650009">"Utječe na ton sintetiziranog govora"</string>
+ <string name="tts_default_pitch_summary" msgid="1944885882882650009">"Utiče na ton sintetiziranog govora"</string>
<string name="tts_default_lang_title" msgid="8018087612299820556">"Jezik"</string>
<string name="tts_lang_use_system" msgid="2679252467416513208">"Korištenje sistemskog jezika"</string>
<string name="tts_lang_not_selected" msgid="7395787019276734765">"Jezik nije izabran"</string>
@@ -187,7 +187,7 @@
<string name="development_settings_summary" msgid="1815795401632854041">"Postavi opcije za razvoj aplikacija"</string>
<string name="development_settings_not_available" msgid="4308569041701535607">"Opcije za programere nisu dostupne za ovog korisnika"</string>
<string name="vpn_settings_not_available" msgid="956841430176985598">"VPN postavke nisu dostupne za ovog korisnika"</string>
- <string name="tethering_settings_not_available" msgid="6765770438438291012">"Postavke za privezivanje nisu dostupne za ovog korisnika"</string>
+ <string name="tethering_settings_not_available" msgid="6765770438438291012">"Postavke za povezivanje putem mobitela nisu dostupne za ovog korisnika"</string>
<string name="apn_settings_not_available" msgid="7873729032165324000">"Postavke za ime pristupne tačke nisu dostupne za ovog korisnika"</string>
<string name="enable_adb" msgid="7982306934419797485">"Otklanjanje grešaka putem uređaja spojenog na USB"</string>
<string name="enable_adb_summary" msgid="4881186971746056635">"Način rada za uklanjanje grešaka kada je povezan USB"</string>
@@ -201,7 +201,7 @@
<string name="oem_unlock_enable" msgid="6040763321967327691">"OEM otključavanje"</string>
<string name="oem_unlock_enable_summary" msgid="4720281828891618376">"Dozvoli otključavanje bootloadera"</string>
<string name="confirm_enable_oem_unlock_title" msgid="4802157344812385674">"Želite li dozvoliti OEM otključavanje?"</string>
- <string name="confirm_enable_oem_unlock_text" msgid="5517144575601647022">"UPOZORENJE: Funkcije zaštite ovog uređaja neće funkcionisati dok je ova postavka uključena."</string>
+ <string name="confirm_enable_oem_unlock_text" msgid="5517144575601647022">"UPOZORENJE: Funkcije zaštite ovog uređaja neće funkcionirati dok je ova postavka uključena."</string>
<string name="mock_location_app" msgid="7966220972812881854">"Odaberite aplikaciju za lažne lokacije"</string>
<string name="mock_location_app_not_set" msgid="809543285495344223">"Aplikacija za lažnu lokaciju nije postavljena"</string>
<string name="mock_location_app_set" msgid="8966420655295102685">"Aplikacija za lažne lokacije: <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
@@ -210,7 +210,7 @@
<string name="wifi_verbose_logging" msgid="4203729756047242344">"Omogući detaljniju evidenciju za WiFi"</string>
<string name="wifi_connected_mac_randomization" msgid="3168165236877957767">"Nasumični odabir MAC adrese pri povezivanju"</string>
<string name="mobile_data_always_on" msgid="8774857027458200434">"Mobilna mreža za prijenos podataka je uvijek aktivna"</string>
- <string name="tethering_hardware_offload" msgid="7470077827090325814">"Hardversko ubrzavanje dijeljenja veze"</string>
+ <string name="tethering_hardware_offload" msgid="7470077827090325814">"Hardversko ubrzavanje za povezivanje putem mobitela"</string>
<string name="bluetooth_show_devices_without_names" msgid="4708446092962060176">"Prikaži Bluetooth uređaje bez naziva"</string>
<string name="bluetooth_disable_absolute_volume" msgid="2660673801947898809">"Onemogući apsolutnu jačinu zvuka"</string>
<string name="bluetooth_select_avrcp_version_string" msgid="3750059931120293633">"Bluetooth AVRCP verzija"</string>
@@ -220,7 +220,7 @@
<string name="bluetooth_select_a2dp_codec_sample_rate" msgid="4788245703824623062">"Brzina uzorkovanja za Bluetooth audio"</string>
<string name="bluetooth_select_a2dp_codec_sample_rate_dialog_title" msgid="8010380028880963535">"Aktivirajte Bluetooth Audio Codec\nOdabir: Brzina uzorkovanja"</string>
<string name="bluetooth_select_a2dp_codec_bits_per_sample" msgid="2099645202720164141">"Bluetooth audio bitovi po uzorku"</string>
- <string name="bluetooth_select_a2dp_codec_bits_per_sample_dialog_title" msgid="8063859754619484760">"Aktivirajte Bluetooth Audio Codec\nOdabir: Bitovi po semplu"</string>
+ <string name="bluetooth_select_a2dp_codec_bits_per_sample_dialog_title" msgid="8063859754619484760">"Aktivirajte Bluetooth Audio Codec\nOdabir: Bitovi po uzorku"</string>
<string name="bluetooth_select_a2dp_codec_channel_mode" msgid="884855779449390540">"Način Bluetooth audio kanala"</string>
<string name="bluetooth_select_a2dp_codec_channel_mode_dialog_title" msgid="7234956835280563341">"Aktivirajte Bluetooth Audio Codec\nOdabir: Način rada po kanalima"</string>
<string name="bluetooth_select_a2dp_codec_ldac_playback_quality" msgid="3619694372407843405">"Bluetooth Audio LDAC kodek: Kvalitet reprodukcije"</string>
@@ -249,7 +249,7 @@
<string name="allow_mock_location" msgid="2787962564578664888">"Dozvoli lažne lokacije"</string>
<string name="allow_mock_location_summary" msgid="317615105156345626">"Dozvoli lažne lokacije"</string>
<string name="debug_view_attributes" msgid="6485448367803310384">"Omogući pregled atributa prikaza"</string>
- <string name="mobile_data_always_on_summary" msgid="8149773901431697910">"Uvijek drži prijenos podataka na mobilnoj mreži aktivnim, čak i kada je WiFi je aktivan (za brzo prebacivanje između mreža)."</string>
+ <string name="mobile_data_always_on_summary" msgid="8149773901431697910">"Uvijek drži prijenos podataka na mobilnoj mreži aktivnim, čak i kada je WiFi aktivan (za brzo prebacivanje između mreža)."</string>
<string name="tethering_hardware_offload_summary" msgid="7726082075333346982">"Koristi hardversko ubrzavanje dijeljenja veze, ako je dostupno"</string>
<string name="adb_warning_title" msgid="6234463310896563253">"Omogućiti otklanjanje grešaka putem uređaja spojenog na USB?"</string>
<string name="adb_warning_message" msgid="7316799925425402244">"Otklanjanje grešaka putem uređaja spojenog na USB je namijenjeno samo u svrhe razvoja aplikacija. Koristite ga za kopiranje podataka između računara i uređaja, instaliranje aplikacija na uređaj bez obavještenja te čitanje podataka iz zapisnika."</string>
@@ -277,7 +277,7 @@
<string name="debug_hw_drawing_category" msgid="6220174216912308658">"Prikaz s hardverskom akceleracijom"</string>
<string name="media_category" msgid="4388305075496848353">"Mediji"</string>
<string name="debug_monitoring_category" msgid="7640508148375798343">"Praćenje"</string>
- <string name="strict_mode" msgid="1938795874357830695">"Omogućen strogi režim"</string>
+ <string name="strict_mode" msgid="1938795874357830695">"Omogućen strogi način rada"</string>
<string name="strict_mode_summary" msgid="142834318897332338">"Prikaži ekran uz treptanje kada aplikacije vrše duge operacije u glavnoj niti"</string>
<string name="pointer_location" msgid="6084434787496938001">"Lokacija pokazivača"</string>
<string name="pointer_location_summary" msgid="840819275172753713">"Trenutni podaci o dodirivanju prikazuju se u nadsloju preko ekrana"</string>
@@ -298,8 +298,8 @@
<string name="usb_audio_disable_routing_summary" msgid="980282760277312264">"Onemogući autom. usmjerav. na USB audio periferije"</string>
<string name="debug_layout" msgid="5981361776594526155">"Prikaži granice rasporeda"</string>
<string name="debug_layout_summary" msgid="2001775315258637682">"Prikaži granice isječka, margine itd."</string>
- <string name="force_rtl_layout_all_locales" msgid="2259906643093138978">"Prisilno postavi raspored s desna u lijevo"</string>
- <string name="force_rtl_layout_all_locales_summary" msgid="9192797796616132534">"Prisilno postavi raspored ekrana s desna u lijevo za sve regije"</string>
+ <string name="force_rtl_layout_all_locales" msgid="2259906643093138978">"Prisilno postavi raspored s desna ulijevo"</string>
+ <string name="force_rtl_layout_all_locales_summary" msgid="9192797796616132534">"Prisilno postavi raspored ekrana s desna ulijevo za sve regije"</string>
<string name="force_msaa" msgid="7920323238677284387">"Prinudno primijeni 4x MSAA"</string>
<string name="force_msaa_summary" msgid="9123553203895817537">"Omogući 4x MSAA u OpenGL ES 2.0 aplikacijama"</string>
<string name="show_non_rect_clip" msgid="505954950474595172">"Ispravi greške na nepravougaonim operacijama isjecanja"</string>
@@ -321,19 +321,19 @@
<string name="force_allow_on_external" msgid="3215759785081916381">"Nametni aplikacije na vanjskoj pohrani"</string>
<string name="force_allow_on_external_summary" msgid="3640752408258034689">"Omogućava upisivanje svih aplikacija u vanjsku pohranu, bez obzira na prikazane vrijednosti"</string>
<string name="force_resizable_activities" msgid="8615764378147824985">"Nametni aktivnostima mijenjanje veličina"</string>
- <string name="force_resizable_activities_summary" msgid="6667493494706124459">"Omogući mijenjanje veličine svih aktivnosti za prikaz sa više prozora, bez obzira na prikazane vrijednosti."</string>
+ <string name="force_resizable_activities_summary" msgid="6667493494706124459">"Omogući mijenjanje veličine svih aktivnosti za prikaz s više prozora, bez obzira na prikazane vrijednosti."</string>
<string name="enable_freeform_support" msgid="1461893351278940416">"Omogući prozore nepravilnih oblika"</string>
<string name="enable_freeform_support_summary" msgid="8247310463288834487">"Omogući podršku za eksperimentalne prozore nepravilnih oblika."</string>
<string name="local_backup_password_title" msgid="3860471654439418822">"Lozinka za sigurnosnu kopiju radne površine"</string>
<string name="local_backup_password_summary_none" msgid="6951095485537767956">"Potpune sigurnosne kopije za računare trenutno nisu zaštićene"</string>
- <string name="local_backup_password_summary_change" msgid="5376206246809190364">"Dodirnite da promijenite ili uklonite lozinku za potpune rezervne kopije sa radne površine"</string>
- <string name="local_backup_password_toast_success" msgid="582016086228434290">"Nova lozinka za sigurnosnu kopiju postavljena"</string>
+ <string name="local_backup_password_summary_change" msgid="5376206246809190364">"Dodirnite da promijenite ili uklonite lozinku za potpune rezervne kopije s radne površine"</string>
+ <string name="local_backup_password_toast_success" msgid="582016086228434290">"Nova lozinka za sigurnosnu kopiju je postavljena"</string>
<string name="local_backup_password_toast_confirmation_mismatch" msgid="7805892532752708288">"Nova lozinka i potvrda se ne podudaraju"</string>
<string name="local_backup_password_toast_validation_failure" msgid="5646377234895626531">"Nije uspjelo postavljanje lozinke za sigurnosnu kopiju"</string>
<string-array name="color_mode_names">
- <item msgid="2425514299220523812">"Živopisan (zadano)"</item>
+ <item msgid="2425514299220523812">"Živopisno (zadano)"</item>
<item msgid="8446070607501413455">"Prirodan"</item>
- <item msgid="6553408765810699025">"Standardni"</item>
+ <item msgid="6553408765810699025">"Standardno"</item>
</string-array>
<string-array name="color_mode_descriptions">
<item msgid="4979629397075120893">"Unaprijeđene boje"</item>
@@ -353,9 +353,9 @@
<string name="convert_to_file_encryption_enabled" msgid="2861258671151428346">"Pretvaranje…"</string>
<string name="convert_to_file_encryption_done" msgid="7859766358000523953">"Fajl je već šifriran"</string>
<string name="title_convert_fbe" msgid="1263622876196444453">"Pretvaranje u šifrirane fajlove"</string>
- <string name="convert_to_fbe_warning" msgid="6139067817148865527">"Pretvorite particiju sa podacima u particiju šifriranu sistemom fajlova.\n !! Upozorenje!! Ovo će izbrisati sve vaše podatke.\n Ova funkcija je u alfa fazi razvoja i možda neće ispravno raditi.\n Pritisnite \"Obriši i pretvori…\" da nastavite."</string>
+ <string name="convert_to_fbe_warning" msgid="6139067817148865527">"Pretvorite particiju s podacima u particiju šifriranu sistemom fajlova.\n !! Upozorenje!! Ovo će izbrisati sve vaše podatke.\n Ova funkcija je u alfa fazi razvoja i možda neće ispravno raditi.\n Pritisnite \"Obriši i pretvori…\" da nastavite."</string>
<string name="button_convert_fbe" msgid="5152671181309826405">"Obriši i pretvori…"</string>
- <string name="picture_color_mode" msgid="4560755008730283695">"Režim boja Slika"</string>
+ <string name="picture_color_mode" msgid="4560755008730283695">"Način rada boja slika"</string>
<string name="picture_color_mode_desc" msgid="1141891467675548590">"Koristi sRGB"</string>
<string name="daltonizer_mode_disabled" msgid="7482661936053801862">"Onemogućeno"</string>
<string name="daltonizer_mode_monochromacy" msgid="8485709880666106721">"Crno-bijelo"</string>
@@ -422,8 +422,8 @@
<string name="retail_demo_reset_title" msgid="696589204029930100">"Potrebna je lozinka"</string>
<string name="active_input_method_subtypes" msgid="3596398805424733238">"Aktivne metode unosa"</string>
<string name="use_system_language_to_select_input_method_subtypes" msgid="5747329075020379587">"Koristi jezik sistema"</string>
- <string name="failed_to_open_app_settings_toast" msgid="1251067459298072462">"Nije uspjelo otvaranje postavki za <xliff:g id="SPELL_APPLICATION_NAME">%1$s</xliff:g>"</string>
- <string name="ime_security_warning" msgid="4135828934735934248">"Ovaj način unosa može prikupiti sav tekst koji otkucate, uključujući lične podatke kao što su lozinke i brojevi kreditnih kartica. Način omogućava aplikacija <xliff:g id="IME_APPLICATION_NAME">%1$s</xliff:g>. Da li želite koristiti ovaj način unosa?"</string>
+ <string name="failed_to_open_app_settings_toast" msgid="1251067459298072462">"Otvaranje postavki za <xliff:g id="SPELL_APPLICATION_NAME">%1$s</xliff:g> nije uspjelo"</string>
+ <string name="ime_security_warning" msgid="4135828934735934248">"Ovaj način unosa može prikupiti sav tekst koji upišete, uključujući lične podatke kao što su lozinke i brojevi kreditnih kartica. Način omogućava aplikacija <xliff:g id="IME_APPLICATION_NAME">%1$s</xliff:g>. Da li želite koristiti ovaj način unosa?"</string>
<string name="direct_boot_unaware_dialog_message" msgid="7870273558547549125">"Napomena: Nakon ponovnog pokretanja, ova aplikacija se neće moći pokrenuti dok ne otključate telefon"</string>
<string name="ims_reg_title" msgid="7609782759207241443">"Stanje IMS registracije"</string>
<string name="ims_reg_status_registered" msgid="933003316932739188">"Registrirano"</string>
diff --git a/packages/SettingsLib/res/values-es/strings.xml b/packages/SettingsLib/res/values-es/strings.xml
index e9b07a4..f04767b 100644
--- a/packages/SettingsLib/res/values-es/strings.xml
+++ b/packages/SettingsLib/res/values-es/strings.xml
@@ -217,8 +217,8 @@
<string name="bluetooth_select_avrcp_version_dialog_title" msgid="7277329668298705702">"Selecciona la versión AVRCP del Bluetooth"</string>
<string name="bluetooth_select_a2dp_codec_type" msgid="90597356942154882">"Códec de audio de Bluetooth"</string>
<string name="bluetooth_select_a2dp_codec_type_dialog_title" msgid="8436224899475822557">"Activar el códec de audio por Bluetooth\nSelección"</string>
- <string name="bluetooth_select_a2dp_codec_sample_rate" msgid="4788245703824623062">"Porcentaje de muestreo de audio por Bluetooth"</string>
- <string name="bluetooth_select_a2dp_codec_sample_rate_dialog_title" msgid="8010380028880963535">"Activar el códec de audio por Bluetooth\nSelección: porcentaje de muestreo"</string>
+ <string name="bluetooth_select_a2dp_codec_sample_rate" msgid="4788245703824623062">"Frecuencia de muestreo de audio por Bluetooth"</string>
+ <string name="bluetooth_select_a2dp_codec_sample_rate_dialog_title" msgid="8010380028880963535">"Activar el códec de audio por Bluetooth\nSelección: frecuencia de muestreo"</string>
<string name="bluetooth_select_a2dp_codec_bits_per_sample" msgid="2099645202720164141">"Bits por muestra del audio Bluetooth"</string>
<string name="bluetooth_select_a2dp_codec_bits_per_sample_dialog_title" msgid="8063859754619484760">"Activar el códec de audio por Bluetooth\nSelección: bits por muestra"</string>
<string name="bluetooth_select_a2dp_codec_channel_mode" msgid="884855779449390540">"Modo de canal de audio por Bluetooth"</string>
@@ -238,7 +238,7 @@
<string name="wifi_connected_mac_randomization_summary" msgid="1743059848752201485">"Ordenar las direcciones MAC de forma aleatoria al conectarse a redes Wi‑Fi"</string>
<string name="wifi_metered_label" msgid="4514924227256839725">"Medida"</string>
<string name="wifi_unmetered_label" msgid="6124098729457992931">"No medida"</string>
- <string name="select_logd_size_title" msgid="7433137108348553508">"Tamaños de búfer de registrador"</string>
+ <string name="select_logd_size_title" msgid="7433137108348553508">"Tamaños del búfer para registrar"</string>
<string name="select_logd_size_dialog_title" msgid="1206769310236476760">"Elige el tamaño del Logger por búfer"</string>
<string name="dev_logpersist_clear_warning_title" msgid="684806692440237967">"¿Borrar almacenamiento continuo del registrador?"</string>
<string name="dev_logpersist_clear_warning_message" msgid="2256582531342994562">"Cuando ya no supervisamos la actividad con el registrador de forma continua, estamos obligados a borrar los datos del registrador almacenados en el dispositivo."</string>
diff --git a/packages/SettingsLib/res/values-fa/strings.xml b/packages/SettingsLib/res/values-fa/strings.xml
index 7dfd429..447ce3c 100644
--- a/packages/SettingsLib/res/values-fa/strings.xml
+++ b/packages/SettingsLib/res/values-fa/strings.xml
@@ -159,7 +159,7 @@
<string name="tts_default_sample_string" msgid="4040835213373086322">"این نمونهای از ترکیب گفتار است"</string>
<string name="tts_status_title" msgid="7268566550242584413">"وضعیت زبان پیشفرض"</string>
<string name="tts_status_ok" msgid="1309762510278029765">"<xliff:g id="LOCALE">%1$s</xliff:g> کاملاً پشتیبانی میشود"</string>
- <string name="tts_status_requires_network" msgid="6042500821503226892">"<xliff:g id="LOCALE">%1$s</xliff:g> به اتصال شبکه نیاز دارد"</string>
+ <string name="tts_status_requires_network" msgid="6042500821503226892">"<xliff:g id="LOCALE">%1$s</xliff:g> باید اتصال شبکه داشته باشد"</string>
<string name="tts_status_not_supported" msgid="4491154212762472495">"<xliff:g id="LOCALE">%1$s</xliff:g> پشتیبانی نمیشود"</string>
<string name="tts_status_checking" msgid="5339150797940483592">"در حال بررسی…"</string>
<string name="tts_engine_settings_title" msgid="3499112142425680334">"تنظیمات برای <xliff:g id="TTS_ENGINE_NAME">%s</xliff:g>"</string>
diff --git a/packages/SettingsLib/res/values-gl/arrays.xml b/packages/SettingsLib/res/values-gl/arrays.xml
index c6c4a2e..f8a69c2 100644
--- a/packages/SettingsLib/res/values-gl/arrays.xml
+++ b/packages/SettingsLib/res/values-gl/arrays.xml
@@ -207,12 +207,12 @@
</string-array>
<string-array name="overlay_display_devices_entries">
<item msgid="1606809880904982133">"Ningunha"</item>
- <item msgid="9033194758688161545">"480 p"</item>
- <item msgid="1025306206556583600">"480 p (seguro)"</item>
+ <item msgid="9033194758688161545">"480p"</item>
+ <item msgid="1025306206556583600">"480p (seguro)"</item>
<item msgid="1853913333042744661">"720p"</item>
<item msgid="3414540279805870511">"720p (seguro)"</item>
- <item msgid="9039818062847141551">"1080 p"</item>
- <item msgid="4939496949750174834">"1080 p (seguro)"</item>
+ <item msgid="9039818062847141551">"1080p"</item>
+ <item msgid="4939496949750174834">"1080p (seguro)"</item>
<item msgid="1833612718524903568">"4K"</item>
<item msgid="238303513127879234">"4K (seguro)"</item>
<item msgid="3547211260846843098">"4K (mellorado)"</item>
diff --git a/packages/SettingsLib/res/values-gl/strings.xml b/packages/SettingsLib/res/values-gl/strings.xml
index 4f26f6a..3e55dc3 100644
--- a/packages/SettingsLib/res/values-gl/strings.xml
+++ b/packages/SettingsLib/res/values-gl/strings.xml
@@ -110,7 +110,7 @@
<string name="bluetooth_talkback_computer" msgid="4875089335641234463">"Ordenador"</string>
<string name="bluetooth_talkback_headset" msgid="5140152177885220949">"Auriculares con micrófono"</string>
<string name="bluetooth_talkback_phone" msgid="4260255181240622896">"Teléfono"</string>
- <string name="bluetooth_talkback_imaging" msgid="551146170554589119">"Imaxes"</string>
+ <string name="bluetooth_talkback_imaging" msgid="551146170554589119">"Dispositivo de imaxe"</string>
<string name="bluetooth_talkback_headphone" msgid="26580326066627664">"Auriculares"</string>
<string name="bluetooth_talkback_input_peripheral" msgid="5165842622743212268">"Periférico de entrada"</string>
<string name="bluetooth_talkback_bluetooth" msgid="5615463912185280812">"Bluetooth"</string>
@@ -213,8 +213,8 @@
<string name="tethering_hardware_offload" msgid="7470077827090325814">"Aceleración de hardware para conexión compartida"</string>
<string name="bluetooth_show_devices_without_names" msgid="4708446092962060176">"Mostrar dispositivos Bluetooth sen nomes"</string>
<string name="bluetooth_disable_absolute_volume" msgid="2660673801947898809">"Desactivar volume absoluto"</string>
- <string name="bluetooth_select_avrcp_version_string" msgid="3750059931120293633">"Versión AVRCP de Bluetooth"</string>
- <string name="bluetooth_select_avrcp_version_dialog_title" msgid="7277329668298705702">"Selecciona a versión AVRCP de Bluetooth"</string>
+ <string name="bluetooth_select_avrcp_version_string" msgid="3750059931120293633">"Versión de Bluetooth AVRCP"</string>
+ <string name="bluetooth_select_avrcp_version_dialog_title" msgid="7277329668298705702">"Selecciona a versión de Bluetooth AVRCP"</string>
<string name="bluetooth_select_a2dp_codec_type" msgid="90597356942154882">"Códec de audio por Bluetooth"</string>
<string name="bluetooth_select_a2dp_codec_type_dialog_title" msgid="8436224899475822557">"Activar códec de audio por Bluetooth\nSelección"</string>
<string name="bluetooth_select_a2dp_codec_sample_rate" msgid="4788245703824623062">"Taxa de mostraxe de audio por Bluetooth"</string>
@@ -353,8 +353,8 @@
<string name="convert_to_file_encryption_enabled" msgid="2861258671151428346">"Converter..."</string>
<string name="convert_to_file_encryption_done" msgid="7859766358000523953">"Xa se encriptou o ficheiro"</string>
<string name="title_convert_fbe" msgid="1263622876196444453">"Convertendo no encriptado baseado en ficheiros"</string>
- <string name="convert_to_fbe_warning" msgid="6139067817148865527">"Converte a partición de datos nunha encriptación baseada en ficheiros.\n Advertencia: Esta acción borrará todos os datos.\n Esta función é alfa e quizais non funcione correctamente.\n Para continuar, toca Limpar e converter..."</string>
- <string name="button_convert_fbe" msgid="5152671181309826405">"Limpar e converter..."</string>
+ <string name="convert_to_fbe_warning" msgid="6139067817148865527">"Converte a partición de datos nunha encriptación baseada en ficheiros.\n Advertencia: Esta acción borrará todos os datos.\n Esta función é alfa e quizais non funcione correctamente.\n Para continuar, toca Borrar e converter..."</string>
+ <string name="button_convert_fbe" msgid="5152671181309826405">"Borrar e converter..."</string>
<string name="picture_color_mode" msgid="4560755008730283695">"Modo de cor da imaxe"</string>
<string name="picture_color_mode_desc" msgid="1141891467675548590">"Utiliza sRGB"</string>
<string name="daltonizer_mode_disabled" msgid="7482661936053801862">"Desactivado"</string>
diff --git a/packages/SettingsLib/res/values-ja/strings.xml b/packages/SettingsLib/res/values-ja/strings.xml
index 2c43d33..b2a6bd0 100644
--- a/packages/SettingsLib/res/values-ja/strings.xml
+++ b/packages/SettingsLib/res/values-ja/strings.xml
@@ -141,7 +141,7 @@
<string name="launch_defaults_some" msgid="313159469856372621">"一部デフォルトで設定"</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_settings_title" msgid="1237820681016639683">"テキスト読み上げの設定"</string>
<string name="tts_default_rate_title" msgid="6030550998379310088">"音声の速度"</string>
<string name="tts_default_rate_summary" msgid="4061815292287182801">"テキストの読み上げ速度"</string>
<string name="tts_default_pitch_title" msgid="6135942113172488671">"音の高さ"</string>
diff --git a/packages/SettingsLib/res/values-nb/strings.xml b/packages/SettingsLib/res/values-nb/strings.xml
index 7f9f4a6..a3293e5 100644
--- a/packages/SettingsLib/res/values-nb/strings.xml
+++ b/packages/SettingsLib/res/values-nb/strings.xml
@@ -307,7 +307,7 @@
<string name="enable_gpu_debug_layers" msgid="3848838293793255097">"Slå på GPU-feilsøkingslag"</string>
<string name="enable_gpu_debug_layers_summary" msgid="8009136940671194940">"Tillat GPU-feilsøkingslag for feilsøkingsapper"</string>
<string name="window_animation_scale_title" msgid="6162587588166114700">"Animasjonsskala for vindu"</string>
- <string name="transition_animation_scale_title" msgid="387527540523595875">"Overgangsanimasjonsskala"</string>
+ <string name="transition_animation_scale_title" msgid="387527540523595875">"Animasjonsskala for overgang"</string>
<string name="animator_duration_scale_title" msgid="3406722410819934083">"Varighetsskala for animasjon"</string>
<string name="overlay_display_devices_title" msgid="5364176287998398539">"Simulering av sekundærskjermer"</string>
<string name="debug_applications_category" msgid="4206913653849771549">"Apper"</string>
diff --git a/packages/SettingsLib/res/values-pl/strings.xml b/packages/SettingsLib/res/values-pl/strings.xml
index 7ec97b5..e472b15 100644
--- a/packages/SettingsLib/res/values-pl/strings.xml
+++ b/packages/SettingsLib/res/values-pl/strings.xml
@@ -194,7 +194,7 @@
<string name="clear_adb_keys" msgid="4038889221503122743">"Odwołaj dostęp do debugowania USB"</string>
<string name="bugreport_in_power" msgid="7923901846375587241">"Skrót do zgłoszenia błędu"</string>
<string name="bugreport_in_power_summary" msgid="1778455732762984579">"Pokaż w menu zasilania przycisk zgłaszania błędu"</string>
- <string name="keep_screen_on" msgid="1146389631208760344">"Pozostaw ekran włączony"</string>
+ <string name="keep_screen_on" msgid="1146389631208760344">"Pozostaw włączony ekran"</string>
<string name="keep_screen_on_summary" msgid="2173114350754293009">"Ekran nie będzie gaszony podczas ładowania telefonu"</string>
<string name="bt_hci_snoop_log" msgid="3340699311158865670">"Włącz dziennik snoop Bluetooth HCI"</string>
<string name="bt_hci_snoop_log_summary" msgid="366083475849911315">"Przechwyć wszystkie pakiety Bluetooth HCI do pliku (przełącz Bluetooth po zmianie tego ustawienia)"</string>
diff --git a/packages/SettingsLib/res/values-pt-rBR/arrays.xml b/packages/SettingsLib/res/values-pt-rBR/arrays.xml
index dfdc09c..563698a 100644
--- a/packages/SettingsLib/res/values-pt-rBR/arrays.xml
+++ b/packages/SettingsLib/res/values-pt-rBR/arrays.xml
@@ -160,11 +160,11 @@
</string-array>
<string-array name="select_logd_size_summaries">
<item msgid="6921048829791179331">"Desativado"</item>
- <item msgid="2969458029344750262">"64 K/buffer de log"</item>
- <item msgid="1342285115665698168">"256 K/buffer de log"</item>
- <item msgid="1314234299552254621">"1 M/buffer de log"</item>
- <item msgid="3606047780792894151">"4 M/buffer de log"</item>
- <item msgid="5431354956856655120">"16 M/buffer de log"</item>
+ <item msgid="2969458029344750262">"64 K/buffer de registro"</item>
+ <item msgid="1342285115665698168">"256 K/buffer de registro"</item>
+ <item msgid="1314234299552254621">"1 M/buffer de registro"</item>
+ <item msgid="3606047780792894151">"4 M/buffer de registro"</item>
+ <item msgid="5431354956856655120">"16 M/buffer de registro"</item>
</string-array>
<string-array name="select_logpersist_titles">
<item msgid="1744840221860799971">"Desativado"</item>
diff --git a/packages/SettingsLib/res/values-pt-rBR/strings.xml b/packages/SettingsLib/res/values-pt-rBR/strings.xml
index dd623d0..98b877be 100644
--- a/packages/SettingsLib/res/values-pt-rBR/strings.xml
+++ b/packages/SettingsLib/res/values-pt-rBR/strings.xml
@@ -196,7 +196,7 @@
<string name="bugreport_in_power_summary" msgid="1778455732762984579">"Mostrar um botão para gerar relatórios de bugs no menu do botão liga/desliga"</string>
<string name="keep_screen_on" msgid="1146389631208760344">"Permanecer ativo"</string>
<string name="keep_screen_on_summary" msgid="2173114350754293009">"A tela nunca entrará em suspensão enquanto estiver carregando."</string>
- <string name="bt_hci_snoop_log" msgid="3340699311158865670">"Ativar log de rastreamento Bluetooth HCI"</string>
+ <string name="bt_hci_snoop_log" msgid="3340699311158865670">"Ativar registro de rastreamento Bluetooth HCI"</string>
<string name="bt_hci_snoop_log_summary" msgid="366083475849911315">"Capturar todos os pacotes Bluetooth HCI em um arquivo (ative o Bluetooth depois de alterar esta configuração)"</string>
<string name="oem_unlock_enable" msgid="6040763321967327691">"Desbloqueio de OEM"</string>
<string name="oem_unlock_enable_summary" msgid="4720281828891618376">"Permitir que o bootloader seja desbloqueado"</string>
@@ -239,7 +239,7 @@
<string name="wifi_metered_label" msgid="4514924227256839725">"Limitada"</string>
<string name="wifi_unmetered_label" msgid="6124098729457992931">"Ilimitada"</string>
<string name="select_logd_size_title" msgid="7433137108348553508">"Tamanhos de buffer de logger"</string>
- <string name="select_logd_size_dialog_title" msgid="1206769310236476760">"Sel. tam. de logger/buffer de log"</string>
+ <string name="select_logd_size_dialog_title" msgid="1206769310236476760">"Sel. tam. de logger/buffer de registro"</string>
<string name="dev_logpersist_clear_warning_title" msgid="684806692440237967">"Limpar armazenamento de logger constante?"</string>
<string name="dev_logpersist_clear_warning_message" msgid="2256582531342994562">"Quando não estivermos mais monitorando com o logger constante, devemos limpar o residente de dados de logger do seu dispositivo."</string>
<string name="select_logpersist_title" msgid="7530031344550073166">"Armazenar dados de logger constantemente no dispositivo"</string>
diff --git a/packages/SettingsLib/res/values-pt/arrays.xml b/packages/SettingsLib/res/values-pt/arrays.xml
index dfdc09c..563698a 100644
--- a/packages/SettingsLib/res/values-pt/arrays.xml
+++ b/packages/SettingsLib/res/values-pt/arrays.xml
@@ -160,11 +160,11 @@
</string-array>
<string-array name="select_logd_size_summaries">
<item msgid="6921048829791179331">"Desativado"</item>
- <item msgid="2969458029344750262">"64 K/buffer de log"</item>
- <item msgid="1342285115665698168">"256 K/buffer de log"</item>
- <item msgid="1314234299552254621">"1 M/buffer de log"</item>
- <item msgid="3606047780792894151">"4 M/buffer de log"</item>
- <item msgid="5431354956856655120">"16 M/buffer de log"</item>
+ <item msgid="2969458029344750262">"64 K/buffer de registro"</item>
+ <item msgid="1342285115665698168">"256 K/buffer de registro"</item>
+ <item msgid="1314234299552254621">"1 M/buffer de registro"</item>
+ <item msgid="3606047780792894151">"4 M/buffer de registro"</item>
+ <item msgid="5431354956856655120">"16 M/buffer de registro"</item>
</string-array>
<string-array name="select_logpersist_titles">
<item msgid="1744840221860799971">"Desativado"</item>
diff --git a/packages/SettingsLib/res/values-pt/strings.xml b/packages/SettingsLib/res/values-pt/strings.xml
index dd623d0..98b877be 100644
--- a/packages/SettingsLib/res/values-pt/strings.xml
+++ b/packages/SettingsLib/res/values-pt/strings.xml
@@ -196,7 +196,7 @@
<string name="bugreport_in_power_summary" msgid="1778455732762984579">"Mostrar um botão para gerar relatórios de bugs no menu do botão liga/desliga"</string>
<string name="keep_screen_on" msgid="1146389631208760344">"Permanecer ativo"</string>
<string name="keep_screen_on_summary" msgid="2173114350754293009">"A tela nunca entrará em suspensão enquanto estiver carregando."</string>
- <string name="bt_hci_snoop_log" msgid="3340699311158865670">"Ativar log de rastreamento Bluetooth HCI"</string>
+ <string name="bt_hci_snoop_log" msgid="3340699311158865670">"Ativar registro de rastreamento Bluetooth HCI"</string>
<string name="bt_hci_snoop_log_summary" msgid="366083475849911315">"Capturar todos os pacotes Bluetooth HCI em um arquivo (ative o Bluetooth depois de alterar esta configuração)"</string>
<string name="oem_unlock_enable" msgid="6040763321967327691">"Desbloqueio de OEM"</string>
<string name="oem_unlock_enable_summary" msgid="4720281828891618376">"Permitir que o bootloader seja desbloqueado"</string>
@@ -239,7 +239,7 @@
<string name="wifi_metered_label" msgid="4514924227256839725">"Limitada"</string>
<string name="wifi_unmetered_label" msgid="6124098729457992931">"Ilimitada"</string>
<string name="select_logd_size_title" msgid="7433137108348553508">"Tamanhos de buffer de logger"</string>
- <string name="select_logd_size_dialog_title" msgid="1206769310236476760">"Sel. tam. de logger/buffer de log"</string>
+ <string name="select_logd_size_dialog_title" msgid="1206769310236476760">"Sel. tam. de logger/buffer de registro"</string>
<string name="dev_logpersist_clear_warning_title" msgid="684806692440237967">"Limpar armazenamento de logger constante?"</string>
<string name="dev_logpersist_clear_warning_message" msgid="2256582531342994562">"Quando não estivermos mais monitorando com o logger constante, devemos limpar o residente de dados de logger do seu dispositivo."</string>
<string name="select_logpersist_title" msgid="7530031344550073166">"Armazenar dados de logger constantemente no dispositivo"</string>
diff --git a/packages/SettingsLib/src/com/android/settingslib/CustomDialogPreferenceCompat.java b/packages/SettingsLib/src/com/android/settingslib/CustomDialogPreferenceCompat.java
new file mode 100644
index 0000000..6ac9d4e
--- /dev/null
+++ b/packages/SettingsLib/src/com/android/settingslib/CustomDialogPreferenceCompat.java
@@ -0,0 +1,129 @@
+/*
+ * Copyright (C) 2018 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;
+
+import android.app.Dialog;
+import android.content.Context;
+import android.content.DialogInterface;
+import android.os.Bundle;
+import android.util.AttributeSet;
+import android.view.View;
+
+import androidx.appcompat.app.AlertDialog;
+import androidx.preference.DialogPreference;
+import androidx.preference.PreferenceDialogFragmentCompat;
+
+public class CustomDialogPreferenceCompat extends DialogPreference {
+
+ private CustomPreferenceDialogFragment mFragment;
+ private DialogInterface.OnShowListener mOnShowListener;
+
+ public CustomDialogPreferenceCompat(Context context, AttributeSet attrs, int defStyleAttr,
+ int defStyleRes) {
+ super(context, attrs, defStyleAttr, defStyleRes);
+ }
+
+ public CustomDialogPreferenceCompat(Context context, AttributeSet attrs, int defStyleAttr) {
+ super(context, attrs, defStyleAttr);
+ }
+
+ public CustomDialogPreferenceCompat(Context context, AttributeSet attrs) {
+ super(context, attrs);
+ }
+
+ public CustomDialogPreferenceCompat(Context context) {
+ super(context);
+ }
+
+ public boolean isDialogOpen() {
+ return getDialog() != null && getDialog().isShowing();
+ }
+
+ public Dialog getDialog() {
+ return mFragment != null ? mFragment.getDialog() : null;
+ }
+
+ public void setOnShowListener(DialogInterface.OnShowListener listner) {
+ mOnShowListener = listner;
+ }
+
+ protected void onPrepareDialogBuilder(AlertDialog.Builder builder,
+ DialogInterface.OnClickListener listener) {
+ }
+
+ protected void onDialogClosed(boolean positiveResult) {
+ }
+
+ protected void onClick(DialogInterface dialog, int which) {
+ }
+
+ protected void onBindDialogView(View view) {
+ }
+
+ private void setFragment(CustomPreferenceDialogFragment fragment) {
+ mFragment = fragment;
+ }
+
+ private DialogInterface.OnShowListener getOnShowListener() {
+ return mOnShowListener;
+ }
+
+ public static class CustomPreferenceDialogFragment extends PreferenceDialogFragmentCompat {
+
+ public static CustomPreferenceDialogFragment newInstance(String key) {
+ final CustomPreferenceDialogFragment fragment = new CustomPreferenceDialogFragment();
+ final Bundle b = new Bundle(1);
+ b.putString(ARG_KEY, key);
+ fragment.setArguments(b);
+ return fragment;
+ }
+
+ private CustomDialogPreferenceCompat getCustomizablePreference() {
+ return (CustomDialogPreferenceCompat) getPreference();
+ }
+
+ @Override
+ protected void onPrepareDialogBuilder(AlertDialog.Builder builder) {
+ super.onPrepareDialogBuilder(builder);
+ getCustomizablePreference().setFragment(this);
+ getCustomizablePreference().onPrepareDialogBuilder(builder, this);
+ }
+
+ @Override
+ public void onDialogClosed(boolean positiveResult) {
+ getCustomizablePreference().onDialogClosed(positiveResult);
+ }
+
+ @Override
+ protected void onBindDialogView(View view) {
+ super.onBindDialogView(view);
+ getCustomizablePreference().onBindDialogView(view);
+ }
+
+ @Override
+ public Dialog onCreateDialog(Bundle savedInstanceState) {
+ final Dialog dialog = super.onCreateDialog(savedInstanceState);
+ dialog.setOnShowListener(getCustomizablePreference().getOnShowListener());
+ return dialog;
+ }
+
+ @Override
+ public void onClick(DialogInterface dialog, int which) {
+ super.onClick(dialog, which);
+ getCustomizablePreference().onClick(dialog, which);
+ }
+ }
+}
diff --git a/packages/SettingsLib/src/com/android/settingslib/CustomEditTextPreferenceCompat.java b/packages/SettingsLib/src/com/android/settingslib/CustomEditTextPreferenceCompat.java
new file mode 100644
index 0000000..6ddc89a
--- /dev/null
+++ b/packages/SettingsLib/src/com/android/settingslib/CustomEditTextPreferenceCompat.java
@@ -0,0 +1,136 @@
+/*
+ * Copyright (C) 2018 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;
+
+import static android.text.InputType.TYPE_CLASS_TEXT;
+import static android.text.InputType.TYPE_TEXT_FLAG_CAP_SENTENCES;
+
+import android.app.Dialog;
+import android.content.Context;
+import android.content.DialogInterface;
+import android.os.Bundle;
+import android.util.AttributeSet;
+import android.view.View;
+import android.widget.EditText;
+
+import androidx.annotation.CallSuper;
+import androidx.appcompat.app.AlertDialog;
+import androidx.preference.EditTextPreference;
+import androidx.preference.EditTextPreferenceDialogFragmentCompat;
+
+public class CustomEditTextPreferenceCompat extends EditTextPreference {
+
+ private CustomPreferenceDialogFragment mFragment;
+
+ public CustomEditTextPreferenceCompat(Context context, AttributeSet attrs, int defStyleAttr,
+ int defStyleRes) {
+ super(context, attrs, defStyleAttr, defStyleRes);
+ }
+
+ public CustomEditTextPreferenceCompat(Context context, AttributeSet attrs, int defStyleAttr) {
+ super(context, attrs, defStyleAttr);
+ }
+
+ public CustomEditTextPreferenceCompat(Context context, AttributeSet attrs) {
+ super(context, attrs);
+ }
+
+ public CustomEditTextPreferenceCompat(Context context) {
+ super(context);
+ }
+
+ public EditText getEditText() {
+ if (mFragment != null) {
+ final Dialog dialog = mFragment.getDialog();
+ if (dialog != null) {
+ return (EditText) dialog.findViewById(android.R.id.edit);
+ }
+ }
+ return null;
+ }
+
+ public boolean isDialogOpen() {
+ return getDialog() != null && getDialog().isShowing();
+ }
+
+ public Dialog getDialog() {
+ return mFragment != null ? mFragment.getDialog() : null;
+ }
+
+ protected void onPrepareDialogBuilder(AlertDialog.Builder builder,
+ DialogInterface.OnClickListener listener) {
+ }
+
+ protected void onDialogClosed(boolean positiveResult) {
+ }
+
+ protected void onClick(DialogInterface dialog, int which) {
+ }
+
+ @CallSuper
+ protected void onBindDialogView(View view) {
+ final EditText editText = view.findViewById(android.R.id.edit);
+ if (editText != null) {
+ editText.setInputType(TYPE_CLASS_TEXT | TYPE_TEXT_FLAG_CAP_SENTENCES);
+ editText.requestFocus();
+ }
+ }
+
+ private void setFragment(CustomPreferenceDialogFragment fragment) {
+ mFragment = fragment;
+ }
+
+ public static class CustomPreferenceDialogFragment extends
+ EditTextPreferenceDialogFragmentCompat {
+
+ public static CustomPreferenceDialogFragment newInstance(String key) {
+ final CustomPreferenceDialogFragment fragment = new CustomPreferenceDialogFragment();
+ final Bundle b = new Bundle(1);
+ b.putString(ARG_KEY, key);
+ fragment.setArguments(b);
+ return fragment;
+ }
+
+ private CustomEditTextPreferenceCompat getCustomizablePreference() {
+ return (CustomEditTextPreferenceCompat) getPreference();
+ }
+
+ @Override
+ protected void onBindDialogView(View view) {
+ super.onBindDialogView(view);
+ getCustomizablePreference().onBindDialogView(view);
+ }
+
+ @Override
+ protected void onPrepareDialogBuilder(AlertDialog.Builder builder) {
+ super.onPrepareDialogBuilder(builder);
+ getCustomizablePreference().setFragment(this);
+ getCustomizablePreference().onPrepareDialogBuilder(builder, this);
+ }
+
+ @Override
+ public void onDialogClosed(boolean positiveResult) {
+ super.onDialogClosed(positiveResult);
+ getCustomizablePreference().onDialogClosed(positiveResult);
+ }
+
+ @Override
+ public void onClick(DialogInterface dialog, int which) {
+ super.onClick(dialog, which);
+ getCustomizablePreference().onClick(dialog, which);
+ }
+ }
+}
diff --git a/packages/SettingsLib/src/com/android/settingslib/inputmethod/InputMethodAndSubtypeEnablerManagerCompat.java b/packages/SettingsLib/src/com/android/settingslib/inputmethod/InputMethodAndSubtypeEnablerManagerCompat.java
new file mode 100644
index 0000000..ad1368c
--- /dev/null
+++ b/packages/SettingsLib/src/com/android/settingslib/inputmethod/InputMethodAndSubtypeEnablerManagerCompat.java
@@ -0,0 +1,265 @@
+/*
+ * Copyright (C) 2018 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.inputmethod;
+
+import android.content.Context;
+import android.content.pm.PackageManager;
+import android.content.res.Configuration;
+import android.text.TextUtils;
+import android.view.inputmethod.InputMethodInfo;
+import android.view.inputmethod.InputMethodManager;
+import android.view.inputmethod.InputMethodSubtype;
+
+import com.android.settingslib.R;
+
+import java.text.Collator;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+
+import androidx.preference.Preference;
+import androidx.preference.PreferenceCategory;
+import androidx.preference.PreferenceFragmentCompat;
+import androidx.preference.PreferenceScreen;
+import androidx.preference.TwoStatePreference;
+
+public class InputMethodAndSubtypeEnablerManagerCompat implements
+ Preference.OnPreferenceChangeListener {
+
+ private final PreferenceFragmentCompat mFragment;
+
+ private boolean mHaveHardKeyboard;
+ private final HashMap<String, List<Preference>> mInputMethodAndSubtypePrefsMap =
+ new HashMap<>();
+ private final HashMap<String, TwoStatePreference> mAutoSelectionPrefsMap = new HashMap<>();
+ private InputMethodManager mImm;
+ // TODO: Change mInputMethodInfoList to Map
+ private List<InputMethodInfo> mInputMethodInfoList;
+ private final Collator mCollator = Collator.getInstance();
+
+ public InputMethodAndSubtypeEnablerManagerCompat(PreferenceFragmentCompat fragment) {
+ mFragment = fragment;
+ mImm = fragment.getContext().getSystemService(InputMethodManager.class);
+
+ mInputMethodInfoList = mImm.getInputMethodList();
+ }
+
+ public void init(PreferenceFragmentCompat fragment, String targetImi, PreferenceScreen root) {
+ final Configuration config = fragment.getResources().getConfiguration();
+ mHaveHardKeyboard = (config.keyboard == Configuration.KEYBOARD_QWERTY);
+
+ for (final InputMethodInfo imi : mInputMethodInfoList) {
+ // Add subtype preferences of this IME when it is specified or no IME is specified.
+ if (imi.getId().equals(targetImi) || TextUtils.isEmpty(targetImi)) {
+ addInputMethodSubtypePreferences(fragment, imi, root);
+ }
+ }
+ }
+
+ public void refresh(Context context, PreferenceFragmentCompat fragment) {
+ // Refresh internal states in mInputMethodSettingValues to keep the latest
+ // "InputMethodInfo"s and "InputMethodSubtype"s
+ InputMethodSettingValuesWrapper
+ .getInstance(context).refreshAllInputMethodAndSubtypes();
+ InputMethodAndSubtypeUtilCompat.loadInputMethodSubtypeList(fragment,
+ context.getContentResolver(), mInputMethodInfoList, mInputMethodAndSubtypePrefsMap);
+ updateAutoSelectionPreferences();
+ }
+
+ public void save(Context context, PreferenceFragmentCompat fragment) {
+ InputMethodAndSubtypeUtilCompat.saveInputMethodSubtypeList(fragment,
+ context.getContentResolver(), mInputMethodInfoList, mHaveHardKeyboard);
+ }
+
+ @Override
+ public boolean onPreferenceChange(final Preference pref, final Object newValue) {
+ if (!(newValue instanceof Boolean)) {
+ return true; // Invoke default behavior.
+ }
+ final boolean isChecking = (Boolean) newValue;
+ for (final String imiId : mAutoSelectionPrefsMap.keySet()) {
+ // An auto select subtype preference is changing.
+ if (mAutoSelectionPrefsMap.get(imiId) == pref) {
+ final TwoStatePreference autoSelectionPref = (TwoStatePreference) pref;
+ autoSelectionPref.setChecked(isChecking);
+ // Enable or disable subtypes depending on the auto selection preference.
+ setAutoSelectionSubtypesEnabled(imiId, autoSelectionPref.isChecked());
+ return false;
+ }
+ }
+ // A subtype preference is changing.
+ if (pref instanceof InputMethodSubtypePreference) {
+ final InputMethodSubtypePreference subtypePref = (InputMethodSubtypePreference) pref;
+ subtypePref.setChecked(isChecking);
+ if (!subtypePref.isChecked()) {
+ // It takes care of the case where no subtypes are explicitly enabled then the auto
+ // selection preference is going to be checked.
+ updateAutoSelectionPreferences();
+ }
+ return false;
+ }
+ return true; // Invoke default behavior.
+ }
+
+ private void addInputMethodSubtypePreferences(PreferenceFragmentCompat fragment,
+ InputMethodInfo imi, final PreferenceScreen root) {
+ Context prefContext = fragment.getPreferenceManager().getContext();
+
+ final int subtypeCount = imi.getSubtypeCount();
+ if (subtypeCount <= 1) {
+ return;
+ }
+ final String imiId = imi.getId();
+ final PreferenceCategory keyboardSettingsCategory =
+ new PreferenceCategory(prefContext);
+ root.addPreference(keyboardSettingsCategory);
+ final PackageManager pm = prefContext.getPackageManager();
+ final CharSequence label = imi.loadLabel(pm);
+
+ keyboardSettingsCategory.setTitle(label);
+ keyboardSettingsCategory.setKey(imiId);
+ // TODO: Use toggle Preference if images are ready.
+ final TwoStatePreference autoSelectionPref =
+ new SwitchWithNoTextPreference(prefContext);
+ mAutoSelectionPrefsMap.put(imiId, autoSelectionPref);
+ keyboardSettingsCategory.addPreference(autoSelectionPref);
+ autoSelectionPref.setOnPreferenceChangeListener(this);
+
+ final PreferenceCategory activeInputMethodsCategory =
+ new PreferenceCategory(prefContext);
+ activeInputMethodsCategory.setTitle(R.string.active_input_method_subtypes);
+ root.addPreference(activeInputMethodsCategory);
+
+ CharSequence autoSubtypeLabel = null;
+ final ArrayList<Preference> subtypePreferences = new ArrayList<>();
+ for (int index = 0; index < subtypeCount; ++index) {
+ final InputMethodSubtype subtype = imi.getSubtypeAt(index);
+ if (subtype.overridesImplicitlyEnabledSubtype()) {
+ if (autoSubtypeLabel == null) {
+ autoSubtypeLabel = InputMethodAndSubtypeUtil.getSubtypeLocaleNameAsSentence(
+ subtype, prefContext, imi);
+ }
+ } else {
+ final Preference subtypePref = new InputMethodSubtypePreference(
+ prefContext, subtype, imi);
+ subtypePreferences.add(subtypePref);
+ }
+ }
+ subtypePreferences.sort((lhs, rhs) -> {
+ if (lhs instanceof InputMethodSubtypePreference) {
+ return ((InputMethodSubtypePreference) lhs).compareTo(rhs, mCollator);
+ }
+ return lhs.compareTo(rhs);
+ });
+ for (final Preference pref : subtypePreferences) {
+ activeInputMethodsCategory.addPreference(pref);
+ pref.setOnPreferenceChangeListener(this);
+ InputMethodAndSubtypeUtil.removeUnnecessaryNonPersistentPreference(pref);
+ }
+ mInputMethodAndSubtypePrefsMap.put(imiId, subtypePreferences);
+ if (TextUtils.isEmpty(autoSubtypeLabel)) {
+ autoSelectionPref.setTitle(
+ R.string.use_system_language_to_select_input_method_subtypes);
+ } else {
+ autoSelectionPref.setTitle(autoSubtypeLabel);
+ }
+ }
+
+ private boolean isNoSubtypesExplicitlySelected(final String imiId) {
+ final List<Preference> subtypePrefs = mInputMethodAndSubtypePrefsMap.get(imiId);
+ for (final Preference pref : subtypePrefs) {
+ if (pref instanceof TwoStatePreference && ((TwoStatePreference) pref).isChecked()) {
+ return false;
+ }
+ }
+ return true;
+ }
+
+ private void setAutoSelectionSubtypesEnabled(final String imiId,
+ final boolean autoSelectionEnabled) {
+ final TwoStatePreference autoSelectionPref = mAutoSelectionPrefsMap.get(imiId);
+ if (autoSelectionPref == null) {
+ return;
+ }
+ autoSelectionPref.setChecked(autoSelectionEnabled);
+ final List<Preference> subtypePrefs = mInputMethodAndSubtypePrefsMap.get(imiId);
+ for (final Preference pref : subtypePrefs) {
+ if (pref instanceof TwoStatePreference) {
+ // When autoSelectionEnabled is true, all subtype prefs need to be disabled with
+ // implicitly checked subtypes. In case of false, all subtype prefs need to be
+ // enabled.
+ pref.setEnabled(!autoSelectionEnabled);
+ if (autoSelectionEnabled) {
+ ((TwoStatePreference) pref).setChecked(false);
+ }
+ }
+ }
+ if (autoSelectionEnabled) {
+ InputMethodAndSubtypeUtilCompat.saveInputMethodSubtypeList(
+ mFragment, mFragment.getContext().getContentResolver(),
+ mInputMethodInfoList, mHaveHardKeyboard);
+ updateImplicitlyEnabledSubtypes(imiId);
+ }
+ }
+
+ private void updateImplicitlyEnabledSubtypes(final String targetImiId) {
+ // When targetImiId is null, apply to all subtypes of all IMEs
+ for (final InputMethodInfo imi : mInputMethodInfoList) {
+ final String imiId = imi.getId();
+ final TwoStatePreference autoSelectionPref = mAutoSelectionPrefsMap.get(imiId);
+ // No need to update implicitly enabled subtypes when the user has unchecked the
+ // "subtype auto selection".
+ if (autoSelectionPref == null || !autoSelectionPref.isChecked()) {
+ continue;
+ }
+ if (imiId.equals(targetImiId) || targetImiId == null) {
+ updateImplicitlyEnabledSubtypesOf(imi);
+ }
+ }
+ }
+
+ private void updateImplicitlyEnabledSubtypesOf(final InputMethodInfo imi) {
+ final String imiId = imi.getId();
+ final List<Preference> subtypePrefs = mInputMethodAndSubtypePrefsMap.get(imiId);
+ final List<InputMethodSubtype> implicitlyEnabledSubtypes =
+ mImm.getEnabledInputMethodSubtypeList(imi, true);
+ if (subtypePrefs == null || implicitlyEnabledSubtypes == null) {
+ return;
+ }
+ for (final Preference pref : subtypePrefs) {
+ if (!(pref instanceof TwoStatePreference)) {
+ continue;
+ }
+ final TwoStatePreference subtypePref = (TwoStatePreference) pref;
+ subtypePref.setChecked(false);
+ for (final InputMethodSubtype subtype : implicitlyEnabledSubtypes) {
+ final String implicitlyEnabledSubtypePrefKey = imiId + subtype.hashCode();
+ if (subtypePref.getKey().equals(implicitlyEnabledSubtypePrefKey)) {
+ subtypePref.setChecked(true);
+ break;
+ }
+ }
+ }
+ }
+
+ private void updateAutoSelectionPreferences() {
+ for (final String imiId : mInputMethodAndSubtypePrefsMap.keySet()) {
+ setAutoSelectionSubtypesEnabled(imiId, isNoSubtypesExplicitlySelected(imiId));
+ }
+ updateImplicitlyEnabledSubtypes(null /* targetImiId */ /* check */);
+ }
+}
diff --git a/packages/SettingsLib/src/com/android/settingslib/inputmethod/InputMethodAndSubtypeUtilCompat.java b/packages/SettingsLib/src/com/android/settingslib/inputmethod/InputMethodAndSubtypeUtilCompat.java
new file mode 100644
index 0000000..9ad2adb
--- /dev/null
+++ b/packages/SettingsLib/src/com/android/settingslib/inputmethod/InputMethodAndSubtypeUtilCompat.java
@@ -0,0 +1,436 @@
+/*
+ * Copyright (C) 2018 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.inputmethod;
+
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.content.ContentResolver;
+import android.content.Context;
+import android.content.SharedPreferences;
+import android.content.res.Configuration;
+import android.icu.text.ListFormatter;
+import android.provider.Settings;
+import android.provider.Settings.SettingNotFoundException;
+import android.text.TextUtils;
+import android.util.Log;
+import android.view.inputmethod.InputMethodInfo;
+import android.view.inputmethod.InputMethodSubtype;
+
+import com.android.internal.app.LocaleHelper;
+
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Locale;
+import java.util.Map;
+
+import androidx.preference.Preference;
+import androidx.preference.PreferenceFragmentCompat;
+import androidx.preference.PreferenceScreen;
+import androidx.preference.TwoStatePreference;
+
+// TODO: Consolidate this with {@link InputMethodSettingValuesWrapper}.
+public class InputMethodAndSubtypeUtilCompat {
+
+ private static final boolean DEBUG = false;
+ private static final String TAG = "InputMethdAndSubtypeUtlCompat";
+
+ private static final String SUBTYPE_MODE_KEYBOARD = "keyboard";
+ private static final char INPUT_METHOD_SEPARATER = ':';
+ private static final char INPUT_METHOD_SUBTYPE_SEPARATER = ';';
+ private static final int NOT_A_SUBTYPE_ID = -1;
+
+ private static final TextUtils.SimpleStringSplitter sStringInputMethodSplitter
+ = new TextUtils.SimpleStringSplitter(INPUT_METHOD_SEPARATER);
+
+ private static final TextUtils.SimpleStringSplitter sStringInputMethodSubtypeSplitter
+ = new TextUtils.SimpleStringSplitter(INPUT_METHOD_SUBTYPE_SEPARATER);
+
+ // InputMethods and subtypes are saved in the settings as follows:
+ // ime0;subtype0;subtype1:ime1;subtype0:ime2:ime3;subtype0;subtype1
+ public static String buildInputMethodsAndSubtypesString(
+ final HashMap<String, HashSet<String>> imeToSubtypesMap) {
+ final StringBuilder builder = new StringBuilder();
+ for (final String imi : imeToSubtypesMap.keySet()) {
+ if (builder.length() > 0) {
+ builder.append(INPUT_METHOD_SEPARATER);
+ }
+ final HashSet<String> subtypeIdSet = imeToSubtypesMap.get(imi);
+ builder.append(imi);
+ for (final String subtypeId : subtypeIdSet) {
+ builder.append(INPUT_METHOD_SUBTYPE_SEPARATER).append(subtypeId);
+ }
+ }
+ return builder.toString();
+ }
+
+ private static String buildInputMethodsString(final HashSet<String> imiList) {
+ final StringBuilder builder = new StringBuilder();
+ for (final String imi : imiList) {
+ if (builder.length() > 0) {
+ builder.append(INPUT_METHOD_SEPARATER);
+ }
+ builder.append(imi);
+ }
+ return builder.toString();
+ }
+
+ private static int getInputMethodSubtypeSelected(ContentResolver resolver) {
+ try {
+ return Settings.Secure.getInt(resolver,
+ Settings.Secure.SELECTED_INPUT_METHOD_SUBTYPE);
+ } catch (SettingNotFoundException e) {
+ return NOT_A_SUBTYPE_ID;
+ }
+ }
+
+ private static boolean isInputMethodSubtypeSelected(ContentResolver resolver) {
+ return getInputMethodSubtypeSelected(resolver) != NOT_A_SUBTYPE_ID;
+ }
+
+ private static void putSelectedInputMethodSubtype(ContentResolver resolver, int hashCode) {
+ Settings.Secure.putInt(resolver, Settings.Secure.SELECTED_INPUT_METHOD_SUBTYPE, hashCode);
+ }
+
+ // Needs to modify InputMethodManageService if you want to change the format of saved string.
+ static HashMap<String, HashSet<String>> getEnabledInputMethodsAndSubtypeList(
+ ContentResolver resolver) {
+ final String enabledInputMethodsStr = Settings.Secure.getString(
+ resolver, Settings.Secure.ENABLED_INPUT_METHODS);
+ if (DEBUG) {
+ Log.d(TAG, "--- Load enabled input methods: " + enabledInputMethodsStr);
+ }
+ return parseInputMethodsAndSubtypesString(enabledInputMethodsStr);
+ }
+
+ public static HashMap<String, HashSet<String>> parseInputMethodsAndSubtypesString(
+ final String inputMethodsAndSubtypesString) {
+ final HashMap<String, HashSet<String>> subtypesMap = new HashMap<>();
+ if (TextUtils.isEmpty(inputMethodsAndSubtypesString)) {
+ return subtypesMap;
+ }
+ sStringInputMethodSplitter.setString(inputMethodsAndSubtypesString);
+ while (sStringInputMethodSplitter.hasNext()) {
+ final String nextImsStr = sStringInputMethodSplitter.next();
+ sStringInputMethodSubtypeSplitter.setString(nextImsStr);
+ if (sStringInputMethodSubtypeSplitter.hasNext()) {
+ final HashSet<String> subtypeIdSet = new HashSet<>();
+ // The first element is {@link InputMethodInfoId}.
+ final String imiId = sStringInputMethodSubtypeSplitter.next();
+ while (sStringInputMethodSubtypeSplitter.hasNext()) {
+ subtypeIdSet.add(sStringInputMethodSubtypeSplitter.next());
+ }
+ subtypesMap.put(imiId, subtypeIdSet);
+ }
+ }
+ return subtypesMap;
+ }
+
+ private static HashSet<String> getDisabledSystemIMEs(ContentResolver resolver) {
+ HashSet<String> set = new HashSet<>();
+ String disabledIMEsStr = Settings.Secure.getString(
+ resolver, Settings.Secure.DISABLED_SYSTEM_INPUT_METHODS);
+ if (TextUtils.isEmpty(disabledIMEsStr)) {
+ return set;
+ }
+ sStringInputMethodSplitter.setString(disabledIMEsStr);
+ while(sStringInputMethodSplitter.hasNext()) {
+ set.add(sStringInputMethodSplitter.next());
+ }
+ return set;
+ }
+
+ public static void saveInputMethodSubtypeList(PreferenceFragmentCompat context,
+ ContentResolver resolver, List<InputMethodInfo> inputMethodInfos,
+ boolean hasHardKeyboard) {
+ String currentInputMethodId = Settings.Secure.getString(resolver,
+ Settings.Secure.DEFAULT_INPUT_METHOD);
+ final int selectedInputMethodSubtype = getInputMethodSubtypeSelected(resolver);
+ final HashMap<String, HashSet<String>> enabledIMEsAndSubtypesMap =
+ getEnabledInputMethodsAndSubtypeList(resolver);
+ final HashSet<String> disabledSystemIMEs = getDisabledSystemIMEs(resolver);
+
+ boolean needsToResetSelectedSubtype = false;
+ for (final InputMethodInfo imi : inputMethodInfos) {
+ final String imiId = imi.getId();
+ final Preference pref = context.findPreference(imiId);
+ if (pref == null) {
+ continue;
+ }
+ // In the choose input method screen or in the subtype enabler screen,
+ // <code>pref</code> is an instance of TwoStatePreference.
+ final boolean isImeChecked = (pref instanceof TwoStatePreference) ?
+ ((TwoStatePreference) pref).isChecked()
+ : enabledIMEsAndSubtypesMap.containsKey(imiId);
+ final boolean isCurrentInputMethod = imiId.equals(currentInputMethodId);
+ final boolean systemIme = imi.isSystem();
+ if ((!hasHardKeyboard && InputMethodSettingValuesWrapper.getInstance(
+ context.getActivity()).isAlwaysCheckedIme(imi))
+ || isImeChecked) {
+ if (!enabledIMEsAndSubtypesMap.containsKey(imiId)) {
+ // imiId has just been enabled
+ enabledIMEsAndSubtypesMap.put(imiId, new HashSet<>());
+ }
+ final HashSet<String> subtypesSet = enabledIMEsAndSubtypesMap.get(imiId);
+
+ boolean subtypePrefFound = false;
+ final int subtypeCount = imi.getSubtypeCount();
+ for (int i = 0; i < subtypeCount; ++i) {
+ final InputMethodSubtype subtype = imi.getSubtypeAt(i);
+ final String subtypeHashCodeStr = String.valueOf(subtype.hashCode());
+ final TwoStatePreference subtypePref = (TwoStatePreference) context
+ .findPreference(imiId + subtypeHashCodeStr);
+ // In the Configure input method screen which does not have subtype preferences.
+ if (subtypePref == null) {
+ continue;
+ }
+ if (!subtypePrefFound) {
+ // Once subtype preference is found, subtypeSet needs to be cleared.
+ // Because of system change, hashCode value could have been changed.
+ subtypesSet.clear();
+ // If selected subtype preference is disabled, needs to reset.
+ needsToResetSelectedSubtype = true;
+ subtypePrefFound = true;
+ }
+ // Checking <code>subtypePref.isEnabled()</code> is insufficient to determine
+ // whether the user manually enabled this subtype or not. Implicitly-enabled
+ // subtypes are also checked just as an indicator to users. We also need to
+ // check <code>subtypePref.isEnabled()</code> so that only manually enabled
+ // subtypes can be saved here.
+ if (subtypePref.isEnabled() && subtypePref.isChecked()) {
+ subtypesSet.add(subtypeHashCodeStr);
+ if (isCurrentInputMethod) {
+ if (selectedInputMethodSubtype == subtype.hashCode()) {
+ // Selected subtype is still enabled, there is no need to reset
+ // selected subtype.
+ needsToResetSelectedSubtype = false;
+ }
+ }
+ } else {
+ subtypesSet.remove(subtypeHashCodeStr);
+ }
+ }
+ } else {
+ enabledIMEsAndSubtypesMap.remove(imiId);
+ if (isCurrentInputMethod) {
+ // We are processing the current input method, but found that it's not enabled.
+ // This means that the current input method has been uninstalled.
+ // If currentInputMethod is already uninstalled, InputMethodManagerService will
+ // find the applicable IME from the history and the system locale.
+ if (DEBUG) {
+ Log.d(TAG, "Current IME was uninstalled or disabled.");
+ }
+ currentInputMethodId = null;
+ }
+ }
+ // If it's a disabled system ime, add it to the disabled list so that it
+ // doesn't get enabled automatically on any changes to the package list
+ if (systemIme && hasHardKeyboard) {
+ if (disabledSystemIMEs.contains(imiId)) {
+ if (isImeChecked) {
+ disabledSystemIMEs.remove(imiId);
+ }
+ } else {
+ if (!isImeChecked) {
+ disabledSystemIMEs.add(imiId);
+ }
+ }
+ }
+ }
+
+ final String enabledIMEsAndSubtypesString = buildInputMethodsAndSubtypesString(
+ enabledIMEsAndSubtypesMap);
+ final String disabledSystemIMEsString = buildInputMethodsString(disabledSystemIMEs);
+ if (DEBUG) {
+ Log.d(TAG, "--- Save enabled inputmethod settings. :" + enabledIMEsAndSubtypesString);
+ Log.d(TAG, "--- Save disabled system inputmethod settings. :"
+ + disabledSystemIMEsString);
+ Log.d(TAG, "--- Save default inputmethod settings. :" + currentInputMethodId);
+ Log.d(TAG, "--- Needs to reset the selected subtype :" + needsToResetSelectedSubtype);
+ Log.d(TAG, "--- Subtype is selected :" + isInputMethodSubtypeSelected(resolver));
+ }
+
+ // Redefines SelectedSubtype when all subtypes are unchecked or there is no subtype
+ // selected. And if the selected subtype of the current input method was disabled,
+ // We should reset the selected input method's subtype.
+ if (needsToResetSelectedSubtype || !isInputMethodSubtypeSelected(resolver)) {
+ if (DEBUG) {
+ Log.d(TAG, "--- Reset inputmethod subtype because it's not defined.");
+ }
+ putSelectedInputMethodSubtype(resolver, NOT_A_SUBTYPE_ID);
+ }
+
+ Settings.Secure.putString(resolver,
+ Settings.Secure.ENABLED_INPUT_METHODS, enabledIMEsAndSubtypesString);
+ if (disabledSystemIMEsString.length() > 0) {
+ Settings.Secure.putString(resolver, Settings.Secure.DISABLED_SYSTEM_INPUT_METHODS,
+ disabledSystemIMEsString);
+ }
+ // If the current input method is unset, InputMethodManagerService will find the applicable
+ // IME from the history and the system locale.
+ Settings.Secure.putString(resolver, Settings.Secure.DEFAULT_INPUT_METHOD,
+ currentInputMethodId != null ? currentInputMethodId : "");
+ }
+
+ public static void loadInputMethodSubtypeList(final PreferenceFragmentCompat context,
+ final ContentResolver resolver, final List<InputMethodInfo> inputMethodInfos,
+ final Map<String, List<Preference>> inputMethodPrefsMap) {
+ final HashMap<String, HashSet<String>> enabledSubtypes =
+ getEnabledInputMethodsAndSubtypeList(resolver);
+
+ for (final InputMethodInfo imi : inputMethodInfos) {
+ final String imiId = imi.getId();
+ final Preference pref = context.findPreference(imiId);
+ if (pref instanceof TwoStatePreference) {
+ final TwoStatePreference subtypePref = (TwoStatePreference) pref;
+ final boolean isEnabled = enabledSubtypes.containsKey(imiId);
+ subtypePref.setChecked(isEnabled);
+ if (inputMethodPrefsMap != null) {
+ for (final Preference childPref: inputMethodPrefsMap.get(imiId)) {
+ childPref.setEnabled(isEnabled);
+ }
+ }
+ setSubtypesPreferenceEnabled(context, inputMethodInfos, imiId, isEnabled);
+ }
+ }
+ updateSubtypesPreferenceChecked(context, inputMethodInfos, enabledSubtypes);
+ }
+
+ private static void setSubtypesPreferenceEnabled(final PreferenceFragmentCompat context,
+ final List<InputMethodInfo> inputMethodProperties, final String id,
+ final boolean enabled) {
+ final PreferenceScreen preferenceScreen = context.getPreferenceScreen();
+ for (final InputMethodInfo imi : inputMethodProperties) {
+ if (id.equals(imi.getId())) {
+ final int subtypeCount = imi.getSubtypeCount();
+ for (int i = 0; i < subtypeCount; ++i) {
+ final InputMethodSubtype subtype = imi.getSubtypeAt(i);
+ final TwoStatePreference pref = (TwoStatePreference) preferenceScreen
+ .findPreference(id + subtype.hashCode());
+ if (pref != null) {
+ pref.setEnabled(enabled);
+ }
+ }
+ }
+ }
+ }
+
+ private static void updateSubtypesPreferenceChecked(final PreferenceFragmentCompat context,
+ final List<InputMethodInfo> inputMethodProperties,
+ final HashMap<String, HashSet<String>> enabledSubtypes) {
+ final PreferenceScreen preferenceScreen = context.getPreferenceScreen();
+ for (final InputMethodInfo imi : inputMethodProperties) {
+ final String id = imi.getId();
+ if (!enabledSubtypes.containsKey(id)) {
+ // There is no need to enable/disable subtypes of disabled IMEs.
+ continue;
+ }
+ final HashSet<String> enabledSubtypesSet = enabledSubtypes.get(id);
+ final int subtypeCount = imi.getSubtypeCount();
+ for (int i = 0; i < subtypeCount; ++i) {
+ final InputMethodSubtype subtype = imi.getSubtypeAt(i);
+ final String hashCode = String.valueOf(subtype.hashCode());
+ if (DEBUG) {
+ Log.d(TAG, "--- Set checked state: " + "id" + ", " + hashCode + ", "
+ + enabledSubtypesSet.contains(hashCode));
+ }
+ final TwoStatePreference pref = (TwoStatePreference) preferenceScreen
+ .findPreference(id + hashCode);
+ if (pref != null) {
+ pref.setChecked(enabledSubtypesSet.contains(hashCode));
+ }
+ }
+ }
+ }
+
+ public static void removeUnnecessaryNonPersistentPreference(final Preference pref) {
+ final String key = pref.getKey();
+ if (pref.isPersistent() || key == null) {
+ return;
+ }
+ final SharedPreferences prefs = pref.getSharedPreferences();
+ if (prefs != null && prefs.contains(key)) {
+ prefs.edit().remove(key).apply();
+ }
+ }
+
+ @NonNull
+ public static String getSubtypeLocaleNameAsSentence(@Nullable InputMethodSubtype subtype,
+ @NonNull final Context context, @NonNull final InputMethodInfo inputMethodInfo) {
+ if (subtype == null) {
+ return "";
+ }
+ final Locale locale = getDisplayLocale(context);
+ final CharSequence subtypeName = subtype.getDisplayName(context,
+ inputMethodInfo.getPackageName(), inputMethodInfo.getServiceInfo()
+ .applicationInfo);
+ return LocaleHelper.toSentenceCase(subtypeName.toString(), locale);
+ }
+
+ @NonNull
+ public static String getSubtypeLocaleNameListAsSentence(
+ @NonNull final List<InputMethodSubtype> subtypes, @NonNull final Context context,
+ @NonNull final InputMethodInfo inputMethodInfo) {
+ if (subtypes.isEmpty()) {
+ return "";
+ }
+ final Locale locale = getDisplayLocale(context);
+ final int subtypeCount = subtypes.size();
+ final CharSequence[] subtypeNames = new CharSequence[subtypeCount];
+ for (int i = 0; i < subtypeCount; i++) {
+ subtypeNames[i] = subtypes.get(i).getDisplayName(context,
+ inputMethodInfo.getPackageName(), inputMethodInfo.getServiceInfo()
+ .applicationInfo);
+ }
+ return LocaleHelper.toSentenceCase(
+ ListFormatter.getInstance(locale).format((Object[]) subtypeNames), locale);
+ }
+
+ @NonNull
+ private static Locale getDisplayLocale(@Nullable final Context context) {
+ if (context == null) {
+ return Locale.getDefault();
+ }
+ if (context.getResources() == null) {
+ return Locale.getDefault();
+ }
+ final Configuration configuration = context.getResources().getConfiguration();
+ if (configuration == null) {
+ return Locale.getDefault();
+ }
+ final Locale configurationLocale = configuration.getLocales().get(0);
+ if (configurationLocale == null) {
+ return Locale.getDefault();
+ }
+ return configurationLocale;
+ }
+
+ public static boolean isValidSystemNonAuxAsciiCapableIme(InputMethodInfo imi) {
+ if (imi.isAuxiliaryIme() || !imi.isSystem()) {
+ return false;
+ }
+ final int subtypeCount = imi.getSubtypeCount();
+ for (int i = 0; i < subtypeCount; ++i) {
+ final InputMethodSubtype subtype = imi.getSubtypeAt(i);
+ if (SUBTYPE_MODE_KEYBOARD.equalsIgnoreCase(subtype.getMode())
+ && subtype.isAsciiCapable()) {
+ return true;
+ }
+ }
+ return false;
+ }
+}
diff --git a/packages/SettingsLib/src/com/android/settingslib/license/LicenseHtmlLoaderCompat.java b/packages/SettingsLib/src/com/android/settingslib/license/LicenseHtmlLoaderCompat.java
new file mode 100644
index 0000000..d7c14ad
--- /dev/null
+++ b/packages/SettingsLib/src/com/android/settingslib/license/LicenseHtmlLoaderCompat.java
@@ -0,0 +1,111 @@
+/*
+ * Copyright (C) 2018 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.license;
+
+import android.content.Context;
+import android.util.Log;
+
+import com.android.settingslib.utils.AsyncLoaderCompat;
+
+import java.io.File;
+import java.util.ArrayList;
+import java.util.List;
+
+import androidx.annotation.VisibleForTesting;
+
+/**
+ * LicenseHtmlLoader is a loader which loads a license html file from default license xml files.
+ */
+public class LicenseHtmlLoaderCompat extends AsyncLoaderCompat<File> {
+ private static final String TAG = "LicenseHtmlLoaderCompat";
+
+ private static final String[] DEFAULT_LICENSE_XML_PATHS = {
+ "/system/etc/NOTICE.xml.gz",
+ "/vendor/etc/NOTICE.xml.gz",
+ "/odm/etc/NOTICE.xml.gz",
+ "/oem/etc/NOTICE.xml.gz"};
+ private static final String NOTICE_HTML_FILE_NAME = "NOTICE.html";
+
+ private Context mContext;
+
+ public LicenseHtmlLoaderCompat(Context context) {
+ super(context);
+ mContext = context;
+ }
+
+ @Override
+ public File loadInBackground() {
+ return generateHtmlFromDefaultXmlFiles();
+ }
+
+ @Override
+ protected void onDiscardResult(File f) {
+ }
+
+ private File generateHtmlFromDefaultXmlFiles() {
+ final List<File> xmlFiles = getVaildXmlFiles();
+ if (xmlFiles.isEmpty()) {
+ Log.e(TAG, "No notice file exists.");
+ return null;
+ }
+
+ File cachedHtmlFile = getCachedHtmlFile();
+ if (!isCachedHtmlFileOutdated(xmlFiles, cachedHtmlFile)
+ || generateHtmlFile(xmlFiles, cachedHtmlFile)) {
+ return cachedHtmlFile;
+ }
+
+ return null;
+ }
+
+ @VisibleForTesting
+ List<File> getVaildXmlFiles() {
+ final List<File> xmlFiles = new ArrayList();
+ for (final String xmlPath : DEFAULT_LICENSE_XML_PATHS) {
+ File file = new File(xmlPath);
+ if (file.exists() && file.length() != 0) {
+ xmlFiles.add(file);
+ }
+ }
+ return xmlFiles;
+ }
+
+ @VisibleForTesting
+ File getCachedHtmlFile() {
+ return new File(mContext.getCacheDir(), NOTICE_HTML_FILE_NAME);
+ }
+
+ @VisibleForTesting
+ boolean isCachedHtmlFileOutdated(List<File> xmlFiles, File cachedHtmlFile) {
+ boolean outdated = true;
+ if (cachedHtmlFile.exists() && cachedHtmlFile.length() != 0) {
+ outdated = false;
+ for (File file : xmlFiles) {
+ if (cachedHtmlFile.lastModified() < file.lastModified()) {
+ outdated = true;
+ break;
+ }
+ }
+ }
+ return outdated;
+ }
+
+ @VisibleForTesting
+ boolean generateHtmlFile(List<File> xmlFiles, File htmlFile) {
+ return LicenseHtmlGeneratorFromXml.generateHtml(xmlFiles, htmlFile);
+ }
+}
diff --git a/packages/SettingsLib/src/com/android/settingslib/net/ChartDataLoaderCompat.java b/packages/SettingsLib/src/com/android/settingslib/net/ChartDataLoaderCompat.java
new file mode 100644
index 0000000..3adbd4d
--- /dev/null
+++ b/packages/SettingsLib/src/com/android/settingslib/net/ChartDataLoaderCompat.java
@@ -0,0 +1,146 @@
+/*
+ * Copyright (C) 2018 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.net;
+
+import static android.net.NetworkStats.SET_DEFAULT;
+import static android.net.NetworkStats.SET_FOREGROUND;
+import static android.net.NetworkStats.TAG_NONE;
+import static android.net.NetworkStatsHistory.FIELD_RX_BYTES;
+import static android.net.NetworkStatsHistory.FIELD_TX_BYTES;
+import static android.text.format.DateUtils.HOUR_IN_MILLIS;
+
+import android.content.Context;
+import android.net.INetworkStatsSession;
+import android.net.NetworkStatsHistory;
+import android.net.NetworkTemplate;
+import android.os.Bundle;
+import android.os.RemoteException;
+
+import com.android.settingslib.AppItem;
+
+import androidx.loader.content.AsyncTaskLoader;
+
+/**
+ * Loader for historical chart data for both network and UID details.
+ */
+public class ChartDataLoaderCompat extends AsyncTaskLoader<ChartData> {
+ private static final String KEY_TEMPLATE = "template";
+ private static final String KEY_APP = "app";
+ private static final String KEY_FIELDS = "fields";
+
+ private final INetworkStatsSession mSession;
+ private final Bundle mArgs;
+
+ public static Bundle buildArgs(NetworkTemplate template, AppItem app) {
+ return buildArgs(template, app, FIELD_RX_BYTES | FIELD_TX_BYTES);
+ }
+
+ public static Bundle buildArgs(NetworkTemplate template, AppItem app, int fields) {
+ final Bundle args = new Bundle();
+ args.putParcelable(KEY_TEMPLATE, template);
+ args.putParcelable(KEY_APP, app);
+ args.putInt(KEY_FIELDS, fields);
+ return args;
+ }
+
+ public ChartDataLoaderCompat(Context context, INetworkStatsSession session, Bundle args) {
+ super(context);
+ mSession = session;
+ mArgs = args;
+ }
+
+ @Override
+ protected void onStartLoading() {
+ super.onStartLoading();
+ forceLoad();
+ }
+
+ @Override
+ public ChartData loadInBackground() {
+ final NetworkTemplate template = mArgs.getParcelable(KEY_TEMPLATE);
+ final AppItem app = mArgs.getParcelable(KEY_APP);
+ final int fields = mArgs.getInt(KEY_FIELDS);
+
+ try {
+ return loadInBackground(template, app, fields);
+ } catch (RemoteException e) {
+ // since we can't do much without history, and we don't want to
+ // leave with half-baked UI, we bail hard.
+ throw new RuntimeException("problem reading network stats", e);
+ }
+ }
+
+ private ChartData loadInBackground(NetworkTemplate template, AppItem app, int fields)
+ throws RemoteException {
+ final ChartData data = new ChartData();
+ data.network = mSession.getHistoryForNetwork(template, fields);
+
+ if (app != null) {
+ // load stats for current uid and template
+ final int size = app.uids.size();
+ for (int i = 0; i < size; i++) {
+ final int uid = app.uids.keyAt(i);
+ data.detailDefault = collectHistoryForUid(
+ template, uid, SET_DEFAULT, data.detailDefault);
+ data.detailForeground = collectHistoryForUid(
+ template, uid, SET_FOREGROUND, data.detailForeground);
+ }
+
+ if (size > 0) {
+ data.detail = new NetworkStatsHistory(data.detailForeground.getBucketDuration());
+ data.detail.recordEntireHistory(data.detailDefault);
+ data.detail.recordEntireHistory(data.detailForeground);
+ } else {
+ data.detailDefault = new NetworkStatsHistory(HOUR_IN_MILLIS);
+ data.detailForeground = new NetworkStatsHistory(HOUR_IN_MILLIS);
+ data.detail = new NetworkStatsHistory(HOUR_IN_MILLIS);
+ }
+ }
+
+ return data;
+ }
+
+ @Override
+ protected void onStopLoading() {
+ super.onStopLoading();
+ cancelLoad();
+ }
+
+ @Override
+ protected void onReset() {
+ super.onReset();
+ cancelLoad();
+ }
+
+ /**
+ * Collect {@link NetworkStatsHistory} for the requested UID, combining with
+ * an existing {@link NetworkStatsHistory} if provided.
+ */
+ private NetworkStatsHistory collectHistoryForUid(
+ NetworkTemplate template, int uid, int set, NetworkStatsHistory existing)
+ throws RemoteException {
+ final NetworkStatsHistory history = mSession.getHistoryForUid(
+ template, uid, set, TAG_NONE, FIELD_RX_BYTES | FIELD_TX_BYTES);
+
+ if (existing != null) {
+ existing.recordEntireHistory(history);
+ return existing;
+ } else {
+ return history;
+ }
+ }
+}
diff --git a/packages/SettingsLib/src/com/android/settingslib/net/SummaryForAllUidLoaderCompat.java b/packages/SettingsLib/src/com/android/settingslib/net/SummaryForAllUidLoaderCompat.java
new file mode 100644
index 0000000..c311337
--- /dev/null
+++ b/packages/SettingsLib/src/com/android/settingslib/net/SummaryForAllUidLoaderCompat.java
@@ -0,0 +1,81 @@
+/*
+ * Copyright (C) 2018 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.net;
+
+import android.content.Context;
+import android.net.INetworkStatsSession;
+import android.net.NetworkStats;
+import android.net.NetworkTemplate;
+import android.os.Bundle;
+import android.os.RemoteException;
+
+import androidx.loader.content.AsyncTaskLoader;
+
+public class SummaryForAllUidLoaderCompat extends AsyncTaskLoader<NetworkStats> {
+ private static final String KEY_TEMPLATE = "template";
+ private static final String KEY_START = "start";
+ private static final String KEY_END = "end";
+
+ private final INetworkStatsSession mSession;
+ private final Bundle mArgs;
+
+ public static Bundle buildArgs(NetworkTemplate template, long start, long end) {
+ final Bundle args = new Bundle();
+ args.putParcelable(KEY_TEMPLATE, template);
+ args.putLong(KEY_START, start);
+ args.putLong(KEY_END, end);
+ return args;
+ }
+
+ public SummaryForAllUidLoaderCompat(Context context, INetworkStatsSession session,
+ Bundle args) {
+ super(context);
+ mSession = session;
+ mArgs = args;
+ }
+
+ @Override
+ protected void onStartLoading() {
+ super.onStartLoading();
+ forceLoad();
+ }
+
+ @Override
+ public NetworkStats loadInBackground() {
+ final NetworkTemplate template = mArgs.getParcelable(KEY_TEMPLATE);
+ final long start = mArgs.getLong(KEY_START);
+ final long end = mArgs.getLong(KEY_END);
+
+ try {
+ return mSession.getSummaryForAllUid(template, start, end, false);
+ } catch (RemoteException e) {
+ return null;
+ }
+ }
+
+ @Override
+ protected void onStopLoading() {
+ super.onStopLoading();
+ cancelLoad();
+ }
+
+ @Override
+ protected void onReset() {
+ super.onReset();
+ cancelLoad();
+ }
+}
diff --git a/packages/SettingsLib/src/com/android/settingslib/suggestions/SuggestionControllerMixinCompat.java b/packages/SettingsLib/src/com/android/settingslib/suggestions/SuggestionControllerMixinCompat.java
new file mode 100644
index 0000000..1791217
--- /dev/null
+++ b/packages/SettingsLib/src/com/android/settingslib/suggestions/SuggestionControllerMixinCompat.java
@@ -0,0 +1,143 @@
+/*
+ * Copyright (C) 2018 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.suggestions;
+
+
+import android.content.ComponentName;
+import android.content.Context;
+import android.os.Bundle;
+import android.service.settings.suggestions.Suggestion;
+import android.util.Log;
+
+import com.android.settingslib.core.lifecycle.Lifecycle;
+
+import java.util.List;
+
+import androidx.annotation.Nullable;
+import androidx.lifecycle.OnLifecycleEvent;
+import androidx.loader.app.LoaderManager;
+import androidx.loader.content.Loader;
+
+/**
+ * Manages IPC communication to SettingsIntelligence for suggestion related services.
+ */
+public class SuggestionControllerMixinCompat implements
+ SuggestionController.ServiceConnectionListener, androidx.lifecycle.LifecycleObserver,
+ LoaderManager.LoaderCallbacks<List<Suggestion>> {
+
+ public interface SuggestionControllerHost {
+ /**
+ * Called when suggestion data fetching is ready.
+ */
+ void onSuggestionReady(List<Suggestion> data);
+
+ /**
+ * Returns {@link LoaderManager} associated with the host. If host is not attached to
+ * activity then return null.
+ */
+ @Nullable
+ LoaderManager getLoaderManager();
+ }
+
+ private static final String TAG = "SuggestionCtrlMixin";
+ private static final boolean DEBUG = false;
+
+ private final Context mContext;
+ private final SuggestionController mSuggestionController;
+ private final SuggestionControllerHost mHost;
+
+ private boolean mSuggestionLoaded;
+
+ public SuggestionControllerMixinCompat(Context context, SuggestionControllerHost host,
+ Lifecycle lifecycle, ComponentName componentName) {
+ mContext = context.getApplicationContext();
+ mHost = host;
+ mSuggestionController = new SuggestionController(mContext, componentName,
+ this /* serviceConnectionListener */);
+ if (lifecycle != null) {
+ lifecycle.addObserver(this);
+ }
+ }
+
+ @OnLifecycleEvent(Lifecycle.Event.ON_START)
+ public void onStart() {
+ if (DEBUG) {
+ Log.d(TAG, "SuggestionController started");
+ }
+ mSuggestionController.start();
+ }
+
+ @OnLifecycleEvent(Lifecycle.Event.ON_STOP)
+ public void onStop() {
+ if (DEBUG) {
+ Log.d(TAG, "SuggestionController stopped.");
+ }
+ mSuggestionController.stop();
+ }
+
+ @Override
+ public void onServiceConnected() {
+ final LoaderManager loaderManager = mHost.getLoaderManager();
+ if (loaderManager != null) {
+ loaderManager.restartLoader(SuggestionLoader.LOADER_ID_SUGGESTIONS,
+ null /* args */, this /* callback */);
+ }
+ }
+
+ @Override
+ public void onServiceDisconnected() {
+ if (DEBUG) {
+ Log.d(TAG, "SuggestionService disconnected");
+ }
+ final LoaderManager loaderManager = mHost.getLoaderManager();
+ if (loaderManager != null) {
+ loaderManager.destroyLoader(SuggestionLoader.LOADER_ID_SUGGESTIONS);
+ }
+ }
+
+ @Override
+ public Loader<List<Suggestion>> onCreateLoader(int id, Bundle args) {
+ if (id == SuggestionLoader.LOADER_ID_SUGGESTIONS) {
+ mSuggestionLoaded = false;
+ return new SuggestionLoaderCompat(mContext, mSuggestionController);
+ }
+ throw new IllegalArgumentException("This loader id is not supported " + id);
+ }
+
+ @Override
+ public void onLoadFinished(Loader<List<Suggestion>> loader, List<Suggestion> data) {
+ mSuggestionLoaded = true;
+ mHost.onSuggestionReady(data);
+ }
+
+ @Override
+ public void onLoaderReset(Loader<List<Suggestion>> loader) {
+ mSuggestionLoaded = false;
+ }
+
+ public boolean isSuggestionLoaded() {
+ return mSuggestionLoaded;
+ }
+
+ public void dismissSuggestion(Suggestion suggestion) {
+ mSuggestionController.dismissSuggestions(suggestion);
+ }
+
+ public void launchSuggestion(Suggestion suggestion) {
+ mSuggestionController.launchSuggestion(suggestion);
+ }
+}
diff --git a/packages/SettingsLib/src/com/android/settingslib/suggestions/SuggestionLoaderCompat.java b/packages/SettingsLib/src/com/android/settingslib/suggestions/SuggestionLoaderCompat.java
new file mode 100644
index 0000000..066de19
--- /dev/null
+++ b/packages/SettingsLib/src/com/android/settingslib/suggestions/SuggestionLoaderCompat.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.settingslib.suggestions;
+
+import android.content.Context;
+import android.service.settings.suggestions.Suggestion;
+import android.util.Log;
+
+import com.android.settingslib.utils.AsyncLoaderCompat;
+
+import java.util.List;
+
+public class SuggestionLoaderCompat extends AsyncLoaderCompat<List<Suggestion>> {
+
+ public static final int LOADER_ID_SUGGESTIONS = 42;
+ private static final String TAG = "SuggestionLoader";
+
+ private final SuggestionController mSuggestionController;
+
+ public SuggestionLoaderCompat(Context context, SuggestionController controller) {
+ super(context);
+ mSuggestionController = controller;
+ }
+
+ @Override
+ protected void onDiscardResult(List<Suggestion> result) {
+
+ }
+
+ @Override
+ public List<Suggestion> loadInBackground() {
+ final List<Suggestion> data = mSuggestionController.getSuggestions();
+ if (data == null) {
+ Log.d(TAG, "data is null");
+ } else {
+ Log.d(TAG, "data size " + data.size());
+ }
+ return data;
+ }
+}
\ No newline at end of file
diff --git a/packages/SettingsLib/src/com/android/settingslib/utils/AsyncLoaderCompat.java b/packages/SettingsLib/src/com/android/settingslib/utils/AsyncLoaderCompat.java
new file mode 100644
index 0000000..916d7e3
--- /dev/null
+++ b/packages/SettingsLib/src/com/android/settingslib/utils/AsyncLoaderCompat.java
@@ -0,0 +1,111 @@
+/*
+ * Copyright (C) 2018 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.utils;
+
+import android.content.Context;
+
+import androidx.loader.content.AsyncTaskLoader;
+
+/**
+ * This class fills in some boilerplate for AsyncTaskLoader to actually load things.
+ *
+ * Subclasses need to implement {@link AsyncLoaderCompat#loadInBackground()} to perform the actual
+ * background task, and {@link AsyncLoaderCompat#onDiscardResult(T)} to clean up previously loaded
+ * results.
+ *
+ * This loader is based on the MailAsyncTaskLoader from the AOSP EmailUnified repo.
+ *
+ * @param <T> the data type to be loaded.
+ */
+public abstract class AsyncLoaderCompat<T> extends AsyncTaskLoader<T> {
+ private T mResult;
+
+ public AsyncLoaderCompat(final Context context) {
+ super(context);
+ }
+
+ @Override
+ protected void onStartLoading() {
+ if (mResult != null) {
+ deliverResult(mResult);
+ }
+
+ if (takeContentChanged() || mResult == null) {
+ forceLoad();
+ }
+ }
+
+ @Override
+ protected void onStopLoading() {
+ cancelLoad();
+ }
+
+ @Override
+ public void deliverResult(final T data) {
+ if (isReset()) {
+ if (data != null) {
+ onDiscardResult(data);
+ }
+ return;
+ }
+
+ final T oldResult = mResult;
+ mResult = data;
+
+ if (isStarted()) {
+ super.deliverResult(data);
+ }
+
+ if (oldResult != null && oldResult != mResult) {
+ onDiscardResult(oldResult);
+ }
+ }
+
+ @Override
+ protected void onReset() {
+ super.onReset();
+
+ onStopLoading();
+
+ if (mResult != null) {
+ onDiscardResult(mResult);
+ }
+ mResult = null;
+ }
+
+ @Override
+ public void onCanceled(final T data) {
+ super.onCanceled(data);
+
+ if (data != null) {
+ onDiscardResult(data);
+ }
+ }
+
+ /**
+ * Called when discarding the load results so subclasses can take care of clean-up or
+ * recycling tasks. This is not called if the same result (by way of pointer equality) is
+ * returned again by a subsequent call to loadInBackground, or if result is null.
+ *
+ * Note that this may be called concurrently with loadInBackground(), and in some circumstances
+ * may be called more than once for a given object.
+ *
+ * @param result The value returned from {@link AsyncLoaderCompat#loadInBackground()} which
+ * is to be discarded.
+ */
+ protected abstract void onDiscardResult(T result);
+}
diff --git a/packages/SettingsLib/src/com/android/settingslib/widget/FooterPreferenceMixinCompat.java b/packages/SettingsLib/src/com/android/settingslib/widget/FooterPreferenceMixinCompat.java
new file mode 100644
index 0000000..260ac83
--- /dev/null
+++ b/packages/SettingsLib/src/com/android/settingslib/widget/FooterPreferenceMixinCompat.java
@@ -0,0 +1,72 @@
+/*
+ * Copyright (C) 2018 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.widget;
+
+import android.content.Context;
+
+import com.android.settingslib.core.lifecycle.Lifecycle;
+import com.android.settingslib.core.lifecycle.LifecycleObserver;
+import com.android.settingslib.core.lifecycle.events.SetPreferenceScreen;
+
+import androidx.preference.PreferenceFragmentCompat;
+import androidx.preference.PreferenceScreen;
+
+public class FooterPreferenceMixinCompat implements LifecycleObserver, SetPreferenceScreen {
+
+ private final PreferenceFragmentCompat mFragment;
+ private FooterPreference mFooterPreference;
+
+ public FooterPreferenceMixinCompat(PreferenceFragmentCompat fragment, Lifecycle lifecycle) {
+ mFragment = fragment;
+ lifecycle.addObserver(this);
+ }
+
+ @Override
+ public void setPreferenceScreen(PreferenceScreen preferenceScreen) {
+ if (mFooterPreference != null) {
+ preferenceScreen.addPreference(mFooterPreference);
+ }
+ }
+
+ /**
+ * Creates a new {@link FooterPreference}.
+ */
+ public FooterPreference createFooterPreference() {
+ final PreferenceScreen screen = mFragment.getPreferenceScreen();
+ if (mFooterPreference != null && screen != null) {
+ screen.removePreference(mFooterPreference);
+ }
+ mFooterPreference = new FooterPreference(getPrefContext());
+
+ if (screen != null) {
+ screen.addPreference(mFooterPreference);
+ }
+ return mFooterPreference;
+ }
+
+ /**
+ * Returns an UI context with theme properly set for new Preference objects.
+ */
+ private Context getPrefContext() {
+ return mFragment.getPreferenceManager().getContext();
+ }
+
+ public boolean hasFooter() {
+ return mFooterPreference != null;
+ }
+}
+
diff --git a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/CustomEditTextPreferenceComaptTest.java b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/CustomEditTextPreferenceComaptTest.java
new file mode 100644
index 0000000..9ba9967
--- /dev/null
+++ b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/CustomEditTextPreferenceComaptTest.java
@@ -0,0 +1,77 @@
+/*
+ * Copyright (C) 2018 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;
+
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.spy;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+import android.content.Context;
+import android.view.View;
+import android.widget.EditText;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+import org.robolectric.RuntimeEnvironment;
+import org.robolectric.util.ReflectionHelpers;
+
+@RunWith(SettingsLibRobolectricTestRunner.class)
+public class CustomEditTextPreferenceComaptTest {
+
+ @Mock
+ private View mView;
+
+ private TestPreference mPreference;
+
+ @Before
+ public void setUp() {
+ MockitoAnnotations.initMocks(this);
+ mPreference = new TestPreference(RuntimeEnvironment.application);
+ }
+
+ @Test
+ public void bindDialogView_shouldRequestFocus() {
+ final String testText = "";
+ final EditText editText = spy(new EditText(RuntimeEnvironment.application));
+ editText.setText(testText);
+ when(mView.findViewById(android.R.id.edit)).thenReturn(editText);
+
+ mPreference.onBindDialogView(mView);
+
+ verify(editText).requestFocus();
+ }
+
+ @Test
+ public void getEditText_noDialog_shouldNotCrash() {
+ ReflectionHelpers.setField(mPreference, "mFragment",
+ mock(CustomEditTextPreferenceCompat.CustomPreferenceDialogFragment.class));
+
+ mPreference.getEditText();
+
+ // no crash
+ }
+
+ private static class TestPreference extends CustomEditTextPreferenceCompat {
+ public TestPreference(Context context) {
+ super(context);
+ }
+ }
+}
diff --git a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/inputmethod/InputMethodAndSubtypeUtilCompatTest.java b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/inputmethod/InputMethodAndSubtypeUtilCompatTest.java
new file mode 100644
index 0000000..ddadac1
--- /dev/null
+++ b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/inputmethod/InputMethodAndSubtypeUtilCompatTest.java
@@ -0,0 +1,271 @@
+/*
+ * Copyright (C) 2018 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.inputmethod;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import android.content.pm.ApplicationInfo;
+import android.content.pm.ResolveInfo;
+import android.content.pm.ServiceInfo;
+import android.view.inputmethod.InputMethodInfo;
+import android.view.inputmethod.InputMethodSubtype;
+import android.view.inputmethod.InputMethodSubtype.InputMethodSubtypeBuilder;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.robolectric.RobolectricTestRunner;
+
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.HashSet;
+
+@RunWith(RobolectricTestRunner.class)
+public class InputMethodAndSubtypeUtilCompatTest {
+
+ private static final HashSet<String> EMPTY_STRING_SET = new HashSet<>();
+
+ private static HashSet<String> asHashSet(String... strings) {
+ HashSet<String> hashSet = new HashSet<>();
+ for (String s : strings) {
+ hashSet.add(s);
+ }
+ return hashSet;
+ }
+
+ @Test
+ public void parseInputMethodsAndSubtypesString_EmptyString() {
+ assertThat(InputMethodAndSubtypeUtilCompat.
+ parseInputMethodsAndSubtypesString("")).isEmpty();
+ assertThat(InputMethodAndSubtypeUtilCompat.
+ parseInputMethodsAndSubtypesString(null)).isEmpty();
+ }
+
+ @Test
+ public void parseInputMethodsAndSubtypesString_SingleImeNoSubtype() {
+ HashMap<String, HashSet<String>> r =
+ InputMethodAndSubtypeUtilCompat.parseInputMethodsAndSubtypesString("ime0");
+ assertThat(r).containsExactly("ime0", EMPTY_STRING_SET);
+ }
+
+ @Test
+ public void parseInputMethodsAndSubtypesString_MultipleImesNoSubtype() {
+ HashMap<String, HashSet<String>> r =
+ InputMethodAndSubtypeUtilCompat.parseInputMethodsAndSubtypesString("ime0:ime1");
+ assertThat(r).containsExactly("ime0", EMPTY_STRING_SET, "ime1", EMPTY_STRING_SET);
+ }
+
+ @Test
+ public void parseInputMethodsAndSubtypesString_SingleImeSingleSubtype() {
+ HashMap<String, HashSet<String>> r =
+ InputMethodAndSubtypeUtilCompat.parseInputMethodsAndSubtypesString("ime0;subtype0");
+ assertThat(r).containsExactly("ime0", asHashSet("subtype0"));
+ }
+
+ @Test
+ public void parseInputMethodsAndSubtypesString_SingleImeDuplicateSameSubtypes() {
+ HashMap<String, HashSet<String>> r =
+ InputMethodAndSubtypeUtilCompat.parseInputMethodsAndSubtypesString(
+ "ime0;subtype0;subtype0");
+ assertThat(r).containsExactly("ime0", asHashSet("subtype0"));
+ }
+
+ @Test
+ public void parseInputMethodsAndSubtypesString_SingleImeMultipleSubtypes() {
+ HashMap<String, HashSet<String>> r =
+ InputMethodAndSubtypeUtilCompat.parseInputMethodsAndSubtypesString(
+ "ime0;subtype0;subtype1");
+ assertThat(r).containsExactly("ime0", asHashSet("subtype0", "subtype1"));
+ }
+
+ @Test
+ public void parseInputMethodsAndSubtypesString_MultiplePairsOfImeSubtype() {
+ assertThat(InputMethodAndSubtypeUtilCompat.parseInputMethodsAndSubtypesString(
+ "ime0;subtype0:ime1;subtype1"))
+ .containsExactly("ime0", asHashSet("subtype0"), "ime1", asHashSet("subtype1"));
+ assertThat(InputMethodAndSubtypeUtilCompat.parseInputMethodsAndSubtypesString(
+ "ime0;subtype0;subtype1:ime1;subtype2"))
+ .containsExactly("ime0", asHashSet("subtype0", "subtype1"),
+ "ime1", asHashSet("subtype2"));
+ assertThat(InputMethodAndSubtypeUtilCompat.parseInputMethodsAndSubtypesString(
+ "ime0;subtype0;subtype1:ime1;subtype1;subtype2"))
+ .containsExactly("ime0", asHashSet("subtype0", "subtype1"),
+ "ime1", asHashSet("subtype1", "subtype2"));
+
+ }
+
+ @Test
+ public void parseInputMethodsAndSubtypesString_MixedImeSubtypePairsAndImeNoSubtype() {
+ HashMap<String, HashSet<String>> r =
+ InputMethodAndSubtypeUtilCompat.parseInputMethodsAndSubtypesString(
+ "ime0;subtype0;subtype1:ime1;subtype1;subtype2:ime2");
+ assertThat(r).containsExactly("ime0", asHashSet("subtype0", "subtype1"),
+ "ime1", asHashSet("subtype1", "subtype2"),
+ "ime2", EMPTY_STRING_SET);
+ }
+
+ @Test
+ public void buildInputMethodsAndSubtypesString_EmptyInput() {
+ HashMap<String, HashSet<String>> map = new HashMap<>();
+ assertThat(map).isEmpty();
+ }
+
+ @Test
+ public void buildInputMethodsAndSubtypesString_SingleIme() {
+ HashMap<String, HashSet<String>> map = new HashMap<>();
+ map.put("ime0", new HashSet<>());
+ String result = InputMethodAndSubtypeUtilCompat.buildInputMethodsAndSubtypesString(map);
+ assertThat(result).isEqualTo("ime0");
+ }
+
+ @Test
+ public void buildInputMethodsAndSubtypesString_SingleImeSingleSubtype() {
+ HashMap<String, HashSet<String>> map = new HashMap<>();
+ map.put("ime0", asHashSet("subtype0"));
+ String result = InputMethodAndSubtypeUtilCompat.buildInputMethodsAndSubtypesString(map);
+ assertThat(result).isEqualTo("ime0;subtype0");
+ }
+
+ @Test
+ public void buildInputMethodsAndSubtypesString_SingleImeMultipleSubtypes() {
+ HashMap<String, HashSet<String>> map = new HashMap<>();
+ map.put("ime0", asHashSet("subtype0", "subtype1"));
+ String result = InputMethodAndSubtypeUtilCompat.buildInputMethodsAndSubtypesString(map);
+
+ // We do not expect what order will be used to concatenate items in
+ // InputMethodAndSubtypeUtil.buildInputMethodsAndSubtypesString() hence accept all possible
+ // permutations here.
+ assertThat(result).matches("ime0;subtype0;subtype1|ime0;subtype1;subtype0");
+ }
+
+ @Test
+ public void buildInputMethodsAndSubtypesString_MultipleImesNoSubtypes() {
+ HashMap<String, HashSet<String>> map = new HashMap<>();
+ map.put("ime0", EMPTY_STRING_SET);
+ map.put("ime1", EMPTY_STRING_SET);
+ String result = InputMethodAndSubtypeUtilCompat.buildInputMethodsAndSubtypesString(map);
+
+ // We do not expect what order will be used to concatenate items in
+ // InputMethodAndSubtypeUtil.buildInputMethodsAndSubtypesString() hence accept all possible
+ // permutations here.
+ assertThat(result).matches("ime0:ime1|ime1:ime0");
+ }
+
+ @Test
+ public void buildInputMethodsAndSubtypesString_MultipleImesWithAndWithoutSubtypes() {
+ HashMap<String, HashSet<String>> map = new HashMap<>();
+ map.put("ime0", asHashSet("subtype0", "subtype1"));
+ map.put("ime1", EMPTY_STRING_SET);
+ String result = InputMethodAndSubtypeUtilCompat.buildInputMethodsAndSubtypesString(map);
+
+ // We do not expect what order will be used to concatenate items in
+ // InputMethodAndSubtypeUtil.buildInputMethodsAndSubtypesString() hence accept all possible
+ // permutations here.
+ assertThat(result).matches("ime0;subtype0;subtype1:ime1|ime0;subtype1;subtype0:ime1"
+ + "|ime1:ime0;subtype0;subtype1|ime1:ime0;subtype1;subtype0");
+ }
+
+ @Test
+ public void buildInputMethodsAndSubtypesString_MultipleImesWithSubtypes() {
+ HashMap<String, HashSet<String>> map = new HashMap<>();
+ map.put("ime0", asHashSet("subtype0", "subtype1"));
+ map.put("ime1", asHashSet("subtype2", "subtype3"));
+ String result = InputMethodAndSubtypeUtilCompat.buildInputMethodsAndSubtypesString(map);
+
+ // We do not expect what order will be used to concatenate items in
+ // InputMethodAndSubtypeUtil.buildInputMethodsAndSubtypesString() hence accept all possible
+ // permutations here.
+ assertThat(result).matches("ime0;subtype0;subtype1:ime1;subtype2;subtype3"
+ + "|ime0;subtype1;subtype0:ime1;subtype2;subtype3"
+ + "|ime0;subtype0;subtype1:ime1;subtype3;subtype2"
+ + "|ime0;subtype1;subtype0:ime1;subtype3;subtype2"
+ + "|ime1;subtype2;subtype3:ime0;subtype0;subtype1"
+ + "|ime2;subtype3;subtype2:ime0;subtype0;subtype1"
+ + "|ime3;subtype2;subtype3:ime0;subtype1;subtype0"
+ + "|ime4;subtype3;subtype2:ime0;subtype1;subtype0");
+ }
+
+ @Test
+ public void isValidSystemNonAuxAsciiCapableIme() {
+ // System IME w/ no subtype
+ assertThat(InputMethodAndSubtypeUtilCompat.isValidSystemNonAuxAsciiCapableIme(
+ createDummyIme(true, false)))
+ .isFalse();
+
+ // System IME w/ non-Aux and non-ASCII-capable "keyboard" subtype
+ assertThat(InputMethodAndSubtypeUtilCompat.isValidSystemNonAuxAsciiCapableIme(
+ createDummyIme(true, false, createDummySubtype("keyboard", false, false))))
+ .isFalse();
+
+ // System IME w/ non-Aux and ASCII-capable "keyboard" subtype
+ assertThat(InputMethodAndSubtypeUtilCompat.isValidSystemNonAuxAsciiCapableIme(
+ createDummyIme(true, false, createDummySubtype("keyboard", false, true))))
+ .isTrue();
+
+ // System IME w/ Aux and ASCII-capable "keyboard" subtype
+ assertThat(InputMethodAndSubtypeUtilCompat.isValidSystemNonAuxAsciiCapableIme(
+ createDummyIme(true, true, createDummySubtype("keyboard", true, true))))
+ .isFalse();
+
+ // System IME w/ non-Aux and ASCII-capable "voice" subtype
+ assertThat(InputMethodAndSubtypeUtilCompat.isValidSystemNonAuxAsciiCapableIme(
+ createDummyIme(true, false, createDummySubtype("voice", false, true))))
+ .isFalse();
+
+ // System IME w/ non-Aux and non-ASCII-capable subtype + Non-Aux and ASCII-capable subtype
+ assertThat(InputMethodAndSubtypeUtilCompat.isValidSystemNonAuxAsciiCapableIme(
+ createDummyIme(true, false,
+ createDummySubtype("keyboard", false, true),
+ createDummySubtype("keyboard", false, false))))
+ .isTrue();
+
+ // Non-system IME w/ non-Aux and ASCII-capable "keyboard" subtype
+ assertThat(InputMethodAndSubtypeUtilCompat.isValidSystemNonAuxAsciiCapableIme(
+ createDummyIme(false, false, createDummySubtype("keyboard", false, true))))
+ .isFalse();
+ }
+
+ private static InputMethodInfo createDummyIme(boolean isSystem, boolean isAuxIme,
+ InputMethodSubtype... subtypes) {
+ final ResolveInfo ri = new ResolveInfo();
+ final ServiceInfo si = new ServiceInfo();
+ final ApplicationInfo ai = new ApplicationInfo();
+ ai.packageName = "com.example.android.dummyime";
+ ai.enabled = true;
+ ai.flags |= (isSystem ? ApplicationInfo.FLAG_SYSTEM : 0);
+ si.applicationInfo = ai;
+ si.enabled = true;
+ si.packageName = "com.example.android.dummyime";
+ si.name = "Dummy IME";
+ si.exported = true;
+ si.nonLocalizedLabel = "Dummy IME";
+ ri.serviceInfo = si;
+ return new InputMethodInfo(ri, isAuxIme, "", Arrays.asList(subtypes), 1, false);
+ }
+
+ private static InputMethodSubtype createDummySubtype(
+ String mode, boolean isAuxiliary, boolean isAsciiCapable) {
+ return new InputMethodSubtypeBuilder()
+ .setSubtypeNameResId(0)
+ .setSubtypeIconResId(0)
+ .setSubtypeLocale("en_US")
+ .setLanguageTag("en-US")
+ .setSubtypeMode(mode)
+ .setIsAuxiliary(isAuxiliary)
+ .setIsAsciiCapable(isAsciiCapable)
+ .build();
+ }
+}
diff --git a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/license/LicenseHtmlLoaderCompatTest.java b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/license/LicenseHtmlLoaderCompatTest.java
new file mode 100644
index 0000000..f981f36
--- /dev/null
+++ b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/license/LicenseHtmlLoaderCompatTest.java
@@ -0,0 +1,108 @@
+/*
+ * 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.license;
+
+import static com.google.common.truth.Truth.assertThat;
+import static org.mockito.Matchers.any;
+import static org.mockito.Mockito.doReturn;
+import static org.mockito.Mockito.never;
+import static org.mockito.Mockito.spy;
+import static org.mockito.Mockito.verify;
+
+import android.content.Context;
+
+import com.android.settingslib.SettingsLibRobolectricTestRunner;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+
+import java.io.File;
+import java.util.ArrayList;
+
+@RunWith(SettingsLibRobolectricTestRunner.class)
+public class LicenseHtmlLoaderCompatTest {
+ @Mock
+ private Context mContext;
+
+ LicenseHtmlLoaderCompat newLicenseHtmlLoader(ArrayList<File> xmlFiles,
+ File cachedHtmlFile, boolean isCachedHtmlFileOutdated,
+ boolean generateHtmlFileSucceeded) {
+ LicenseHtmlLoaderCompat loader = spy(new LicenseHtmlLoaderCompat(mContext));
+ doReturn(xmlFiles).when(loader).getVaildXmlFiles();
+ doReturn(cachedHtmlFile).when(loader).getCachedHtmlFile();
+ doReturn(isCachedHtmlFileOutdated).when(loader).isCachedHtmlFileOutdated(any(), any());
+ doReturn(generateHtmlFileSucceeded).when(loader).generateHtmlFile(any(), any());
+ return loader;
+ }
+
+ @Before
+ public void setUp() {
+ MockitoAnnotations.initMocks(this);
+ }
+
+ @Test
+ public void testLoadInBackground() {
+ ArrayList<File> xmlFiles = new ArrayList();
+ xmlFiles.add(new File("test.xml"));
+ File cachedHtmlFile = new File("test.html");
+
+ LicenseHtmlLoaderCompat loader = newLicenseHtmlLoader(xmlFiles, cachedHtmlFile, true, true);
+
+ assertThat(loader.loadInBackground()).isEqualTo(cachedHtmlFile);
+ verify(loader).generateHtmlFile(any(), any());
+ }
+
+ @Test
+ public void testLoadInBackgroundWithNoVaildXmlFiles() {
+ ArrayList<File> xmlFiles = new ArrayList();
+ File cachedHtmlFile = new File("test.html");
+
+ LicenseHtmlLoaderCompat loader = newLicenseHtmlLoader(xmlFiles, cachedHtmlFile, true, true);
+
+ assertThat(loader.loadInBackground()).isNull();
+ verify(loader, never()).generateHtmlFile(any(), any());
+ }
+
+ @Test
+ public void testLoadInBackgroundWithNonOutdatedCachedHtmlFile() {
+ ArrayList<File> xmlFiles = new ArrayList();
+ xmlFiles.add(new File("test.xml"));
+ File cachedHtmlFile = new File("test.html");
+
+ LicenseHtmlLoaderCompat loader = newLicenseHtmlLoader(xmlFiles, cachedHtmlFile, false,
+ true);
+
+ assertThat(loader.loadInBackground()).isEqualTo(cachedHtmlFile);
+ verify(loader, never()).generateHtmlFile(any(), any());
+ }
+
+ @Test
+ public void testLoadInBackgroundWithGenerateHtmlFileFailed() {
+ ArrayList<File> xmlFiles = new ArrayList();
+ xmlFiles.add(new File("test.xml"));
+ File cachedHtmlFile = new File("test.html");
+
+ LicenseHtmlLoaderCompat loader = newLicenseHtmlLoader(xmlFiles, cachedHtmlFile, true,
+ false);
+
+ assertThat(loader.loadInBackground()).isNull();
+ verify(loader).generateHtmlFile(any(), any());
+ }
+}
diff --git a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/suggestions/SuggestionControllerMixinCompatTest.java b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/suggestions/SuggestionControllerMixinCompatTest.java
new file mode 100644
index 0000000..1ee3afa
--- /dev/null
+++ b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/suggestions/SuggestionControllerMixinCompatTest.java
@@ -0,0 +1,127 @@
+/*
+ * Copyright (C) 2018 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.suggestions;
+
+import static androidx.lifecycle.Lifecycle.Event.ON_START;
+import static androidx.lifecycle.Lifecycle.Event.ON_STOP;
+import static com.google.common.truth.Truth.assertThat;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+import android.content.ComponentName;
+import android.content.Context;
+
+import com.android.settingslib.SettingsLibRobolectricTestRunner;
+import com.android.settingslib.core.lifecycle.Lifecycle;
+
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+import org.robolectric.RuntimeEnvironment;
+import org.robolectric.annotation.Config;
+
+import androidx.lifecycle.LifecycleOwner;
+import androidx.loader.app.LoaderManager;
+
+@RunWith(SettingsLibRobolectricTestRunner.class)
+@Config(shadows = ShadowSuggestionController.class)
+public class SuggestionControllerMixinCompatTest {
+
+ @Mock
+ private SuggestionControllerMixinCompat.SuggestionControllerHost mHost;
+
+ private Context mContext;
+ private LifecycleOwner mLifecycleOwner;
+ private Lifecycle mLifecycle;
+ private SuggestionControllerMixinCompat mMixin;
+ private ComponentName mComponentName;
+ @Before
+ public void setUp() {
+ MockitoAnnotations.initMocks(this);
+ mContext = RuntimeEnvironment.application;
+ mLifecycleOwner = () -> mLifecycle;
+ mLifecycle = new Lifecycle(mLifecycleOwner);
+ mComponentName = new ComponentName(
+ "com.android.settings.intelligence",
+ "com.android.settings.intelligence.suggestions.SuggestionService");
+ }
+
+ @After
+ public void tearDown() {
+ ShadowSuggestionController.reset();
+ }
+
+ @Test
+ public void goThroughLifecycle_onStartStop_shouldStartStopController() {
+ mMixin = new SuggestionControllerMixinCompat(mContext, mHost, mLifecycle, mComponentName);
+
+ mLifecycle.handleLifecycleEvent(ON_START);
+ assertThat(ShadowSuggestionController.sStartCalled).isTrue();
+
+ mLifecycle.handleLifecycleEvent(ON_STOP);
+ assertThat(ShadowSuggestionController.sStopCalled).isTrue();
+ }
+
+ @Test
+ public void onServiceConnected_shouldGetSuggestion() {
+ final LoaderManager loaderManager = mock(LoaderManager.class);
+ when(mHost.getLoaderManager()).thenReturn(loaderManager);
+
+ mMixin = new SuggestionControllerMixinCompat(mContext, mHost, mLifecycle, mComponentName);
+ mMixin.onServiceConnected();
+
+ verify(loaderManager).restartLoader(SuggestionLoader.LOADER_ID_SUGGESTIONS,
+ null /* args */, mMixin /* callback */);
+ }
+
+ @Test
+ public void onServiceConnected_hostNotAttached_shouldDoNothing() {
+ when(mHost.getLoaderManager()).thenReturn(null);
+
+ mMixin = new SuggestionControllerMixinCompat(mContext, mHost, mLifecycle, mComponentName);
+ mMixin.onServiceConnected();
+
+ verify(mHost).getLoaderManager();
+ }
+
+ @Test
+ public void onServiceDisconnected_hostNotAttached_shouldDoNothing() {
+ when(mHost.getLoaderManager()).thenReturn(null);
+
+ mMixin = new SuggestionControllerMixinCompat(mContext, mHost, mLifecycle, mComponentName);
+ mMixin.onServiceDisconnected();
+
+ verify(mHost).getLoaderManager();
+ }
+
+ @Test
+ public void doneLoadingg_shouldSetSuggestionLoaded() {
+ mMixin = new SuggestionControllerMixinCompat(mContext, mHost, mLifecycle, mComponentName);
+
+ mMixin.onLoadFinished(mock(SuggestionLoaderCompat.class), null);
+
+ assertThat(mMixin.isSuggestionLoaded()).isTrue();
+
+ mMixin.onLoaderReset(mock(SuggestionLoaderCompat.class));
+
+ assertThat(mMixin.isSuggestionLoaded()).isFalse();
+ }
+}
diff --git a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/widget/FooterPreferenceMixinCompatTest.java b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/widget/FooterPreferenceMixinCompatTest.java
new file mode 100644
index 0000000..1abbaba
--- /dev/null
+++ b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/widget/FooterPreferenceMixinCompatTest.java
@@ -0,0 +1,100 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.settingslib.widget;
+
+import static com.google.common.truth.Truth.assertThat;
+import static org.mockito.Matchers.any;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.times;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+import com.android.settingslib.SettingsLibRobolectricTestRunner;
+import com.android.settingslib.core.lifecycle.Lifecycle;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+import org.robolectric.shadows.ShadowApplication;
+
+import androidx.lifecycle.LifecycleOwner;
+import androidx.preference.PreferenceFragmentCompat;
+import androidx.preference.PreferenceManager;
+import androidx.preference.PreferenceScreen;
+
+@RunWith(SettingsLibRobolectricTestRunner.class)
+public class FooterPreferenceMixinCompatTest {
+
+ @Mock
+ private PreferenceFragmentCompat mFragment;
+ @Mock
+ private PreferenceScreen mScreen;
+
+ private LifecycleOwner mLifecycleOwner;
+ private Lifecycle mLifecycle;
+ private FooterPreferenceMixinCompat mMixin;
+
+ @Before
+ public void setUp() {
+ MockitoAnnotations.initMocks(this);
+ mLifecycleOwner = () -> mLifecycle;
+ mLifecycle = new Lifecycle(mLifecycleOwner);
+ when(mFragment.getPreferenceManager()).thenReturn(mock(PreferenceManager.class));
+ when(mFragment.getPreferenceManager().getContext())
+ .thenReturn(ShadowApplication.getInstance().getApplicationContext());
+ mMixin = new FooterPreferenceMixinCompat(mFragment, mLifecycle);
+ }
+
+ @Test
+ public void createFooter_screenNotAvailable_noCrash() {
+ assertThat(mMixin.createFooterPreference()).isNotNull();
+ }
+
+ @Test
+ public void createFooter_screenAvailable_canAttachToScreen() {
+ when(mFragment.getPreferenceScreen()).thenReturn(mScreen);
+
+ final FooterPreference preference = mMixin.createFooterPreference();
+
+ assertThat(preference).isNotNull();
+ verify(mScreen).addPreference(preference);
+ }
+
+ @Test
+ public void createFooter_screenAvailableDelayed_canAttachToScreen() {
+ final FooterPreference preference = mMixin.createFooterPreference();
+
+ mLifecycle.setPreferenceScreen(mScreen);
+
+ assertThat(preference).isNotNull();
+ verify(mScreen).addPreference(preference);
+ }
+
+ @Test
+ public void createFooterTwice_screenAvailable_replaceOldFooter() {
+ when(mFragment.getPreferenceScreen()).thenReturn(mScreen);
+
+ mMixin.createFooterPreference();
+ mMixin.createFooterPreference();
+
+ verify(mScreen).removePreference(any(FooterPreference.class));
+ verify(mScreen, times(2)).addPreference(any(FooterPreference.class));
+ }
+
+}
diff --git a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/widget/FooterPreferenceMixinTest.java b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/widget/FooterPreferenceMixinTest.java
index 78b7616..8604d18 100644
--- a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/widget/FooterPreferenceMixinTest.java
+++ b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/widget/FooterPreferenceMixinTest.java
@@ -23,11 +23,6 @@
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
-import androidx.lifecycle.LifecycleOwner;
-import androidx.preference.PreferenceFragment;
-import androidx.preference.PreferenceManager;
-import androidx.preference.PreferenceScreen;
-
import com.android.settingslib.SettingsLibRobolectricTestRunner;
import com.android.settingslib.core.lifecycle.Lifecycle;
@@ -38,6 +33,11 @@
import org.mockito.MockitoAnnotations;
import org.robolectric.shadows.ShadowApplication;
+import androidx.lifecycle.LifecycleOwner;
+import androidx.preference.PreferenceFragment;
+import androidx.preference.PreferenceManager;
+import androidx.preference.PreferenceScreen;
+
@RunWith(SettingsLibRobolectricTestRunner.class)
public class FooterPreferenceMixinTest {
diff --git a/packages/SystemUI/res-keyguard/values/strings.xml b/packages/SystemUI/res-keyguard/values/strings.xml
index 721e9c5..1d5aa6d 100644
--- a/packages/SystemUI/res-keyguard/values/strings.xml
+++ b/packages/SystemUI/res-keyguard/values/strings.xml
@@ -62,7 +62,7 @@
<!-- When the lock screen is showing, the phone is plugged in and the battery is fully
charged, say that it is charged. -->
- <string name="keyguard_charged">Charged</string>
+ <string name="keyguard_charged">Fully charged</string>
<!-- When the lock screen is showing and the phone plugged in, and the battery
is not fully charged, say that it's charging. -->
diff --git a/packages/overlays/SysuiDarkThemeOverlay/res/color/qs_detail_progress_track.xml b/packages/SystemUI/res/color-night/qs_detail_progress_track.xml
similarity index 100%
rename from packages/overlays/SysuiDarkThemeOverlay/res/color/qs_detail_progress_track.xml
rename to packages/SystemUI/res/color-night/qs_detail_progress_track.xml
diff --git a/packages/SystemUI/res/values/styles.xml b/packages/SystemUI/res/values/styles.xml
index 988a516..f867048 100644
--- a/packages/SystemUI/res/values/styles.xml
+++ b/packages/SystemUI/res/values/styles.xml
@@ -335,10 +335,7 @@
<item name="*android:errorColor">?android:attr/colorError</item>
</style>
- <!-- Overlay manager may replace this theme -->
- <style name="qs_base" parent="@*android:style/Theme.DeviceDefault.QuickSettings" />
-
- <style name="qs_theme" parent="qs_base">
+ <style name="qs_theme" parent="@*android:style/Theme.DeviceDefault.QuickSettings">
<item name="lightIconTheme">@style/QSIconTheme</item>
<item name="darkIconTheme">@style/QSIconTheme</item>
<item name="android:windowIsFloating">true</item>
@@ -501,7 +498,7 @@
parent="@*android:style/TextAppearance.Material.Notification.Info">
</style>
- <style name="edit_theme" parent="qs_base">
+ <style name="edit_theme" parent="qs_theme">
<item name="android:colorBackground">?android:attr/colorSecondary</item>
</style>
diff --git a/packages/SystemUI/src/com/android/systemui/AutoReinflateContainer.java b/packages/SystemUI/src/com/android/systemui/AutoReinflateContainer.java
index 01b4254..bbc8ecd 100644
--- a/packages/SystemUI/src/com/android/systemui/AutoReinflateContainer.java
+++ b/packages/SystemUI/src/com/android/systemui/AutoReinflateContainer.java
@@ -92,6 +92,11 @@
}
@Override
+ public void onUiModeChanged() {
+ inflateLayout();
+ }
+
+ @Override
public void onLocaleListChanged() {
inflateLayout();
}
diff --git a/packages/SystemUI/src/com/android/systemui/HardwareUiLayout.java b/packages/SystemUI/src/com/android/systemui/HardwareUiLayout.java
index 7742c55..198a4e6 100644
--- a/packages/SystemUI/src/com/android/systemui/HardwareUiLayout.java
+++ b/packages/SystemUI/src/com/android/systemui/HardwareUiLayout.java
@@ -28,6 +28,7 @@
import android.view.ViewOutlineProvider;
import android.view.ViewTreeObserver;
import android.widget.LinearLayout;
+
import com.android.systemui.tuner.TunerService;
import com.android.systemui.tuner.TunerService.Tunable;
import com.android.systemui.util.leak.RotationUtils;
@@ -41,14 +42,15 @@
private static final String EDGE_BLEED = "sysui_hwui_edge_bleed";
private static final String ROUNDED_DIVIDER = "sysui_hwui_rounded_divider";
private final int[] mTmp2 = new int[2];
- private View mChild;
+ private View mList;
private View mSeparatedView;
private int mOldHeight;
private boolean mAnimating;
private AnimatorSet mAnimation;
private View mDivision;
private boolean mHasOutsideTouch;
- private HardwareBgDrawable mBackground;
+ private HardwareBgDrawable mListBackground;
+ private HardwareBgDrawable mSeparatedViewBackground;
private Animator mAnimator;
private boolean mCollapse;
private boolean mHasSeparatedButton;
@@ -90,17 +92,19 @@
mRoundedDivider = Settings.Secure.getInt(getContext().getContentResolver(),
ROUNDED_DIVIDER, 0) != 0;
updateEdgeMargin(mEdgeBleed ? 0 : getEdgePadding());
- mBackground = new HardwareBgDrawable(mRoundedDivider, !mEdgeBleed, getContext());
- if (mChild != null) {
- mChild.setBackground(mBackground);
- mSeparatedView.setBackground(mBackground);
+ mListBackground = new HardwareBgDrawable(mRoundedDivider, !mEdgeBleed, getContext());
+ mSeparatedViewBackground = new HardwareBgDrawable(mRoundedDivider, !mEdgeBleed,
+ getContext());
+ if (mList != null) {
+ mList.setBackground(mListBackground);
+ mSeparatedView.setBackground(mSeparatedViewBackground);
requestLayout();
}
}
private void updateEdgeMargin(int edge) {
- if (mChild != null) {
- MarginLayoutParams params = (MarginLayoutParams) mChild.getLayoutParams();
+ if (mList != null) {
+ MarginLayoutParams params = (MarginLayoutParams) mList.getLayoutParams();
if (mRotation == ROTATION_LANDSCAPE) {
params.topMargin = edge;
} else if (mRotation == ROTATION_SEASCAPE) {
@@ -108,7 +112,7 @@
} else {
params.rightMargin = edge;
}
- mChild.setLayoutParams(params);
+ mList.setLayoutParams(params);
}
if (mSeparatedView != null) {
@@ -131,15 +135,15 @@
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
- if (mChild == null) {
+ if (mList == null) {
if (getChildCount() != 0) {
- mChild = getChildAt(0);
- mChild.setBackground(mBackground);
+ mList = getChildAt(0);
+ mList.setBackground(mListBackground);
mSeparatedView = getChildAt(1);
- mSeparatedView.setBackground(mBackground);
+ mSeparatedView.setBackground(mSeparatedViewBackground);
updateEdgeMargin(mEdgeBleed ? 0 : getEdgePadding());
- mOldHeight = mChild.getMeasuredHeight();
- mChild.addOnLayoutChangeListener(
+ mOldHeight = mList.getMeasuredHeight();
+ mList.addOnLayoutChangeListener(
(v, left, top, right, bottom, oldLeft, oldTop, oldRight, oldBottom) ->
updatePosition());
updateRotation();
@@ -147,7 +151,7 @@
return;
}
}
- int newHeight = mChild.getMeasuredHeight();
+ int newHeight = mList.getMeasuredHeight();
if (newHeight != mOldHeight) {
animateChild(mOldHeight, newHeight);
}
@@ -196,27 +200,29 @@
}
}
if (to != ROTATION_NONE) {
- if (mChild instanceof LinearLayout) {
+ if (mList instanceof LinearLayout) {
mRotatedBackground = true;
- mBackground.setRotatedBackground(true);
- LinearLayout linearLayout = (LinearLayout) mChild;
+ mListBackground.setRotatedBackground(true);
+ mSeparatedViewBackground.setRotatedBackground(true);
+ LinearLayout linearLayout = (LinearLayout) mList;
if (mSwapOrientation) {
linearLayout.setOrientation(LinearLayout.HORIZONTAL);
setOrientation(LinearLayout.HORIZONTAL);
}
- swapDimens(mChild);
+ swapDimens(mList);
swapDimens(mSeparatedView);
}
} else {
- if (mChild instanceof LinearLayout) {
+ if (mList instanceof LinearLayout) {
mRotatedBackground = false;
- mBackground.setRotatedBackground(false);
- LinearLayout linearLayout = (LinearLayout) mChild;
+ mListBackground.setRotatedBackground(false);
+ mSeparatedViewBackground.setRotatedBackground(false);
+ LinearLayout linearLayout = (LinearLayout) mList;
if (mSwapOrientation) {
linearLayout.setOrientation(LinearLayout.VERTICAL);
setOrientation(LinearLayout.VERTICAL);
}
- swapDimens(mChild);
+ swapDimens(mList);
swapDimens(mSeparatedView);
}
}
@@ -224,12 +230,12 @@
private void rotateRight() {
rotateRight(this);
- rotateRight(mChild);
+ rotateRight(mList);
swapDimens(this);
- LayoutParams p = (LayoutParams) mChild.getLayoutParams();
+ LayoutParams p = (LayoutParams) mList.getLayoutParams();
p.gravity = rotateGravityRight(p.gravity);
- mChild.setLayoutParams(p);
+ mList.setLayoutParams(p);
LayoutParams separatedViewLayoutParams = (LayoutParams) mSeparatedView.getLayoutParams();
separatedViewLayoutParams.gravity = rotateGravityRight(separatedViewLayoutParams.gravity);
@@ -282,12 +288,12 @@
private void rotateLeft() {
rotateLeft(this);
- rotateLeft(mChild);
+ rotateLeft(mList);
swapDimens(this);
- LayoutParams p = (LayoutParams) mChild.getLayoutParams();
+ LayoutParams p = (LayoutParams) mList.getLayoutParams();
p.gravity = rotateGravityLeft(p.gravity);
- mChild.setLayoutParams(p);
+ mList.setLayoutParams(p);
LayoutParams separatedViewLayoutParams = (LayoutParams) mSeparatedView.getLayoutParams();
separatedViewLayoutParams.gravity = rotateGravityLeft(separatedViewLayoutParams.gravity);
@@ -379,14 +385,14 @@
mAnimating = false;
}
});
- int fromTop = mChild.getTop();
- int fromBottom = mChild.getBottom();
+ int fromTop = mList.getTop();
+ int fromBottom = mList.getBottom();
int toTop = fromTop - ((newHeight - oldHeight) / 2);
int toBottom = fromBottom + ((newHeight - oldHeight) / 2);
- ObjectAnimator top = ObjectAnimator.ofInt(mChild, "top", fromTop, toTop);
- top.addUpdateListener(animation -> mBackground.invalidateSelf());
+ ObjectAnimator top = ObjectAnimator.ofInt(mList, "top", fromTop, toTop);
+ top.addUpdateListener(animation -> mListBackground.invalidateSelf());
mAnimation.playTogether(top,
- ObjectAnimator.ofInt(mChild, "bottom", fromBottom, toBottom));
+ ObjectAnimator.ofInt(mList, "bottom", fromBottom, toBottom));
}
public void setDivisionView(View v) {
@@ -400,29 +406,30 @@
}
private void updatePosition() {
- if (mChild == null) return;
+ if (mList == null) return;
// If got separated button, setRotatedBackground to false,
// all items won't get white background.
- mBackground.setRotatedBackground(mHasSeparatedButton);
+ mListBackground.setRotatedBackground(mHasSeparatedButton);
+ mSeparatedViewBackground.setRotatedBackground(mHasSeparatedButton);
if (mDivision != null && mDivision.getVisibility() == VISIBLE) {
int index = mRotatedBackground ? 0 : 1;
mDivision.getLocationOnScreen(mTmp2);
float trans = mRotatedBackground ? mDivision.getTranslationX()
: mDivision.getTranslationY();
int viewTop = (int) (mTmp2[index] + trans);
- mChild.getLocationOnScreen(mTmp2);
+ mList.getLocationOnScreen(mTmp2);
viewTop -= mTmp2[index];
setCutPoint(viewTop);
} else {
- setCutPoint(mChild.getMeasuredHeight());
+ setCutPoint(mList.getMeasuredHeight());
}
}
private void setCutPoint(int point) {
- int curPoint = mBackground.getCutPoint();
+ int curPoint = mListBackground.getCutPoint();
if (curPoint == point) return;
if (getAlpha() == 0 || curPoint == 0) {
- mBackground.setCutPoint(point);
+ mListBackground.setCutPoint(point);
return;
}
if (mAnimator != null) {
@@ -432,7 +439,7 @@
mAnimator.cancel();
}
mEndPoint = point;
- mAnimator = ObjectAnimator.ofInt(mBackground, "cutPoint", curPoint, point);
+ mAnimator = ObjectAnimator.ofInt(mListBackground, "cutPoint", curPoint, point);
if (mCollapse) {
mAnimator.setStartDelay(300);
mCollapse = false;
@@ -470,14 +477,14 @@
}
private final ViewTreeObserver.OnComputeInternalInsetsListener mInsetsListener = inoutInfo -> {
- if (mHasOutsideTouch || (mChild == null)) {
+ if (mHasOutsideTouch || (mList == null)) {
inoutInfo.setTouchableInsets(
ViewTreeObserver.InternalInsetsInfo.TOUCHABLE_INSETS_FRAME);
return;
}
inoutInfo.setTouchableInsets(
ViewTreeObserver.InternalInsetsInfo.TOUCHABLE_INSETS_CONTENT);
- inoutInfo.contentInsets.set(mChild.getLeft(), mChild.getTop(),
- 0, getBottom() - mChild.getBottom());
+ inoutInfo.contentInsets.set(mList.getLeft(), mList.getTop(),
+ 0, getBottom() - mList.getBottom());
};
}
diff --git a/packages/SystemUI/src/com/android/systemui/Interpolators.java b/packages/SystemUI/src/com/android/systemui/Interpolators.java
index aeef496..eb704c8 100644
--- a/packages/SystemUI/src/com/android/systemui/Interpolators.java
+++ b/packages/SystemUI/src/com/android/systemui/Interpolators.java
@@ -31,6 +31,13 @@
*/
public class Interpolators {
public static final Interpolator FAST_OUT_SLOW_IN = new PathInterpolator(0.4f, 0f, 0.2f, 1f);
+
+ /**
+ * Like {@link #FAST_OUT_SLOW_IN}, but used in case the animation is played in reverse (i.e. t
+ * goes from 1 to 0 instead of 0 to 1).
+ */
+ public static final Interpolator FAST_OUT_SLOW_IN_REVERSE =
+ new PathInterpolator(0.8f, 0f, 0.6f, 1f);
public static final Interpolator FAST_OUT_LINEAR_IN = new PathInterpolator(0.4f, 0f, 1f, 1f);
public static final Interpolator LINEAR_OUT_SLOW_IN = new PathInterpolator(0f, 0f, 0.2f, 1f);
public static final Interpolator ALPHA_IN = new PathInterpolator(0.4f, 0f, 1f, 1f);
@@ -51,4 +58,11 @@
*/
public static final Interpolator TOUCH_RESPONSE =
new PathInterpolator(0.3f, 0f, 0.1f, 1f);
+
+ /**
+ * Like {@link #TOUCH_RESPONSE}, but used in case the animation is played in reverse (i.e. t
+ * goes from 1 to 0 instead of 0 to 1).
+ */
+ public static final Interpolator TOUCH_RESPONSE_REVERSE =
+ new PathInterpolator(0.9f, 0f, 0.7f, 1f);
}
diff --git a/packages/SystemUI/src/com/android/systemui/OverviewProxyService.java b/packages/SystemUI/src/com/android/systemui/OverviewProxyService.java
index 70ca055..d21465c 100644
--- a/packages/SystemUI/src/com/android/systemui/OverviewProxyService.java
+++ b/packages/SystemUI/src/com/android/systemui/OverviewProxyService.java
@@ -30,6 +30,7 @@
import android.os.PatternMatcher;
import android.os.RemoteException;
import android.os.UserHandle;
+import android.provider.Settings;
import android.util.Log;
import android.view.SurfaceControl;
@@ -391,14 +392,22 @@
@Override
public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
pw.println(TAG_OPS + " state:");
- pw.print(" mConnectionBackoffAttempts="); pw.println(mConnectionBackoffAttempts);
+ pw.print(" recentsComponentName="); pw.println(mRecentsComponentName);
+ pw.print(" isConnected="); pw.println(mOverviewProxy != null);
pw.print(" isCurrentUserSetup="); pw.println(mDeviceProvisionedController
.isCurrentUserSetup());
- pw.print(" isConnected="); pw.println(mOverviewProxy != null);
- pw.print(" mRecentsComponentName="); pw.println(mRecentsComponentName);
- pw.print(" mIsEnabled="); pw.println(isEnabled());
- pw.print(" mInteractionFlags="); pw.println(mInteractionFlags);
- pw.print(" mQuickStepIntent="); pw.println(mQuickStepIntent);
+ pw.print(" connectionBackoffAttempts="); pw.println(mConnectionBackoffAttempts);
+ pw.print(" interactionFlags="); pw.println(mInteractionFlags);
+
+ pw.print(" quickStepIntent="); pw.println(mQuickStepIntent);
+ pw.print(" quickStepIntentResolved="); pw.println(isEnabled());
+
+ final int swipeUpDefaultValue = mContext.getResources()
+ .getBoolean(com.android.internal.R.bool.config_swipe_up_gesture_default) ? 1 : 0;
+ final int swipeUpEnabled = Settings.Secure.getInt(mContext.getContentResolver(),
+ Settings.Secure.SWIPE_UP_TO_SWITCH_APPS_ENABLED, swipeUpDefaultValue);
+ pw.print(" swipeUpSetting="); pw.println(swipeUpEnabled != 0);
+ pw.print(" swipeUpSettingDefault="); pw.println(swipeUpDefaultValue != 0);
}
public interface OverviewProxyListener {
diff --git a/packages/SystemUI/src/com/android/systemui/doze/DozeUi.java b/packages/SystemUI/src/com/android/systemui/doze/DozeUi.java
index b7ff984..7863245 100644
--- a/packages/SystemUI/src/com/android/systemui/doze/DozeUi.java
+++ b/packages/SystemUI/src/com/android/systemui/doze/DozeUi.java
@@ -33,7 +33,6 @@
import com.android.systemui.util.wakelock.WakeLock;
import java.util.Calendar;
-import java.util.GregorianCalendar;
/**
* The policy controlling doze.
@@ -113,9 +112,7 @@
// The display buffers will be empty and need to be filled.
mHost.dozeTimeTick();
// The first frame may arrive when the display isn't ready yet.
- mHandler.postDelayed(mWakeLock.wrap(mHost::dozeTimeTick), 100);
- // The the delayed frame may arrive when the display isn't ready yet either.
- mHandler.postDelayed(mWakeLock.wrap(mHost::dozeTimeTick), 1000);
+ mHandler.postDelayed(mWakeLock.wrap(mHost::dozeTimeTick), 500);
}
scheduleTimeTick();
break;
@@ -184,7 +181,7 @@
}
private long roundToNextMinute(long timeInMillis) {
- Calendar calendar = GregorianCalendar.getInstance();
+ Calendar calendar = Calendar.getInstance();
calendar.setTimeInMillis(timeInMillis);
calendar.set(Calendar.MILLISECOND, 0);
calendar.set(Calendar.SECOND, 0);
diff --git a/packages/SystemUI/src/com/android/systemui/fragments/FragmentHostManager.java b/packages/SystemUI/src/com/android/systemui/fragments/FragmentHostManager.java
index f422737..0ed1cd1 100644
--- a/packages/SystemUI/src/com/android/systemui/fragments/FragmentHostManager.java
+++ b/packages/SystemUI/src/com/android/systemui/fragments/FragmentHostManager.java
@@ -51,7 +51,8 @@
private final View mRootView;
private final InterestingConfigChanges mConfigChanges = new InterestingConfigChanges(
ActivityInfo.CONFIG_FONT_SCALE | ActivityInfo.CONFIG_LOCALE
- | ActivityInfo.CONFIG_SCREEN_LAYOUT | ActivityInfo.CONFIG_ASSETS_PATHS);
+ | ActivityInfo.CONFIG_SCREEN_LAYOUT | ActivityInfo.CONFIG_ASSETS_PATHS
+ | ActivityInfo.CONFIG_UI_MODE);
private final FragmentService mManager;
private final ExtensionFragmentManager mPlugins = new ExtensionFragmentManager();
diff --git a/packages/SystemUI/src/com/android/systemui/globalactions/GlobalActionsDialog.java b/packages/SystemUI/src/com/android/systemui/globalactions/GlobalActionsDialog.java
index 532fa034a..201f40e 100644
--- a/packages/SystemUI/src/com/android/systemui/globalactions/GlobalActionsDialog.java
+++ b/packages/SystemUI/src/com/android/systemui/globalactions/GlobalActionsDialog.java
@@ -265,7 +265,7 @@
if (!mHasVibrator) {
mSilentModeAction = new SilentModeToggleAction();
} else {
- mSilentModeAction = new SilentModeTriStateAction(mContext, mAudioManager, mHandler);
+ mSilentModeAction = new SilentModeTriStateAction(mAudioManager, mHandler);
}
mAirplaneModeOn = new ToggleAction(
R.drawable.ic_lock_airplane_mode,
@@ -1211,12 +1211,10 @@
private final AudioManager mAudioManager;
private final Handler mHandler;
- private final Context mContext;
- SilentModeTriStateAction(Context context, AudioManager audioManager, Handler handler) {
+ SilentModeTriStateAction(AudioManager audioManager, Handler handler) {
mAudioManager = audioManager;
mHandler = handler;
- mContext = context;
}
private int ringerModeToIndex(int ringerMode) {
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java
index 120fa42..8d7eb6c 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java
@@ -346,6 +346,11 @@
*/
private WorkLockActivityController mWorkLockController;
+ /**
+ * @see #setPulsing(boolean)
+ */
+ private boolean mPulsing;
+
private boolean mLockLater;
private boolean mWakeAndUnlocking;
@@ -1801,10 +1806,12 @@
int flags = 0;
if (mStatusBarKeyguardViewManager.shouldDisableWindowAnimationsForUnlock()
- || mWakeAndUnlocking) {
- flags |= WindowManagerPolicyConstants.KEYGUARD_GOING_AWAY_FLAG_NO_WINDOW_ANIMATIONS;
+ || (mWakeAndUnlocking && !mPulsing)) {
+ flags |= WindowManagerPolicyConstants
+ .KEYGUARD_GOING_AWAY_FLAG_NO_WINDOW_ANIMATIONS;
}
- if (mStatusBarKeyguardViewManager.isGoingToNotificationShade()) {
+ if (mStatusBarKeyguardViewManager.isGoingToNotificationShade()
+ || (mWakeAndUnlocking && mPulsing)) {
flags |= WindowManagerPolicyConstants.KEYGUARD_GOING_AWAY_FLAG_TO_SHADE;
}
if (mStatusBarKeyguardViewManager.isUnlockWithWallpaper()) {
@@ -2110,6 +2117,13 @@
setShowingLocked(mShowing, aodShowing);
}
+ /**
+ * @param pulsing true when device temporarily wakes up to display an incoming notification.
+ */
+ public void setPulsing(boolean pulsing) {
+ mPulsing = pulsing;
+ }
+
private static class StartKeyguardExitAnimParams {
long startTime;
diff --git a/packages/SystemUI/src/com/android/systemui/pip/tv/PipManager.java b/packages/SystemUI/src/com/android/systemui/pip/tv/PipManager.java
old mode 100644
new mode 100755
index d9f923f..020c550
--- a/packages/SystemUI/src/com/android/systemui/pip/tv/PipManager.java
+++ b/packages/SystemUI/src/com/android/systemui/pip/tv/PipManager.java
@@ -262,12 +262,13 @@
entry = Pair.<String, String>create(packageAndClassName[0], null);
break;
case 2:
- if (packageAndClassName[1] != null
- && packageAndClassName[1].startsWith(".")) {
- entry = Pair.<String, String>create(
- packageAndClassName[0],
- packageAndClassName[0] + packageAndClassName[1]);
+ if (packageAndClassName[1] != null) {
+ entry = Pair.<String, String>create(packageAndClassName[0],
+ packageAndClassName[1].startsWith(".")
+ ? packageAndClassName[0] + packageAndClassName[1]
+ : packageAndClassName[1]);
}
+ break;
}
if (entry != null) {
sSettingsPackageAndClassNamePairList.add(entry);
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/NightDisplayTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/NightDisplayTile.java
index e0a9148..c41f087 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/NightDisplayTile.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/NightDisplayTile.java
@@ -26,7 +26,6 @@
import android.service.quicksettings.Tile;
import androidx.annotation.StringRes;
import android.text.TextUtils;
-import android.text.format.DateFormat;
import android.util.Log;
import android.widget.Switch;
@@ -37,8 +36,11 @@
import com.android.systemui.plugins.qs.QSTile.BooleanState;
import com.android.systemui.qs.tileimpl.QSTileImpl;
+import java.text.DateFormat;
import java.time.LocalTime;
import java.time.format.DateTimeFormatter;
+import java.util.Calendar;
+import java.util.TimeZone;
public class NightDisplayTile extends QSTileImpl<BooleanState>
implements ColorDisplayController.Callback {
@@ -144,13 +146,17 @@
toggleTimeStringRes = R.string.quick_settings_night_secondary_label_on_at;
}
- // Choose between just showing the hour or also showing the minutes (based on the
- // user-selected toggle time). This helps reduce how much space the label takes.
- toggleTimeFormat = DateTimeFormatter.ofPattern(
- DateFormat.is24HourFormat(mContext) ? PATTERN_HOUR_NINUTE_24 :
- toggleTime.getMinute() == 0 ? PATTERN_HOUR : PATTERN_HOUR_MINUTE);
-
- return mContext.getString(toggleTimeStringRes, toggleTime.format(toggleTimeFormat));
+ // TODO(b/111085930): Move this calendar snippet to a common code location that
+ // settings lib can also access.
+ final Calendar c = Calendar.getInstance();
+ DateFormat nightTileFormat = android.text.format.DateFormat.getTimeFormat(mContext);
+ nightTileFormat.setTimeZone(TimeZone.getTimeZone("UTC"));
+ c.setTimeZone(nightTileFormat.getTimeZone());
+ c.set(Calendar.HOUR_OF_DAY, toggleTime.getHour());
+ c.set(Calendar.MINUTE, toggleTime.getMinute());
+ c.set(Calendar.SECOND, 0);
+ c.set(Calendar.MILLISECOND, 0);
+ return mContext.getString(toggleTimeStringRes, nightTileFormat.format(c.getTime()));
default:
// No secondary label when auto mode is disabled.
diff --git a/packages/SystemUI/src/com/android/systemui/screenshot/GlobalScreenshot.java b/packages/SystemUI/src/com/android/systemui/screenshot/GlobalScreenshot.java
index 0ea941f..5eaee54 100644
--- a/packages/SystemUI/src/com/android/systemui/screenshot/GlobalScreenshot.java
+++ b/packages/SystemUI/src/com/android/systemui/screenshot/GlobalScreenshot.java
@@ -301,11 +301,11 @@
.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK | Intent.FLAG_ACTIVITY_NEW_TASK);
// Create a share action for the notification
- PendingIntent shareAction = PendingIntent.getBroadcast(context, 0,
+ PendingIntent shareAction = PendingIntent.getBroadcastAsUser(context, 0,
new Intent(context, GlobalScreenshot.ActionProxyReceiver.class)
.putExtra(EXTRA_ACTION_INTENT, sharingChooserIntent)
.putExtra(EXTRA_DISALLOW_ENTER_PIP, true),
- PendingIntent.FLAG_CANCEL_CURRENT);
+ PendingIntent.FLAG_CANCEL_CURRENT, UserHandle.SYSTEM);
Notification.Action.Builder shareActionBuilder = new Notification.Action.Builder(
R.drawable.ic_screenshot_share,
r.getString(com.android.internal.R.string.share), shareAction);
@@ -324,11 +324,11 @@
editIntent.addFlags(Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
// Create a edit action
- PendingIntent editAction = PendingIntent.getBroadcast(context, 1,
+ PendingIntent editAction = PendingIntent.getBroadcastAsUser(context, 1,
new Intent(context, GlobalScreenshot.ActionProxyReceiver.class)
.putExtra(EXTRA_ACTION_INTENT, editIntent)
.putExtra(EXTRA_CANCEL_NOTIFICATION, editIntent.getComponent() != null),
- PendingIntent.FLAG_CANCEL_CURRENT);
+ PendingIntent.FLAG_CANCEL_CURRENT, UserHandle.SYSTEM);
Notification.Action.Builder editActionBuilder = new Notification.Action.Builder(
R.drawable.ic_screenshot_edit,
r.getString(com.android.internal.R.string.screenshot_edit), editAction);
@@ -910,7 +910,7 @@
ActivityOptions opts = ActivityOptions.makeBasic();
opts.setDisallowEnterPictureInPictureWhileLaunching(
intent.getBooleanExtra(EXTRA_DISALLOW_ENTER_PIP, false));
- context.startActivityAsUser(actionIntent, opts.toBundle(),UserHandle.CURRENT);
+ context.startActivityAsUser(actionIntent, opts.toBundle(), UserHandle.CURRENT);
};
StatusBar statusBar = SysUiServiceProvider.getComponent(context, StatusBar.class);
statusBar.executeRunnableDismissingKeyguard(startActivityRunnable, null,
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/KeyguardIndicationController.java b/packages/SystemUI/src/com/android/systemui/statusbar/KeyguardIndicationController.java
index 294e2f4..551e8a9 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/KeyguardIndicationController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/KeyguardIndicationController.java
@@ -364,22 +364,41 @@
R.integer.wired_charging_keyguard_text_animation_duration_up);
int animateDownDuration = mContext.getResources().getInteger(
R.integer.wired_charging_keyguard_text_animation_duration_down);
+ textView.animate().cancel();
+ float translation = textView.getTranslationY();
textView.animate()
.translationYBy(yTranslation)
.setInterpolator(Interpolators.LINEAR)
.setDuration(animateUpDuration)
.setListener(new AnimatorListenerAdapter() {
+ private boolean mCancelled;
+
@Override
public void onAnimationStart(Animator animation) {
textView.switchIndication(indication);
}
+
+ @Override
+ public void onAnimationCancel(Animator animation) {
+ textView.setTranslationY(translation);
+ mCancelled = true;
+ }
+
@Override
public void onAnimationEnd(Animator animation) {
+ if (mCancelled) {
+ return;
+ }
textView.animate()
.setDuration(animateDownDuration)
.setInterpolator(Interpolators.BOUNCE)
- .translationYBy(-1 * yTranslation)
- .setListener(null);
+ .translationY(translation)
+ .setListener(new AnimatorListenerAdapter() {
+ @Override
+ public void onAnimationCancel(Animator animation) {
+ textView.setTranslationY(translation);
+ }
+ });
}
});
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/BiometricUnlockController.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/BiometricUnlockController.java
index 0b6fd13..2087a16 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/BiometricUnlockController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/BiometricUnlockController.java
@@ -216,15 +216,28 @@
// until the clock and the notifications are faded out.
mStatusBarWindowManager.setForceDozeBrightness(true);
}
- if (!wasDeviceInteractive) {
- if (DEBUG_BIO_WAKELOCK) {
- Log.i(TAG, "bio wakelock: Authenticated, waking up...");
+ // During wake and unlock, we need to draw black before waking up to avoid abrupt
+ // brightness changes due to display state transitions.
+ boolean alwaysOnEnabled = DozeParameters.getInstance(mContext).getAlwaysOn();
+ boolean delayWakeUp = mode == MODE_WAKE_AND_UNLOCK && alwaysOnEnabled;
+ Runnable wakeUp = ()-> {
+ if (!wasDeviceInteractive) {
+ if (DEBUG_BIO_WAKELOCK) {
+ Log.i(TAG, "bio wakelock: Authenticated, waking up...");
+ }
+ mPowerManager.wakeUp(SystemClock.uptimeMillis(), "android.policy:BIOMETRIC");
}
- mPowerManager.wakeUp(SystemClock.uptimeMillis(), "android.policy:BIOMETRIC");
+ if (delayWakeUp) {
+ mKeyguardViewMediator.onWakeAndUnlocking();
+ }
+ Trace.beginSection("release wake-and-unlock");
+ releaseBiometricWakeLock();
+ Trace.endSection();
+ };
+
+ if (!delayWakeUp) {
+ wakeUp.run();
}
- Trace.beginSection("release wake-and-unlock");
- releaseBiometricWakeLock();
- Trace.endSection();
switch (mMode) {
case MODE_DISMISS_BOUNCER:
Trace.beginSection("MODE_DISMISS");
@@ -257,7 +270,11 @@
mUpdateMonitor.awakenFromDream();
}
mStatusBarWindowManager.setStatusBarFocusable(false);
- mKeyguardViewMediator.onWakeAndUnlocking();
+ if (delayWakeUp) {
+ mHandler.postDelayed(wakeUp, 50);
+ } else {
+ mKeyguardViewMediator.onWakeAndUnlocking();
+ }
if (mStatusBar.getNavigationBarView() != null) {
mStatusBar.getNavigationBarView().setWakeAndUnlocking(true);
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/ConfigurationControllerImpl.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/ConfigurationControllerImpl.java
index 6f53844..7ddca17 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/ConfigurationControllerImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/ConfigurationControllerImpl.java
@@ -64,8 +64,9 @@
final float fontScale = newConfig.fontScale;
final int density = newConfig.densityDpi;
int uiMode = newConfig.uiMode & Configuration.UI_MODE_NIGHT_MASK;
+ boolean uiModeChanged = uiMode != mUiMode;
if (density != mDensity || fontScale != mFontScale
- || (mInCarMode && uiMode != mUiMode)) {
+ || (mInCarMode && uiModeChanged)) {
listeners.forEach(l -> {
if (mListeners.contains(l)) {
l.onDensityOrFontScaleChanged();
@@ -73,7 +74,6 @@
});
mDensity = density;
mFontScale = fontScale;
- mUiMode = uiMode;
}
final LocaleList localeList = newConfig.getLocales();
@@ -86,6 +86,15 @@
});
}
+ if (uiModeChanged) {
+ mUiMode = uiMode;
+ listeners.forEach(l -> {
+ if (mListeners.contains(l)) {
+ l.onUiModeChanged();
+ }
+ });
+ }
+
if ((mLastConfig.updateFrom(newConfig) & ActivityInfo.CONFIG_ASSETS_PATHS) != 0) {
listeners.forEach(l -> {
if (mListeners.contains(l)) {
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 492efa2..5a07dbd 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java
@@ -47,6 +47,7 @@
import android.view.ViewGroup;
import android.view.WindowInsets;
import android.view.accessibility.AccessibilityManager;
+import android.view.animation.Interpolator;
import android.widget.FrameLayout;
import com.android.internal.logging.MetricsLogger;
@@ -109,17 +110,20 @@
private static final AnimationProperties CLOCK_ANIMATION_PROPERTIES = new AnimationProperties()
.setDuration(StackStateAnimator.ANIMATION_DURATION_STANDARD);
private static final FloatProperty<NotificationPanelView> SET_DARK_AMOUNT_PROPERTY =
- new FloatProperty<NotificationPanelView>("mDarkAmount") {
+ new FloatProperty<NotificationPanelView>("mInterpolatedDarkAmount") {
+
@Override
public void setValue(NotificationPanelView object, float value) {
- object.setDarkAmount(value);
+ object.setDarkAmount(value, object.mDarkInterpolator.getInterpolation(value));
}
@Override
public Float get(NotificationPanelView object) {
- return object.mDarkAmount;
+ return object.mLinearDarkAmount;
}
};
+
+ private Interpolator mDarkInterpolator;
private final PowerManager mPowerManager;
private final AccessibilityManager mAccessibilityManager;
@@ -239,7 +243,18 @@
private int mIndicationBottomPadding;
private int mAmbientIndicationBottomPadding;
private boolean mIsFullWidth;
- private float mDarkAmount;
+
+ /**
+ * Current dark amount that follows regular interpolation curve of animation.
+ */
+ private float mInterpolatedDarkAmount;
+
+ /**
+ * Dark amount that animates from 0 to 1 or vice-versa in linear manner, even if the
+ * interpolation curve is different.
+ */
+ private float mLinearDarkAmount;
+
private float mDarkAmountTarget;
private boolean mPulsing;
private LockscreenGestureLogger mLockscreenGestureLogger = new LockscreenGestureLogger();
@@ -394,7 +409,7 @@
false);
addView(mKeyguardBottomArea, index);
initBottomArea();
- setDarkAmount(mDarkAmount);
+ setDarkAmount(mLinearDarkAmount, mInterpolatedDarkAmount);
setKeyguardStatusViewVisibility(mStatusBarState, false, false);
setKeyguardBottomAreaVisibility(mStatusBarState, false);
@@ -508,7 +523,7 @@
getExpandedFraction(),
totalHeight,
mKeyguardStatusView.getHeight(),
- mDarkAmount,
+ mInterpolatedDarkAmount,
mStatusBar.isKeyguardCurrentlySecure(),
mPulsing,
mBouncerTop);
@@ -1919,7 +1934,7 @@
if (view == null && mQsExpanded) {
return;
}
- if (needsAnimation && mDarkAmount == 0) {
+ if (needsAnimation && mInterpolatedDarkAmount == 0) {
mAnimateNextPositionUpdate = true;
}
ExpandableView firstChildNotGone = mNotificationStackScroller.getFirstChildNotGone();
@@ -2729,20 +2744,28 @@
}
mDarkAmountTarget = darkAmount;
if (animate) {
+ if (mInterpolatedDarkAmount == 0f || mInterpolatedDarkAmount == 1f) {
+ mDarkInterpolator = dozing
+ ? Interpolators.FAST_OUT_SLOW_IN
+ : Interpolators.TOUCH_RESPONSE_REVERSE;
+ }
+ mNotificationStackScroller.notifyDarkAnimationStart(dozing);
mDarkAnimator = ObjectAnimator.ofFloat(this, SET_DARK_AMOUNT_PROPERTY, darkAmount);
- mDarkAnimator.setInterpolator(Interpolators.LINEAR_OUT_SLOW_IN);
- mDarkAnimator.setDuration(StackStateAnimator.ANIMATION_DURATION_WAKEUP);
+ mDarkAnimator.setInterpolator(Interpolators.LINEAR);
+ mDarkAnimator.setDuration(mNotificationStackScroller.getDarkAnimationDuration(dozing));
mDarkAnimator.start();
} else {
- setDarkAmount(darkAmount);
+ setDarkAmount(darkAmount, darkAmount);
}
}
- private void setDarkAmount(float amount) {
- mDarkAmount = amount;
- mKeyguardStatusView.setDarkAmount(mDarkAmount);
- mKeyguardBottomArea.setDarkAmount(mDarkAmount);
+ private void setDarkAmount(float linearAmount, float amount) {
+ mInterpolatedDarkAmount = amount;
+ mLinearDarkAmount = linearAmount;
+ mKeyguardStatusView.setDarkAmount(mInterpolatedDarkAmount);
+ mKeyguardBottomArea.setDarkAmount(mInterpolatedDarkAmount);
positionClockAndNotifications();
+ mNotificationStackScroller.setDarkAmount(linearAmount, mInterpolatedDarkAmount);
}
public void setPulsing(boolean pulsing) {
@@ -2767,7 +2790,7 @@
public void dozeTimeTick() {
mKeyguardStatusView.dozeTimeTick();
mKeyguardBottomArea.dozeTimeTick();
- if (mDarkAmount > 0) {
+ if (mInterpolatedDarkAmount > 0) {
positionClockAndNotifications();
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/ScrimState.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/ScrimState.java
index cdbad59..19015fc 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/ScrimState.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/ScrimState.java
@@ -146,7 +146,7 @@
mAnimationDuration = StatusBar.FADE_KEYGUARD_DURATION;
mAnimateChange = !mLaunchingAffordanceWithPreview;
- if (previousState == ScrimState.AOD || previousState == ScrimState.PULSING) {
+ if (previousState == ScrimState.AOD) {
// Fade from black to transparent when coming directly from AOD
updateScrimColor(mScrimInFront, 1, Color.BLACK);
updateScrimColor(mScrimBehind, 1, Color.BLACK);
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 e3e791d..7cf2c33 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java
@@ -330,12 +330,6 @@
/** If true, the lockscreen will show a distinct wallpaper */
private static final boolean ENABLE_LOCKSCREEN_WALLPAPER = true;
- /** Whether to force dark theme if Configuration.UI_MODE_NIGHT_YES. */
- private static final boolean DARK_THEME_IN_NIGHT_MODE = true;
-
- /** Whether to switch the device into night mode in battery saver. */
- private static final boolean NIGHT_MODE_IN_BATTERY_SAVER = true;
-
/**
* Never let the alpha become zero for surfaces that draw with SRC - otherwise the RenderNode
* won't draw anything and uninitialized memory will show through
@@ -580,7 +574,7 @@
= (KeyguardMonitorImpl) Dependency.get(KeyguardMonitor.class);
private BatteryController mBatteryController;
protected boolean mPanelExpanded;
- private IOverlayManager mOverlayManager;
+ private UiModeManager mUiModeManager;
private boolean mKeyguardRequested;
private boolean mIsKeyguard;
private LogMaker mStatusBarStateLog;
@@ -641,8 +635,7 @@
mWakefulnessLifecycle.addObserver(mWakefulnessObserver);
mBatteryController = Dependency.get(BatteryController.class);
mAssistManager = Dependency.get(AssistManager.class);
- mOverlayManager = IOverlayManager.Stub.asInterface(
- ServiceManager.getService(Context.OVERLAY_SERVICE));
+ mUiModeManager = mContext.getSystemService(UiModeManager.class);
mLockscreenUserManager = Dependency.get(NotificationLockscreenUserManager.class);
mGutsManager = Dependency.get(NotificationGutsManager.class);
mMediaManager = Dependency.get(NotificationMediaManager.class);
@@ -948,10 +941,6 @@
if (mDozeServiceHost != null) {
mDozeServiceHost.firePowerSaveChanged(isPowerSave);
}
- if (NIGHT_MODE_IN_BATTERY_SAVER) {
- mContext.getSystemService(UiModeManager.class).setNightMode(
- isPowerSave ? UiModeManager.MODE_NIGHT_YES : UiModeManager.MODE_NIGHT_NO);
- }
}
@Override
@@ -1199,6 +1188,18 @@
}
}
+ @Override
+ public void onUiModeChanged() {
+ // UiMode will change the style was already evaluated.
+ // We need to force the re-evaluation to make sure that all parents
+ // are up to date and new attrs will be rettrieved.
+ mContext.getTheme().applyStyle(mContext.getThemeResId(), true);
+
+ if (mBrightnessMirrorController != null) {
+ mBrightnessMirrorController.onUiModeChanged();
+ }
+ }
+
private void inflateEmptyShadeView() {
if (mStackScroller == null) {
return;
@@ -2099,17 +2100,6 @@
updateTheme();
}
- public boolean isUsingDarkTheme() {
- OverlayInfo themeInfo = null;
- try {
- themeInfo = mOverlayManager.getOverlayInfo("com.android.systemui.theme.dark",
- mLockscreenUserManager.getCurrentUserId());
- } catch (RemoteException e) {
- e.printStackTrace();
- }
- return themeInfo != null && themeInfo.isEnabled();
- }
-
@Nullable
public View getAmbientIndicationContainer() {
return mAmbientIndicationContainer;
@@ -2812,11 +2802,11 @@
mStackScroller.dump(fd, pw, args);
}
pw.println(" Theme:");
- if (mOverlayManager == null) {
- pw.println(" overlay manager not initialized!");
- } else {
- pw.println(" dark overlay on: " + isUsingDarkTheme());
- }
+ String nightMode = mUiModeManager == null ? "null" : mUiModeManager.getNightMode() + "";
+ pw.println(" dark theme: " + nightMode +
+ " (auto: " + UiModeManager.MODE_NIGHT_AUTO +
+ ", yes: " + UiModeManager.MODE_NIGHT_YES +
+ ", no: " + UiModeManager.MODE_NIGHT_NO + ")");
final boolean lightWpTheme = mContext.getThemeResId() == R.style.Theme_SystemUI_Light;
pw.println(" light wallpaper theme: " + lightWpTheme);
@@ -3149,7 +3139,6 @@
public void onConfigChanged(Configuration newConfig) {
updateResources();
updateDisplaySize(); // populates mDisplayMetrics
- updateTheme();
if (DEBUG) {
Log.v(TAG, "configuration changed: " + mContext.getResources().getConfiguration());
@@ -3887,27 +3876,6 @@
protected void updateTheme() {
final boolean inflated = mStackScroller != null && mStatusBarWindowManager != null;
- // The system wallpaper defines if QS should be light or dark.
- WallpaperColors systemColors = mColorExtractor
- .getWallpaperColors(WallpaperManager.FLAG_SYSTEM);
- final boolean wallpaperWantsDarkTheme = systemColors != null
- && (systemColors.getColorHints() & WallpaperColors.HINT_SUPPORTS_DARK_THEME) != 0;
- final Configuration config = mContext.getResources().getConfiguration();
- final boolean nightModeWantsDarkTheme = DARK_THEME_IN_NIGHT_MODE
- && (config.uiMode & Configuration.UI_MODE_NIGHT_MASK)
- == Configuration.UI_MODE_NIGHT_YES;
- final boolean useDarkTheme = wallpaperWantsDarkTheme || nightModeWantsDarkTheme;
- if (isUsingDarkTheme() != useDarkTheme) {
- mUiOffloadThread.submit(() -> {
- try {
- mOverlayManager.setEnabled("com.android.systemui.theme.dark",
- useDarkTheme, mLockscreenUserManager.getCurrentUserId());
- } catch (RemoteException e) {
- Log.w(TAG, "Can't change theme", e);
- }
- });
- }
-
// Lock wallpaper defines the color of the majority of the views, hence we'll use it
// to set our default theme.
final boolean lockDarkText = mColorExtractor.getColors(WallpaperManager.FLAG_LOCK, true
@@ -4871,6 +4839,7 @@
}
private void setPulsing(boolean pulsing) {
+ mKeyguardViewMediator.setPulsing(pulsing);
mNotificationPanel.setPulsing(pulsing);
mVisualStabilityManager.setPulsing(pulsing);
mIgnoreTouchWhilePulsing = false;
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 fadc0ea..a38328a 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowManager.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowManager.java
@@ -180,6 +180,15 @@
mLpChanged.softInputMode = WindowManager.LayoutParams.SOFT_INPUT_ADJUST_RESIZE;
}
+ private void applyExpandedFlag(State state) {
+ if (state.panelExpanded || state.isKeyguardShowingAndNotOccluded() || state.bouncerShowing
+ || ENABLE_REMOTE_INPUT && state.remoteInputActive) {
+ mLpChanged.privateFlags |= LayoutParams.PRIVATE_FLAG_STATUS_BAR_EXPANDED;
+ } else {
+ mLpChanged.privateFlags &= ~LayoutParams.PRIVATE_FLAG_STATUS_BAR_EXPANDED;
+ }
+ }
+
private void applyHeight(State state) {
boolean expanded = isExpanded(state);
if (state.forcePluginOpen) {
@@ -234,6 +243,7 @@
applyKeyguardFlags(state);
applyForceStatusBarVisibleFlag(state);
applyFocusableFlag(state);
+ applyExpandedFlag(state);
adjustScreenOrientation(state);
applyHeight(state);
applyUserActivityTimeout(state);
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 e9bdc68..b198678 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/BrightnessMirrorController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/BrightnessMirrorController.java
@@ -19,7 +19,6 @@
import android.annotation.NonNull;
import android.content.res.Resources;
import android.util.ArraySet;
-import android.view.ContextThemeWrapper;
import android.view.LayoutInflater;
import android.view.View;
import android.widget.FrameLayout;
@@ -105,11 +104,9 @@
}
private void reinflate() {
- ContextThemeWrapper qsThemeContext =
- new ContextThemeWrapper(mBrightnessMirror.getContext(), R.style.qs_theme);
int index = mStatusBarWindow.indexOfChild(mBrightnessMirror);
mStatusBarWindow.removeView(mBrightnessMirror);
- mBrightnessMirror = LayoutInflater.from(qsThemeContext).inflate(
+ mBrightnessMirror = LayoutInflater.from(mBrightnessMirror.getContext()).inflate(
R.layout.brightness_mirror, mStatusBarWindow, false);
mStatusBarWindow.addView(mBrightnessMirror, index);
@@ -129,6 +126,10 @@
mBrightnessMirrorListeners.remove(listener);
}
+ public void onUiModeChanged() {
+ reinflate();
+ }
+
public interface BrightnessMirrorListener {
void onBrightnessMirrorReinflated(View brightnessMirror);
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/ConfigurationController.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/ConfigurationController.java
index 3dca371..8c631d9 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/ConfigurationController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/ConfigurationController.java
@@ -28,6 +28,7 @@
default void onConfigChanged(Configuration newConfig) {}
default void onDensityOrFontScaleChanged() {}
default void onOverlayChanged() {}
+ default void onUiModeChanged() {}
default void onLocaleListChanged() {}
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkControllerImpl.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkControllerImpl.java
index 25261c0..f729120 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkControllerImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkControllerImpl.java
@@ -976,7 +976,7 @@
private SubscriptionInfo addSignalController(int id, int simSlotIndex) {
SubscriptionInfo info = new SubscriptionInfo(id, "", simSlotIndex, "", "", 0, 0, "", 0,
- null, 0, 0, "");
+ null, null, null, "");
MobileSignalController controller = new MobileSignalController(mContext,
mConfig, mHasMobileDataFeature, mPhone, mCallbackHandler, this, info,
mSubDefaults, mReceiverHandler.getLooper());
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 052e8e1..6fc4911 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/stack/NotificationStackScrollLayout.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/stack/NotificationStackScrollLayout.java
@@ -34,7 +34,6 @@
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
-import android.graphics.Path;
import android.graphics.PointF;
import android.graphics.PorterDuff;
import android.graphics.PorterDuffXfermode;
@@ -46,11 +45,9 @@
import androidx.annotation.VisibleForTesting;
import androidx.core.graphics.ColorUtils;
import android.util.AttributeSet;
-import android.util.FloatProperty;
import android.util.Log;
import android.util.MathUtils;
import android.util.Pair;
-import android.util.Property;
import android.view.ContextThemeWrapper;
import android.view.InputDevice;
import android.view.MotionEvent;
@@ -375,25 +372,22 @@
private boolean mScrollable;
private View mForcedScroll;
private View mNeedingPulseAnimation;
- private float mDarkAmount = 0f;
+
+ /**
+ * @see #setDarkAmount(float, float)
+ */
+ private float mInterpolatedDarkAmount = 0f;
+
+ /**
+ * @see #setDarkAmount(float, float)
+ */
+ private float mLinearDarkAmount = 0f;
/**
* How fast the background scales in the X direction as a factor of the Y expansion.
*/
private float mBackgroundXFactor = 1f;
- private static final Property<NotificationStackScrollLayout, Float> DARK_AMOUNT =
- new FloatProperty<NotificationStackScrollLayout>("darkAmount") {
- @Override
- public void setValue(NotificationStackScrollLayout object, float value) {
- object.setDarkAmount(value);
- }
- @Override
- public Float get(NotificationStackScrollLayout object) {
- return object.getDarkAmount();
- }
- };
- private ObjectAnimator mDarkAmountAnimator;
private boolean mUsingLightTheme;
private boolean mQsExpanded;
private boolean mForwardScrollable;
@@ -424,6 +418,8 @@
private NotificationIconAreaController mIconAreaController;
private float mVerticalPanelTranslation;
+ private Interpolator mDarkXInterpolator = Interpolators.FAST_OUT_SLOW_IN;
+
public NotificationStackScrollLayout(Context context) {
this(context, null);
}
@@ -558,16 +554,16 @@
canvas.drawRect(darkLeft, darkTop, darkRight, darkBottom, mBackgroundPaint);
}
} else {
- float inverseDark = 1 - mDarkAmount;
- float yProgress = Interpolators.FAST_OUT_SLOW_IN.getInterpolation(inverseDark);
- float xProgress = Interpolators.FAST_OUT_SLOW_IN
- .getInterpolation(inverseDark * mBackgroundXFactor);
+ float yProgress = 1 - mInterpolatedDarkAmount;
+ float xProgress = mDarkXInterpolator.getInterpolation(
+ (1 - mLinearDarkAmount) * mBackgroundXFactor);
mBackgroundAnimationRect.set(
(int) MathUtils.lerp(darkLeft, lockScreenLeft, xProgress),
(int) MathUtils.lerp(darkTop, lockScreenTop, yProgress),
(int) MathUtils.lerp(darkRight, lockScreenRight, xProgress),
(int) MathUtils.lerp(darkBottom, lockScreenBottom, yProgress));
+
if (!mAmbientState.isDark() || mFirstVisibleBackgroundChild != null) {
canvas.drawRoundRect(mBackgroundAnimationRect.left, mBackgroundAnimationRect.top,
mBackgroundAnimationRect.right, mBackgroundAnimationRect.bottom,
@@ -585,14 +581,15 @@
float alpha =
BACKGROUND_ALPHA_DIMMED + (1 - BACKGROUND_ALPHA_DIMMED) * (1.0f - mDimAmount);
- alpha *= 1f - mDarkAmount;
+ alpha *= 1f - mInterpolatedDarkAmount;
// We need to manually blend in the background color.
int scrimColor = mScrimController.getBackgroundColor();
int awakeColor = ColorUtils.blendARGB(scrimColor, mBgColor, alpha);
// Interpolate between semi-transparent notification panel background color
// and white AOD separator.
- float colorInterpolation = Interpolators.DECELERATE_QUINT.getInterpolation(mDarkAmount);
+ float colorInterpolation = Interpolators.DECELERATE_QUINT.getInterpolation(
+ mInterpolatedDarkAmount);
int color = ColorUtils.blendARGB(awakeColor, Color.WHITE, colorInterpolation);
if (mCachedBackgroundColor != color) {
@@ -740,7 +737,8 @@
}
private void updateAlgorithmHeightAndPadding() {
- mTopPadding = (int) MathUtils.lerp(mRegularTopPadding, mDarkTopPadding, mDarkAmount);
+ mTopPadding = (int) MathUtils.lerp(mRegularTopPadding, mDarkTopPadding,
+ mInterpolatedDarkAmount);
mAmbientState.setLayoutHeight(getLayoutHeight());
updateAlgorithmLayoutMinHeight();
mAmbientState.setTopPadding(mTopPadding);
@@ -965,7 +963,7 @@
}
public void updateClipping() {
- boolean animatingClipping = mDarkAmount > 0 && mDarkAmount < 1;
+ boolean animatingClipping = mInterpolatedDarkAmount > 0 && mInterpolatedDarkAmount < 1;
boolean clipped = mRequestedClipBounds != null && !mInHeadsUpPinnedMode
&& !mHeadsUpAnimatingAway;
if (mIsClipped != clipped) {
@@ -2425,7 +2423,7 @@
return;
}
- final boolean awake = mDarkAmount != 0 || mAmbientState.isDark();
+ final boolean awake = mInterpolatedDarkAmount != 0 || mAmbientState.isDark();
mScrimController.setExcludedBackgroundArea(
mFadingOut || mParentNotFullyVisible || awake || mIsClipped ? null
: mCurrentBounds);
@@ -3417,7 +3415,6 @@
.animateY(mShelf));
ev.darkAnimationOriginIndex = mDarkAnimationOriginIndex;
mAnimationEvents.add(ev);
- startDarkAmountAnimation();
}
mDarkNeedsAnimation = false;
}
@@ -3993,11 +3990,8 @@
if (animate && mAnimationsEnabled) {
mDarkNeedsAnimation = true;
mDarkAnimationOriginIndex = findDarkAnimationOriginIndex(touchWakeUpScreenLocation);
- mNeedsAnimation = true;
+ mNeedsAnimation = true;
} else {
- if (mDarkAmountAnimator != null) {
- mDarkAmountAnimator.cancel();
- }
setDarkAmount(dark ? 1f : 0f);
updateBackground();
}
@@ -4008,7 +4002,7 @@
}
private void updatePanelTranslation() {
- setTranslationX(mVerticalPanelTranslation + mAntiBurnInOffsetX * mDarkAmount);
+ setTranslationX(mVerticalPanelTranslation + mAntiBurnInOffsetX * mInterpolatedDarkAmount);
}
public void setVerticalPanelTranslation(float verticalPanelTranslation) {
@@ -4027,9 +4021,22 @@
}
private void setDarkAmount(float darkAmount) {
- mDarkAmount = darkAmount;
+ setDarkAmount(darkAmount, darkAmount);
+ }
+
+ /**
+ * Sets the current dark amount.
+ *
+ * @param linearDarkAmount The dark amount that follows linear interpoloation in the animation,
+ * i.e. animates from 0 to 1 or vice-versa in a linear manner.
+ * @param interpolatedDarkAmount The dark amount that follows the actual interpolation of the
+ * animation curve.
+ */
+ public void setDarkAmount(float linearDarkAmount, float interpolatedDarkAmount) {
+ mLinearDarkAmount = linearDarkAmount;
+ mInterpolatedDarkAmount = interpolatedDarkAmount;
boolean wasFullyDark = mAmbientState.isFullyDark();
- mAmbientState.setDarkAmount(darkAmount);
+ mAmbientState.setDarkAmount(interpolatedDarkAmount);
boolean nowFullyDark = mAmbientState.isFullyDark();
if (nowFullyDark != wasFullyDark) {
updateContentHeight();
@@ -4047,42 +4054,24 @@
requestChildrenUpdate();
}
- public float getDarkAmount() {
- return mDarkAmount;
+ public void notifyDarkAnimationStart(boolean dark) {
+ // We only swap the scaling factor if we're fully dark or fully awake to avoid
+ // interpolation issues when playing with the power button.
+ if (mInterpolatedDarkAmount == 0 || mInterpolatedDarkAmount == 1) {
+ mBackgroundXFactor = dark ? 1.8f : 1.5f;
+ mDarkXInterpolator = dark
+ ? Interpolators.FAST_OUT_SLOW_IN_REVERSE
+ : Interpolators.FAST_OUT_SLOW_IN;
+ }
}
- /**
- * Cancel any previous dark animations - to avoid race conditions - and creates a new one.
- * This function also sets {@code mBackgroundXFactor} based on the current {@code mDarkAmount}.
- */
- private void startDarkAmountAnimation() {
- boolean dark = mAmbientState.isDark();
- if (mDarkAmountAnimator != null) {
- mDarkAmountAnimator.cancel();
- }
-
+ public long getDarkAnimationDuration(boolean dark) {
long duration = StackStateAnimator.ANIMATION_DURATION_WAKEUP;
// Longer animation when sleeping with more than 1 notification
if (dark && getNotGoneChildCount() > 2) {
duration *= 1.2f;
}
-
- mDarkAmountAnimator = ObjectAnimator.ofFloat(this, DARK_AMOUNT, mDarkAmount,
- dark ? 1f : 0);
- // We only swap the scaling factor if we're fully dark or fully awake to avoid
- // interpolation issues when playing with the power button.
- if (mDarkAmount == 0 || mDarkAmount == 1) {
- mBackgroundXFactor = dark ? 2.5f : 1.5f;
- }
- mDarkAmountAnimator.setDuration(duration);
- mDarkAmountAnimator.setInterpolator(Interpolators.LINEAR);
- mDarkAmountAnimator.addListener(new AnimatorListenerAdapter() {
- @Override
- public void onAnimationEnd(Animator animation) {
- mDarkAmountAnimator = null;
- }
- });
- mDarkAmountAnimator.start();
+ return duration;
}
private int findDarkAnimationOriginIndex(@Nullable PointF screenLocation) {
diff --git a/packages/SystemUI/src/com/android/systemui/util/wakelock/DelayedWakeLock.java b/packages/SystemUI/src/com/android/systemui/util/wakelock/DelayedWakeLock.java
index a901e88..b835909 100644
--- a/packages/SystemUI/src/com/android/systemui/util/wakelock/DelayedWakeLock.java
+++ b/packages/SystemUI/src/com/android/systemui/util/wakelock/DelayedWakeLock.java
@@ -23,7 +23,7 @@
*/
public class DelayedWakeLock implements WakeLock {
- private static final long RELEASE_DELAY_MS = 140;
+ private static final long RELEASE_DELAY_MS = 100;
private final Handler mHandler;
private final WakeLock mInner;
diff --git a/packages/SystemUI/src/com/android/systemui/volume/VolumeDialogComponent.java b/packages/SystemUI/src/com/android/systemui/volume/VolumeDialogComponent.java
index dd55264..2861dff 100644
--- a/packages/SystemUI/src/com/android/systemui/volume/VolumeDialogComponent.java
+++ b/packages/SystemUI/src/com/android/systemui/volume/VolumeDialogComponent.java
@@ -61,7 +61,7 @@
private final VolumeDialogControllerImpl mController;
private final InterestingConfigChanges mConfigChanges = new InterestingConfigChanges(
ActivityInfo.CONFIG_FONT_SCALE | ActivityInfo.CONFIG_LOCALE
- | ActivityInfo.CONFIG_ASSETS_PATHS);
+ | ActivityInfo.CONFIG_ASSETS_PATHS | ActivityInfo.CONFIG_UI_MODE);
private VolumeDialog mDialog;
private VolumePolicy mVolumePolicy = new VolumePolicy(
DEFAULT_VOLUME_DOWN_TO_ENTER_SILENT, // volumeDownToEnterSilent
diff --git a/packages/overlays/SysuiDarkThemeOverlay/Android.mk b/packages/overlays/SysuiDarkThemeOverlay/Android.mk
deleted file mode 100644
index 7b277bc..0000000
--- a/packages/overlays/SysuiDarkThemeOverlay/Android.mk
+++ /dev/null
@@ -1,14 +0,0 @@
-LOCAL_PATH:= $(call my-dir)
-include $(CLEAR_VARS)
-
-LOCAL_RRO_THEME := SysuiDarkTheme
-LOCAL_CERTIFICATE := platform
-
-LOCAL_SRC_FILES := $(call all-subdir-java-files)
-
-LOCAL_RESOURCE_DIR := $(LOCAL_PATH)/res
-
-LOCAL_PACKAGE_NAME := SysuiDarkThemeOverlay
-LOCAL_SDK_VERSION := current
-
-include $(BUILD_RRO_PACKAGE)
diff --git a/packages/overlays/SysuiDarkThemeOverlay/AndroidManifest.xml b/packages/overlays/SysuiDarkThemeOverlay/AndroidManifest.xml
deleted file mode 100644
index 8b6ee2b..0000000
--- a/packages/overlays/SysuiDarkThemeOverlay/AndroidManifest.xml
+++ /dev/null
@@ -1,8 +0,0 @@
-<manifest xmlns:android="http://schemas.android.com/apk/res/android"
- package="com.android.systemui.theme.dark"
- android:versionCode="1"
- android:versionName="1.0">
- <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-af/strings.xml b/packages/overlays/SysuiDarkThemeOverlay/res/values-af/strings.xml
deleted file mode 100644
index 33c6982..0000000
--- a/packages/overlays/SysuiDarkThemeOverlay/res/values-af/strings.xml
+++ /dev/null
@@ -1,23 +0,0 @@
-<?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.
- */
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="sysui_overlay_dark" msgid="557336259295713662">"Donker"</string>
-</resources>
diff --git a/packages/overlays/SysuiDarkThemeOverlay/res/values-am/strings.xml b/packages/overlays/SysuiDarkThemeOverlay/res/values-am/strings.xml
deleted file mode 100644
index 5979569..0000000
--- a/packages/overlays/SysuiDarkThemeOverlay/res/values-am/strings.xml
+++ /dev/null
@@ -1,23 +0,0 @@
-<?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.
- */
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="sysui_overlay_dark" msgid="557336259295713662">"ጨለማ"</string>
-</resources>
diff --git a/packages/overlays/SysuiDarkThemeOverlay/res/values-ar/strings.xml b/packages/overlays/SysuiDarkThemeOverlay/res/values-ar/strings.xml
deleted file mode 100644
index 7b20c01..0000000
--- a/packages/overlays/SysuiDarkThemeOverlay/res/values-ar/strings.xml
+++ /dev/null
@@ -1,23 +0,0 @@
-<?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.
- */
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="sysui_overlay_dark" msgid="557336259295713662">"داكن"</string>
-</resources>
diff --git a/packages/overlays/SysuiDarkThemeOverlay/res/values-as/strings.xml b/packages/overlays/SysuiDarkThemeOverlay/res/values-as/strings.xml
deleted file mode 100644
index 0910e7e..0000000
--- a/packages/overlays/SysuiDarkThemeOverlay/res/values-as/strings.xml
+++ /dev/null
@@ -1,23 +0,0 @@
-<?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.
- */
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="sysui_overlay_dark" msgid="557336259295713662">"গাঢ়"</string>
-</resources>
diff --git a/packages/overlays/SysuiDarkThemeOverlay/res/values-az/strings.xml b/packages/overlays/SysuiDarkThemeOverlay/res/values-az/strings.xml
deleted file mode 100644
index a9db75c..0000000
--- a/packages/overlays/SysuiDarkThemeOverlay/res/values-az/strings.xml
+++ /dev/null
@@ -1,23 +0,0 @@
-<?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.
- */
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="sysui_overlay_dark" msgid="557336259295713662">"Qaranlıq"</string>
-</resources>
diff --git a/packages/overlays/SysuiDarkThemeOverlay/res/values-b+sr+Latn/strings.xml b/packages/overlays/SysuiDarkThemeOverlay/res/values-b+sr+Latn/strings.xml
deleted file mode 100644
index b63dcbc..0000000
--- a/packages/overlays/SysuiDarkThemeOverlay/res/values-b+sr+Latn/strings.xml
+++ /dev/null
@@ -1,23 +0,0 @@
-<?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.
- */
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="sysui_overlay_dark" msgid="557336259295713662">"Tamno"</string>
-</resources>
diff --git a/packages/overlays/SysuiDarkThemeOverlay/res/values-be/strings.xml b/packages/overlays/SysuiDarkThemeOverlay/res/values-be/strings.xml
deleted file mode 100644
index eb875b3..0000000
--- a/packages/overlays/SysuiDarkThemeOverlay/res/values-be/strings.xml
+++ /dev/null
@@ -1,23 +0,0 @@
-<?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.
- */
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="sysui_overlay_dark" msgid="557336259295713662">"Цёмная"</string>
-</resources>
diff --git a/packages/overlays/SysuiDarkThemeOverlay/res/values-bg/strings.xml b/packages/overlays/SysuiDarkThemeOverlay/res/values-bg/strings.xml
deleted file mode 100644
index 7b39462..0000000
--- a/packages/overlays/SysuiDarkThemeOverlay/res/values-bg/strings.xml
+++ /dev/null
@@ -1,23 +0,0 @@
-<?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.
- */
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="sysui_overlay_dark" msgid="557336259295713662">"Тъмно"</string>
-</resources>
diff --git a/packages/overlays/SysuiDarkThemeOverlay/res/values-bn/strings.xml b/packages/overlays/SysuiDarkThemeOverlay/res/values-bn/strings.xml
deleted file mode 100644
index 0910e7e..0000000
--- a/packages/overlays/SysuiDarkThemeOverlay/res/values-bn/strings.xml
+++ /dev/null
@@ -1,23 +0,0 @@
-<?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.
- */
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="sysui_overlay_dark" msgid="557336259295713662">"গাঢ়"</string>
-</resources>
diff --git a/packages/overlays/SysuiDarkThemeOverlay/res/values-bs/strings.xml b/packages/overlays/SysuiDarkThemeOverlay/res/values-bs/strings.xml
deleted file mode 100644
index b63dcbc..0000000
--- a/packages/overlays/SysuiDarkThemeOverlay/res/values-bs/strings.xml
+++ /dev/null
@@ -1,23 +0,0 @@
-<?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.
- */
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="sysui_overlay_dark" msgid="557336259295713662">"Tamno"</string>
-</resources>
diff --git a/packages/overlays/SysuiDarkThemeOverlay/res/values-ca/strings.xml b/packages/overlays/SysuiDarkThemeOverlay/res/values-ca/strings.xml
deleted file mode 100644
index 02ee226..0000000
--- a/packages/overlays/SysuiDarkThemeOverlay/res/values-ca/strings.xml
+++ /dev/null
@@ -1,23 +0,0 @@
-<?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.
- */
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="sysui_overlay_dark" msgid="557336259295713662">"Fosc"</string>
-</resources>
diff --git a/packages/overlays/SysuiDarkThemeOverlay/res/values-cs/strings.xml b/packages/overlays/SysuiDarkThemeOverlay/res/values-cs/strings.xml
deleted file mode 100644
index 5d11f07..0000000
--- a/packages/overlays/SysuiDarkThemeOverlay/res/values-cs/strings.xml
+++ /dev/null
@@ -1,23 +0,0 @@
-<?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.
- */
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="sysui_overlay_dark" msgid="557336259295713662">"Tmavé"</string>
-</resources>
diff --git a/packages/overlays/SysuiDarkThemeOverlay/res/values-da/strings.xml b/packages/overlays/SysuiDarkThemeOverlay/res/values-da/strings.xml
deleted file mode 100644
index 460ebe7..0000000
--- a/packages/overlays/SysuiDarkThemeOverlay/res/values-da/strings.xml
+++ /dev/null
@@ -1,23 +0,0 @@
-<?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.
- */
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="sysui_overlay_dark" msgid="557336259295713662">"Mørk"</string>
-</resources>
diff --git a/packages/overlays/SysuiDarkThemeOverlay/res/values-de/strings.xml b/packages/overlays/SysuiDarkThemeOverlay/res/values-de/strings.xml
deleted file mode 100644
index 4b54b8e..0000000
--- a/packages/overlays/SysuiDarkThemeOverlay/res/values-de/strings.xml
+++ /dev/null
@@ -1,23 +0,0 @@
-<?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.
- */
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="sysui_overlay_dark" msgid="557336259295713662">"Dunkel"</string>
-</resources>
diff --git a/packages/overlays/SysuiDarkThemeOverlay/res/values-el/strings.xml b/packages/overlays/SysuiDarkThemeOverlay/res/values-el/strings.xml
deleted file mode 100644
index c58061d..0000000
--- a/packages/overlays/SysuiDarkThemeOverlay/res/values-el/strings.xml
+++ /dev/null
@@ -1,23 +0,0 @@
-<?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.
- */
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="sysui_overlay_dark" msgid="557336259295713662">"Σκοτεινό"</string>
-</resources>
diff --git a/packages/overlays/SysuiDarkThemeOverlay/res/values-en-rAU/strings.xml b/packages/overlays/SysuiDarkThemeOverlay/res/values-en-rAU/strings.xml
deleted file mode 100644
index 7c94a51..0000000
--- a/packages/overlays/SysuiDarkThemeOverlay/res/values-en-rAU/strings.xml
+++ /dev/null
@@ -1,23 +0,0 @@
-<?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.
- */
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="sysui_overlay_dark" msgid="557336259295713662">"Dark"</string>
-</resources>
diff --git a/packages/overlays/SysuiDarkThemeOverlay/res/values-en-rCA/strings.xml b/packages/overlays/SysuiDarkThemeOverlay/res/values-en-rCA/strings.xml
deleted file mode 100644
index 7c94a51..0000000
--- a/packages/overlays/SysuiDarkThemeOverlay/res/values-en-rCA/strings.xml
+++ /dev/null
@@ -1,23 +0,0 @@
-<?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.
- */
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="sysui_overlay_dark" msgid="557336259295713662">"Dark"</string>
-</resources>
diff --git a/packages/overlays/SysuiDarkThemeOverlay/res/values-en-rGB/strings.xml b/packages/overlays/SysuiDarkThemeOverlay/res/values-en-rGB/strings.xml
deleted file mode 100644
index 7c94a51..0000000
--- a/packages/overlays/SysuiDarkThemeOverlay/res/values-en-rGB/strings.xml
+++ /dev/null
@@ -1,23 +0,0 @@
-<?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.
- */
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="sysui_overlay_dark" msgid="557336259295713662">"Dark"</string>
-</resources>
diff --git a/packages/overlays/SysuiDarkThemeOverlay/res/values-en-rIN/strings.xml b/packages/overlays/SysuiDarkThemeOverlay/res/values-en-rIN/strings.xml
deleted file mode 100644
index 7c94a51..0000000
--- a/packages/overlays/SysuiDarkThemeOverlay/res/values-en-rIN/strings.xml
+++ /dev/null
@@ -1,23 +0,0 @@
-<?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.
- */
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="sysui_overlay_dark" msgid="557336259295713662">"Dark"</string>
-</resources>
diff --git a/packages/overlays/SysuiDarkThemeOverlay/res/values-en-rXC/strings.xml b/packages/overlays/SysuiDarkThemeOverlay/res/values-en-rXC/strings.xml
deleted file mode 100644
index cbdd3d2..0000000
--- a/packages/overlays/SysuiDarkThemeOverlay/res/values-en-rXC/strings.xml
+++ /dev/null
@@ -1,23 +0,0 @@
-<?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.
- */
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="sysui_overlay_dark" msgid="557336259295713662">"Dark"</string>
-</resources>
diff --git a/packages/overlays/SysuiDarkThemeOverlay/res/values-es-rUS/strings.xml b/packages/overlays/SysuiDarkThemeOverlay/res/values-es-rUS/strings.xml
deleted file mode 100644
index 2717f0f..0000000
--- a/packages/overlays/SysuiDarkThemeOverlay/res/values-es-rUS/strings.xml
+++ /dev/null
@@ -1,23 +0,0 @@
-<?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.
- */
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="sysui_overlay_dark" msgid="557336259295713662">"Oscuro"</string>
-</resources>
diff --git a/packages/overlays/SysuiDarkThemeOverlay/res/values-es/strings.xml b/packages/overlays/SysuiDarkThemeOverlay/res/values-es/strings.xml
deleted file mode 100644
index 2717f0f..0000000
--- a/packages/overlays/SysuiDarkThemeOverlay/res/values-es/strings.xml
+++ /dev/null
@@ -1,23 +0,0 @@
-<?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.
- */
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="sysui_overlay_dark" msgid="557336259295713662">"Oscuro"</string>
-</resources>
diff --git a/packages/overlays/SysuiDarkThemeOverlay/res/values-et/strings.xml b/packages/overlays/SysuiDarkThemeOverlay/res/values-et/strings.xml
deleted file mode 100644
index e0cce05..0000000
--- a/packages/overlays/SysuiDarkThemeOverlay/res/values-et/strings.xml
+++ /dev/null
@@ -1,23 +0,0 @@
-<?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.
- */
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="sysui_overlay_dark" msgid="557336259295713662">"Tume"</string>
-</resources>
diff --git a/packages/overlays/SysuiDarkThemeOverlay/res/values-eu/strings.xml b/packages/overlays/SysuiDarkThemeOverlay/res/values-eu/strings.xml
deleted file mode 100644
index 44cee4c..0000000
--- a/packages/overlays/SysuiDarkThemeOverlay/res/values-eu/strings.xml
+++ /dev/null
@@ -1,23 +0,0 @@
-<?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.
- */
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="sysui_overlay_dark" msgid="557336259295713662">"Iluna"</string>
-</resources>
diff --git a/packages/overlays/SysuiDarkThemeOverlay/res/values-fa/strings.xml b/packages/overlays/SysuiDarkThemeOverlay/res/values-fa/strings.xml
deleted file mode 100644
index fdd1df5..0000000
--- a/packages/overlays/SysuiDarkThemeOverlay/res/values-fa/strings.xml
+++ /dev/null
@@ -1,23 +0,0 @@
-<?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.
- */
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="sysui_overlay_dark" msgid="557336259295713662">"تیره"</string>
-</resources>
diff --git a/packages/overlays/SysuiDarkThemeOverlay/res/values-fi/strings.xml b/packages/overlays/SysuiDarkThemeOverlay/res/values-fi/strings.xml
deleted file mode 100644
index 237fe70..0000000
--- a/packages/overlays/SysuiDarkThemeOverlay/res/values-fi/strings.xml
+++ /dev/null
@@ -1,23 +0,0 @@
-<?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.
- */
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="sysui_overlay_dark" msgid="557336259295713662">"Tumma"</string>
-</resources>
diff --git a/packages/overlays/SysuiDarkThemeOverlay/res/values-fr-rCA/strings.xml b/packages/overlays/SysuiDarkThemeOverlay/res/values-fr-rCA/strings.xml
deleted file mode 100644
index f92c2ef..0000000
--- a/packages/overlays/SysuiDarkThemeOverlay/res/values-fr-rCA/strings.xml
+++ /dev/null
@@ -1,23 +0,0 @@
-<?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.
- */
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="sysui_overlay_dark" msgid="557336259295713662">"Sombre"</string>
-</resources>
diff --git a/packages/overlays/SysuiDarkThemeOverlay/res/values-fr/strings.xml b/packages/overlays/SysuiDarkThemeOverlay/res/values-fr/strings.xml
deleted file mode 100644
index eac51d3..0000000
--- a/packages/overlays/SysuiDarkThemeOverlay/res/values-fr/strings.xml
+++ /dev/null
@@ -1,23 +0,0 @@
-<?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.
- */
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="sysui_overlay_dark" msgid="557336259295713662">"Foncé"</string>
-</resources>
diff --git a/packages/overlays/SysuiDarkThemeOverlay/res/values-gl/strings.xml b/packages/overlays/SysuiDarkThemeOverlay/res/values-gl/strings.xml
deleted file mode 100644
index 300868f..0000000
--- a/packages/overlays/SysuiDarkThemeOverlay/res/values-gl/strings.xml
+++ /dev/null
@@ -1,23 +0,0 @@
-<?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.
- */
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="sysui_overlay_dark" msgid="557336259295713662">"Escuro"</string>
-</resources>
diff --git a/packages/overlays/SysuiDarkThemeOverlay/res/values-gu/strings.xml b/packages/overlays/SysuiDarkThemeOverlay/res/values-gu/strings.xml
deleted file mode 100644
index 6a4cd62f..0000000
--- a/packages/overlays/SysuiDarkThemeOverlay/res/values-gu/strings.xml
+++ /dev/null
@@ -1,23 +0,0 @@
-<?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.
- */
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="sysui_overlay_dark" msgid="557336259295713662">"ઘેરી"</string>
-</resources>
diff --git a/packages/overlays/SysuiDarkThemeOverlay/res/values-hi/strings.xml b/packages/overlays/SysuiDarkThemeOverlay/res/values-hi/strings.xml
deleted file mode 100644
index c5bc0e2..0000000
--- a/packages/overlays/SysuiDarkThemeOverlay/res/values-hi/strings.xml
+++ /dev/null
@@ -1,23 +0,0 @@
-<?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.
- */
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="sysui_overlay_dark" msgid="557336259295713662">"गहरे रंग की थीम"</string>
-</resources>
diff --git a/packages/overlays/SysuiDarkThemeOverlay/res/values-hr/strings.xml b/packages/overlays/SysuiDarkThemeOverlay/res/values-hr/strings.xml
deleted file mode 100644
index b63dcbc..0000000
--- a/packages/overlays/SysuiDarkThemeOverlay/res/values-hr/strings.xml
+++ /dev/null
@@ -1,23 +0,0 @@
-<?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.
- */
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="sysui_overlay_dark" msgid="557336259295713662">"Tamno"</string>
-</resources>
diff --git a/packages/overlays/SysuiDarkThemeOverlay/res/values-hu/strings.xml b/packages/overlays/SysuiDarkThemeOverlay/res/values-hu/strings.xml
deleted file mode 100644
index 84a3ab8..0000000
--- a/packages/overlays/SysuiDarkThemeOverlay/res/values-hu/strings.xml
+++ /dev/null
@@ -1,23 +0,0 @@
-<?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.
- */
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="sysui_overlay_dark" msgid="557336259295713662">"Sötét"</string>
-</resources>
diff --git a/packages/overlays/SysuiDarkThemeOverlay/res/values-hy/strings.xml b/packages/overlays/SysuiDarkThemeOverlay/res/values-hy/strings.xml
deleted file mode 100644
index 555cb64..0000000
--- a/packages/overlays/SysuiDarkThemeOverlay/res/values-hy/strings.xml
+++ /dev/null
@@ -1,23 +0,0 @@
-<?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.
- */
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="sysui_overlay_dark" msgid="557336259295713662">"Մուգ"</string>
-</resources>
diff --git a/packages/overlays/SysuiDarkThemeOverlay/res/values-in/strings.xml b/packages/overlays/SysuiDarkThemeOverlay/res/values-in/strings.xml
deleted file mode 100644
index 391451b..0000000
--- a/packages/overlays/SysuiDarkThemeOverlay/res/values-in/strings.xml
+++ /dev/null
@@ -1,23 +0,0 @@
-<?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.
- */
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="sysui_overlay_dark" msgid="557336259295713662">"Gelap"</string>
-</resources>
diff --git a/packages/overlays/SysuiDarkThemeOverlay/res/values-is/strings.xml b/packages/overlays/SysuiDarkThemeOverlay/res/values-is/strings.xml
deleted file mode 100644
index f4d1531..0000000
--- a/packages/overlays/SysuiDarkThemeOverlay/res/values-is/strings.xml
+++ /dev/null
@@ -1,23 +0,0 @@
-<?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.
- */
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="sysui_overlay_dark" msgid="557336259295713662">"Dökkt"</string>
-</resources>
diff --git a/packages/overlays/SysuiDarkThemeOverlay/res/values-it/strings.xml b/packages/overlays/SysuiDarkThemeOverlay/res/values-it/strings.xml
deleted file mode 100644
index b59155b..0000000
--- a/packages/overlays/SysuiDarkThemeOverlay/res/values-it/strings.xml
+++ /dev/null
@@ -1,23 +0,0 @@
-<?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.
- */
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="sysui_overlay_dark" msgid="557336259295713662">"Scuro"</string>
-</resources>
diff --git a/packages/overlays/SysuiDarkThemeOverlay/res/values-iw/strings.xml b/packages/overlays/SysuiDarkThemeOverlay/res/values-iw/strings.xml
deleted file mode 100644
index 3ecf444..0000000
--- a/packages/overlays/SysuiDarkThemeOverlay/res/values-iw/strings.xml
+++ /dev/null
@@ -1,23 +0,0 @@
-<?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.
- */
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="sysui_overlay_dark" msgid="557336259295713662">"כהה"</string>
-</resources>
diff --git a/packages/overlays/SysuiDarkThemeOverlay/res/values-ja/strings.xml b/packages/overlays/SysuiDarkThemeOverlay/res/values-ja/strings.xml
deleted file mode 100644
index 3a2dba0..0000000
--- a/packages/overlays/SysuiDarkThemeOverlay/res/values-ja/strings.xml
+++ /dev/null
@@ -1,23 +0,0 @@
-<?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.
- */
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="sysui_overlay_dark" msgid="557336259295713662">"ダーク"</string>
-</resources>
diff --git a/packages/overlays/SysuiDarkThemeOverlay/res/values-ka/strings.xml b/packages/overlays/SysuiDarkThemeOverlay/res/values-ka/strings.xml
deleted file mode 100644
index 36bf77e..0000000
--- a/packages/overlays/SysuiDarkThemeOverlay/res/values-ka/strings.xml
+++ /dev/null
@@ -1,23 +0,0 @@
-<?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.
- */
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="sysui_overlay_dark" msgid="557336259295713662">"მუქი"</string>
-</resources>
diff --git a/packages/overlays/SysuiDarkThemeOverlay/res/values-kk/strings.xml b/packages/overlays/SysuiDarkThemeOverlay/res/values-kk/strings.xml
deleted file mode 100644
index 913c0b1..0000000
--- a/packages/overlays/SysuiDarkThemeOverlay/res/values-kk/strings.xml
+++ /dev/null
@@ -1,23 +0,0 @@
-<?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.
- */
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="sysui_overlay_dark" msgid="557336259295713662">"Қараңғы"</string>
-</resources>
diff --git a/packages/overlays/SysuiDarkThemeOverlay/res/values-km/strings.xml b/packages/overlays/SysuiDarkThemeOverlay/res/values-km/strings.xml
deleted file mode 100644
index b56c490..0000000
--- a/packages/overlays/SysuiDarkThemeOverlay/res/values-km/strings.xml
+++ /dev/null
@@ -1,23 +0,0 @@
-<?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.
- */
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="sysui_overlay_dark" msgid="557336259295713662">"ងងឹត"</string>
-</resources>
diff --git a/packages/overlays/SysuiDarkThemeOverlay/res/values-kn/strings.xml b/packages/overlays/SysuiDarkThemeOverlay/res/values-kn/strings.xml
deleted file mode 100644
index e757116..0000000
--- a/packages/overlays/SysuiDarkThemeOverlay/res/values-kn/strings.xml
+++ /dev/null
@@ -1,23 +0,0 @@
-<?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.
- */
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="sysui_overlay_dark" msgid="557336259295713662">"ಕತ್ತಲೆ"</string>
-</resources>
diff --git a/packages/overlays/SysuiDarkThemeOverlay/res/values-ko/strings.xml b/packages/overlays/SysuiDarkThemeOverlay/res/values-ko/strings.xml
deleted file mode 100644
index ca4ab1e..0000000
--- a/packages/overlays/SysuiDarkThemeOverlay/res/values-ko/strings.xml
+++ /dev/null
@@ -1,23 +0,0 @@
-<?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.
- */
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="sysui_overlay_dark" msgid="557336259295713662">"어두움"</string>
-</resources>
diff --git a/packages/overlays/SysuiDarkThemeOverlay/res/values-ky/strings.xml b/packages/overlays/SysuiDarkThemeOverlay/res/values-ky/strings.xml
deleted file mode 100644
index e8e8279..0000000
--- a/packages/overlays/SysuiDarkThemeOverlay/res/values-ky/strings.xml
+++ /dev/null
@@ -1,23 +0,0 @@
-<?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.
- */
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="sysui_overlay_dark" msgid="557336259295713662">"Караңгы"</string>
-</resources>
diff --git a/packages/overlays/SysuiDarkThemeOverlay/res/values-lo/strings.xml b/packages/overlays/SysuiDarkThemeOverlay/res/values-lo/strings.xml
deleted file mode 100644
index 0434a41..0000000
--- a/packages/overlays/SysuiDarkThemeOverlay/res/values-lo/strings.xml
+++ /dev/null
@@ -1,23 +0,0 @@
-<?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.
- */
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="sysui_overlay_dark" msgid="557336259295713662">"ມືດ"</string>
-</resources>
diff --git a/packages/overlays/SysuiDarkThemeOverlay/res/values-lt/strings.xml b/packages/overlays/SysuiDarkThemeOverlay/res/values-lt/strings.xml
deleted file mode 100644
index 147779b..0000000
--- a/packages/overlays/SysuiDarkThemeOverlay/res/values-lt/strings.xml
+++ /dev/null
@@ -1,23 +0,0 @@
-<?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.
- */
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="sysui_overlay_dark" msgid="557336259295713662">"Tamsi"</string>
-</resources>
diff --git a/packages/overlays/SysuiDarkThemeOverlay/res/values-lv/strings.xml b/packages/overlays/SysuiDarkThemeOverlay/res/values-lv/strings.xml
deleted file mode 100644
index 7a296ec..0000000
--- a/packages/overlays/SysuiDarkThemeOverlay/res/values-lv/strings.xml
+++ /dev/null
@@ -1,23 +0,0 @@
-<?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.
- */
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="sysui_overlay_dark" msgid="557336259295713662">"Tumšs"</string>
-</resources>
diff --git a/packages/overlays/SysuiDarkThemeOverlay/res/values-mk/strings.xml b/packages/overlays/SysuiDarkThemeOverlay/res/values-mk/strings.xml
deleted file mode 100644
index 6be693a..0000000
--- a/packages/overlays/SysuiDarkThemeOverlay/res/values-mk/strings.xml
+++ /dev/null
@@ -1,23 +0,0 @@
-<?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.
- */
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="sysui_overlay_dark" msgid="557336259295713662">"Темна"</string>
-</resources>
diff --git a/packages/overlays/SysuiDarkThemeOverlay/res/values-ml/strings.xml b/packages/overlays/SysuiDarkThemeOverlay/res/values-ml/strings.xml
deleted file mode 100644
index f8a24fa..0000000
--- a/packages/overlays/SysuiDarkThemeOverlay/res/values-ml/strings.xml
+++ /dev/null
@@ -1,23 +0,0 @@
-<?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.
- */
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="sysui_overlay_dark" msgid="557336259295713662">"ഡാർക്ക്"</string>
-</resources>
diff --git a/packages/overlays/SysuiDarkThemeOverlay/res/values-mn/strings.xml b/packages/overlays/SysuiDarkThemeOverlay/res/values-mn/strings.xml
deleted file mode 100644
index e65d9c7..0000000
--- a/packages/overlays/SysuiDarkThemeOverlay/res/values-mn/strings.xml
+++ /dev/null
@@ -1,23 +0,0 @@
-<?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.
- */
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="sysui_overlay_dark" msgid="557336259295713662">"Бараан"</string>
-</resources>
diff --git a/packages/overlays/SysuiDarkThemeOverlay/res/values-mr/strings.xml b/packages/overlays/SysuiDarkThemeOverlay/res/values-mr/strings.xml
deleted file mode 100644
index 854af00..0000000
--- a/packages/overlays/SysuiDarkThemeOverlay/res/values-mr/strings.xml
+++ /dev/null
@@ -1,23 +0,0 @@
-<?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.
- */
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="sysui_overlay_dark" msgid="557336259295713662">"गडद"</string>
-</resources>
diff --git a/packages/overlays/SysuiDarkThemeOverlay/res/values-ms/strings.xml b/packages/overlays/SysuiDarkThemeOverlay/res/values-ms/strings.xml
deleted file mode 100644
index 391451b..0000000
--- a/packages/overlays/SysuiDarkThemeOverlay/res/values-ms/strings.xml
+++ /dev/null
@@ -1,23 +0,0 @@
-<?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.
- */
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="sysui_overlay_dark" msgid="557336259295713662">"Gelap"</string>
-</resources>
diff --git a/packages/overlays/SysuiDarkThemeOverlay/res/values-my/strings.xml b/packages/overlays/SysuiDarkThemeOverlay/res/values-my/strings.xml
deleted file mode 100644
index 008e9c6..0000000
--- a/packages/overlays/SysuiDarkThemeOverlay/res/values-my/strings.xml
+++ /dev/null
@@ -1,23 +0,0 @@
-<?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.
- */
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="sysui_overlay_dark" msgid="557336259295713662">"မှောင်သော"</string>
-</resources>
diff --git a/packages/overlays/SysuiDarkThemeOverlay/res/values-nb/strings.xml b/packages/overlays/SysuiDarkThemeOverlay/res/values-nb/strings.xml
deleted file mode 100644
index 460ebe7..0000000
--- a/packages/overlays/SysuiDarkThemeOverlay/res/values-nb/strings.xml
+++ /dev/null
@@ -1,23 +0,0 @@
-<?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.
- */
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="sysui_overlay_dark" msgid="557336259295713662">"Mørk"</string>
-</resources>
diff --git a/packages/overlays/SysuiDarkThemeOverlay/res/values-ne/strings.xml b/packages/overlays/SysuiDarkThemeOverlay/res/values-ne/strings.xml
deleted file mode 100644
index 8f2c5ba..0000000
--- a/packages/overlays/SysuiDarkThemeOverlay/res/values-ne/strings.xml
+++ /dev/null
@@ -1,23 +0,0 @@
-<?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.
- */
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="sysui_overlay_dark" msgid="557336259295713662">"अँध्यारो"</string>
-</resources>
diff --git a/packages/overlays/SysuiDarkThemeOverlay/res/values-nl/strings.xml b/packages/overlays/SysuiDarkThemeOverlay/res/values-nl/strings.xml
deleted file mode 100644
index 33c6982..0000000
--- a/packages/overlays/SysuiDarkThemeOverlay/res/values-nl/strings.xml
+++ /dev/null
@@ -1,23 +0,0 @@
-<?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.
- */
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="sysui_overlay_dark" msgid="557336259295713662">"Donker"</string>
-</resources>
diff --git a/packages/overlays/SysuiDarkThemeOverlay/res/values-or/strings.xml b/packages/overlays/SysuiDarkThemeOverlay/res/values-or/strings.xml
deleted file mode 100644
index d8045bd..0000000
--- a/packages/overlays/SysuiDarkThemeOverlay/res/values-or/strings.xml
+++ /dev/null
@@ -1,23 +0,0 @@
-<?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.
- */
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="sysui_overlay_dark" msgid="557336259295713662">"ଗାଢ଼"</string>
-</resources>
diff --git a/packages/overlays/SysuiDarkThemeOverlay/res/values-pa/strings.xml b/packages/overlays/SysuiDarkThemeOverlay/res/values-pa/strings.xml
deleted file mode 100644
index 7110303..0000000
--- a/packages/overlays/SysuiDarkThemeOverlay/res/values-pa/strings.xml
+++ /dev/null
@@ -1,23 +0,0 @@
-<?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.
- */
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="sysui_overlay_dark" msgid="557336259295713662">"ਗੂੜ੍ਹਾ"</string>
-</resources>
diff --git a/packages/overlays/SysuiDarkThemeOverlay/res/values-pl/strings.xml b/packages/overlays/SysuiDarkThemeOverlay/res/values-pl/strings.xml
deleted file mode 100644
index 25ca20f..0000000
--- a/packages/overlays/SysuiDarkThemeOverlay/res/values-pl/strings.xml
+++ /dev/null
@@ -1,23 +0,0 @@
-<?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.
- */
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="sysui_overlay_dark" msgid="557336259295713662">"Ciemna"</string>
-</resources>
diff --git a/packages/overlays/SysuiDarkThemeOverlay/res/values-pt-rBR/strings.xml b/packages/overlays/SysuiDarkThemeOverlay/res/values-pt-rBR/strings.xml
deleted file mode 100644
index 300868f..0000000
--- a/packages/overlays/SysuiDarkThemeOverlay/res/values-pt-rBR/strings.xml
+++ /dev/null
@@ -1,23 +0,0 @@
-<?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.
- */
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="sysui_overlay_dark" msgid="557336259295713662">"Escuro"</string>
-</resources>
diff --git a/packages/overlays/SysuiDarkThemeOverlay/res/values-pt-rPT/strings.xml b/packages/overlays/SysuiDarkThemeOverlay/res/values-pt-rPT/strings.xml
deleted file mode 100644
index 300868f..0000000
--- a/packages/overlays/SysuiDarkThemeOverlay/res/values-pt-rPT/strings.xml
+++ /dev/null
@@ -1,23 +0,0 @@
-<?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.
- */
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="sysui_overlay_dark" msgid="557336259295713662">"Escuro"</string>
-</resources>
diff --git a/packages/overlays/SysuiDarkThemeOverlay/res/values-pt/strings.xml b/packages/overlays/SysuiDarkThemeOverlay/res/values-pt/strings.xml
deleted file mode 100644
index 300868f..0000000
--- a/packages/overlays/SysuiDarkThemeOverlay/res/values-pt/strings.xml
+++ /dev/null
@@ -1,23 +0,0 @@
-<?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.
- */
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="sysui_overlay_dark" msgid="557336259295713662">"Escuro"</string>
-</resources>
diff --git a/packages/overlays/SysuiDarkThemeOverlay/res/values-ro/strings.xml b/packages/overlays/SysuiDarkThemeOverlay/res/values-ro/strings.xml
deleted file mode 100644
index de73f36..0000000
--- a/packages/overlays/SysuiDarkThemeOverlay/res/values-ro/strings.xml
+++ /dev/null
@@ -1,23 +0,0 @@
-<?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.
- */
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="sysui_overlay_dark" msgid="557336259295713662">"Întunecată"</string>
-</resources>
diff --git a/packages/overlays/SysuiDarkThemeOverlay/res/values-ru/strings.xml b/packages/overlays/SysuiDarkThemeOverlay/res/values-ru/strings.xml
deleted file mode 100644
index b05e844..0000000
--- a/packages/overlays/SysuiDarkThemeOverlay/res/values-ru/strings.xml
+++ /dev/null
@@ -1,23 +0,0 @@
-<?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.
- */
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="sysui_overlay_dark" msgid="557336259295713662">"Темный"</string>
-</resources>
diff --git a/packages/overlays/SysuiDarkThemeOverlay/res/values-si/strings.xml b/packages/overlays/SysuiDarkThemeOverlay/res/values-si/strings.xml
deleted file mode 100644
index f0f5725..0000000
--- a/packages/overlays/SysuiDarkThemeOverlay/res/values-si/strings.xml
+++ /dev/null
@@ -1,23 +0,0 @@
-<?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.
- */
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="sysui_overlay_dark" msgid="557336259295713662">"අඳුරු"</string>
-</resources>
diff --git a/packages/overlays/SysuiDarkThemeOverlay/res/values-sk/strings.xml b/packages/overlays/SysuiDarkThemeOverlay/res/values-sk/strings.xml
deleted file mode 100644
index 5df6895..0000000
--- a/packages/overlays/SysuiDarkThemeOverlay/res/values-sk/strings.xml
+++ /dev/null
@@ -1,23 +0,0 @@
-<?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.
- */
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="sysui_overlay_dark" msgid="557336259295713662">"Tmavý"</string>
-</resources>
diff --git a/packages/overlays/SysuiDarkThemeOverlay/res/values-sl/strings.xml b/packages/overlays/SysuiDarkThemeOverlay/res/values-sl/strings.xml
deleted file mode 100644
index ad58250..0000000
--- a/packages/overlays/SysuiDarkThemeOverlay/res/values-sl/strings.xml
+++ /dev/null
@@ -1,23 +0,0 @@
-<?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.
- */
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="sysui_overlay_dark" msgid="557336259295713662">"Temno"</string>
-</resources>
diff --git a/packages/overlays/SysuiDarkThemeOverlay/res/values-sq/strings.xml b/packages/overlays/SysuiDarkThemeOverlay/res/values-sq/strings.xml
deleted file mode 100644
index 0e1eae7..0000000
--- a/packages/overlays/SysuiDarkThemeOverlay/res/values-sq/strings.xml
+++ /dev/null
@@ -1,23 +0,0 @@
-<?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.
- */
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="sysui_overlay_dark" msgid="557336259295713662">"E errët"</string>
-</resources>
diff --git a/packages/overlays/SysuiDarkThemeOverlay/res/values-sr/strings.xml b/packages/overlays/SysuiDarkThemeOverlay/res/values-sr/strings.xml
deleted file mode 100644
index 1561ee2..0000000
--- a/packages/overlays/SysuiDarkThemeOverlay/res/values-sr/strings.xml
+++ /dev/null
@@ -1,23 +0,0 @@
-<?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.
- */
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="sysui_overlay_dark" msgid="557336259295713662">"Тамно"</string>
-</resources>
diff --git a/packages/overlays/SysuiDarkThemeOverlay/res/values-sv/strings.xml b/packages/overlays/SysuiDarkThemeOverlay/res/values-sv/strings.xml
deleted file mode 100644
index 676de42..0000000
--- a/packages/overlays/SysuiDarkThemeOverlay/res/values-sv/strings.xml
+++ /dev/null
@@ -1,23 +0,0 @@
-<?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.
- */
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="sysui_overlay_dark" msgid="557336259295713662">"Mörk"</string>
-</resources>
diff --git a/packages/overlays/SysuiDarkThemeOverlay/res/values-sw/strings.xml b/packages/overlays/SysuiDarkThemeOverlay/res/values-sw/strings.xml
deleted file mode 100644
index cc1f120..0000000
--- a/packages/overlays/SysuiDarkThemeOverlay/res/values-sw/strings.xml
+++ /dev/null
@@ -1,23 +0,0 @@
-<?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.
- */
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="sysui_overlay_dark" msgid="557336259295713662">"Nyeusi"</string>
-</resources>
diff --git a/packages/overlays/SysuiDarkThemeOverlay/res/values-ta/strings.xml b/packages/overlays/SysuiDarkThemeOverlay/res/values-ta/strings.xml
deleted file mode 100644
index af98172..0000000
--- a/packages/overlays/SysuiDarkThemeOverlay/res/values-ta/strings.xml
+++ /dev/null
@@ -1,23 +0,0 @@
-<?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.
- */
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="sysui_overlay_dark" msgid="557336259295713662">"டார்க்"</string>
-</resources>
diff --git a/packages/overlays/SysuiDarkThemeOverlay/res/values-te/strings.xml b/packages/overlays/SysuiDarkThemeOverlay/res/values-te/strings.xml
deleted file mode 100644
index 446455f..0000000
--- a/packages/overlays/SysuiDarkThemeOverlay/res/values-te/strings.xml
+++ /dev/null
@@ -1,23 +0,0 @@
-<?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.
- */
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="sysui_overlay_dark" msgid="557336259295713662">"ముదురు రంగు"</string>
-</resources>
diff --git a/packages/overlays/SysuiDarkThemeOverlay/res/values-th/strings.xml b/packages/overlays/SysuiDarkThemeOverlay/res/values-th/strings.xml
deleted file mode 100644
index 9e3462b..0000000
--- a/packages/overlays/SysuiDarkThemeOverlay/res/values-th/strings.xml
+++ /dev/null
@@ -1,23 +0,0 @@
-<?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.
- */
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="sysui_overlay_dark" msgid="557336259295713662">"เข้ม"</string>
-</resources>
diff --git a/packages/overlays/SysuiDarkThemeOverlay/res/values-tl/strings.xml b/packages/overlays/SysuiDarkThemeOverlay/res/values-tl/strings.xml
deleted file mode 100644
index 5502d90..0000000
--- a/packages/overlays/SysuiDarkThemeOverlay/res/values-tl/strings.xml
+++ /dev/null
@@ -1,23 +0,0 @@
-<?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.
- */
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="sysui_overlay_dark" msgid="557336259295713662">"Madilim"</string>
-</resources>
diff --git a/packages/overlays/SysuiDarkThemeOverlay/res/values-tr/strings.xml b/packages/overlays/SysuiDarkThemeOverlay/res/values-tr/strings.xml
deleted file mode 100644
index 368b398..0000000
--- a/packages/overlays/SysuiDarkThemeOverlay/res/values-tr/strings.xml
+++ /dev/null
@@ -1,23 +0,0 @@
-<?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.
- */
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="sysui_overlay_dark" msgid="557336259295713662">"Koyu"</string>
-</resources>
diff --git a/packages/overlays/SysuiDarkThemeOverlay/res/values-uk/strings.xml b/packages/overlays/SysuiDarkThemeOverlay/res/values-uk/strings.xml
deleted file mode 100644
index 6e67e45..0000000
--- a/packages/overlays/SysuiDarkThemeOverlay/res/values-uk/strings.xml
+++ /dev/null
@@ -1,23 +0,0 @@
-<?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.
- */
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="sysui_overlay_dark" msgid="557336259295713662">"Темна тема"</string>
-</resources>
diff --git a/packages/overlays/SysuiDarkThemeOverlay/res/values-ur/strings.xml b/packages/overlays/SysuiDarkThemeOverlay/res/values-ur/strings.xml
deleted file mode 100644
index 1d5d6de..0000000
--- a/packages/overlays/SysuiDarkThemeOverlay/res/values-ur/strings.xml
+++ /dev/null
@@ -1,23 +0,0 @@
-<?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.
- */
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="sysui_overlay_dark" msgid="557336259295713662">"گہرا"</string>
-</resources>
diff --git a/packages/overlays/SysuiDarkThemeOverlay/res/values-uz/strings.xml b/packages/overlays/SysuiDarkThemeOverlay/res/values-uz/strings.xml
deleted file mode 100644
index 957c28f..0000000
--- a/packages/overlays/SysuiDarkThemeOverlay/res/values-uz/strings.xml
+++ /dev/null
@@ -1,23 +0,0 @@
-<?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.
- */
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="sysui_overlay_dark" msgid="557336259295713662">"Tungi"</string>
-</resources>
diff --git a/packages/overlays/SysuiDarkThemeOverlay/res/values-vi/strings.xml b/packages/overlays/SysuiDarkThemeOverlay/res/values-vi/strings.xml
deleted file mode 100644
index a458889..0000000
--- a/packages/overlays/SysuiDarkThemeOverlay/res/values-vi/strings.xml
+++ /dev/null
@@ -1,23 +0,0 @@
-<?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.
- */
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="sysui_overlay_dark" msgid="557336259295713662">"Tối"</string>
-</resources>
diff --git a/packages/overlays/SysuiDarkThemeOverlay/res/values-zh-rCN/strings.xml b/packages/overlays/SysuiDarkThemeOverlay/res/values-zh-rCN/strings.xml
deleted file mode 100644
index c9b43dc..0000000
--- a/packages/overlays/SysuiDarkThemeOverlay/res/values-zh-rCN/strings.xml
+++ /dev/null
@@ -1,23 +0,0 @@
-<?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.
- */
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="sysui_overlay_dark" msgid="557336259295713662">"深色"</string>
-</resources>
diff --git a/packages/overlays/SysuiDarkThemeOverlay/res/values-zh-rHK/strings.xml b/packages/overlays/SysuiDarkThemeOverlay/res/values-zh-rHK/strings.xml
deleted file mode 100644
index c9b43dc..0000000
--- a/packages/overlays/SysuiDarkThemeOverlay/res/values-zh-rHK/strings.xml
+++ /dev/null
@@ -1,23 +0,0 @@
-<?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.
- */
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="sysui_overlay_dark" msgid="557336259295713662">"深色"</string>
-</resources>
diff --git a/packages/overlays/SysuiDarkThemeOverlay/res/values-zh-rTW/strings.xml b/packages/overlays/SysuiDarkThemeOverlay/res/values-zh-rTW/strings.xml
deleted file mode 100644
index c9b43dc..0000000
--- a/packages/overlays/SysuiDarkThemeOverlay/res/values-zh-rTW/strings.xml
+++ /dev/null
@@ -1,23 +0,0 @@
-<?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.
- */
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="sysui_overlay_dark" msgid="557336259295713662">"深色"</string>
-</resources>
diff --git a/packages/overlays/SysuiDarkThemeOverlay/res/values-zu/strings.xml b/packages/overlays/SysuiDarkThemeOverlay/res/values-zu/strings.xml
deleted file mode 100644
index 6d328da..0000000
--- a/packages/overlays/SysuiDarkThemeOverlay/res/values-zu/strings.xml
+++ /dev/null
@@ -1,23 +0,0 @@
-<?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.
- */
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="sysui_overlay_dark" msgid="557336259295713662">"Emnyama"</string>
-</resources>
diff --git a/packages/overlays/SysuiDarkThemeOverlay/res/values/strings.xml b/packages/overlays/SysuiDarkThemeOverlay/res/values/strings.xml
deleted file mode 100644
index 71f48d6..0000000
--- a/packages/overlays/SysuiDarkThemeOverlay/res/values/strings.xml
+++ /dev/null
@@ -1,24 +0,0 @@
-<?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.
- */
--->
-<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-
- <string name="sysui_overlay_dark">Dark</string>
-
-</resources>
-
diff --git a/packages/overlays/SysuiDarkThemeOverlay/res/values/styles.xml b/packages/overlays/SysuiDarkThemeOverlay/res/values/styles.xml
deleted file mode 100644
index 41a2940..0000000
--- a/packages/overlays/SysuiDarkThemeOverlay/res/values/styles.xml
+++ /dev/null
@@ -1,12 +0,0 @@
-<?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">@*android:color/material_grey_900</item>
- <item name="android:panelColorBackground">@*android:color/material_grey_800</item>
- </style>
-</resources>
\ No newline at end of file
diff --git a/services/Android.bp b/services/Android.bp
index d125adc..bea51be 100644
--- a/services/Android.bp
+++ b/services/Android.bp
@@ -2,6 +2,7 @@
// ============================================================
java_library {
name: "services",
+ installable: true,
dex_preopt: {
app_image: true,
diff --git a/services/core/java/com/android/server/AlarmManagerService.java b/services/core/java/com/android/server/AlarmManagerService.java
index cc5acdf..7185f02 100644
--- a/services/core/java/com/android/server/AlarmManagerService.java
+++ b/services/core/java/com/android/server/AlarmManagerService.java
@@ -2690,7 +2690,7 @@
errorMsg.append("[mNextNonWakeup=");
TimeUtils.formatDuration(mNextNonWakeup - nowElapsed, errorMsg);
errorMsg.append(" set at ");
- TimeUtils.formatDuration(mNextNonWakeUpSetAt, errorMsg);
+ TimeUtils.formatDuration(mNextNonWakeUpSetAt - nowElapsed, errorMsg);
errorMsg.append(", mLastWakeup=");
TimeUtils.formatDuration(mLastWakeup - nowElapsed, errorMsg);
errorMsg.append(", timerfd_gettime=" + getNextAlarm(mNativeData, ELAPSED_REALTIME));
@@ -2701,7 +2701,7 @@
errorMsg.append("[mNextWakeup=");
TimeUtils.formatDuration(mNextWakeup - nowElapsed, errorMsg);
errorMsg.append(" set at ");
- TimeUtils.formatDuration(mNextWakeUpSetAt, errorMsg);
+ TimeUtils.formatDuration(mNextWakeUpSetAt - nowElapsed, errorMsg);
errorMsg.append(", mLastWakeup=");
TimeUtils.formatDuration(mLastWakeup - nowElapsed, errorMsg);
errorMsg.append(", timerfd_gettime="
diff --git a/services/core/java/com/android/server/AppOpsService.java b/services/core/java/com/android/server/AppOpsService.java
index 1167e1d..b3f6bd1 100644
--- a/services/core/java/com/android/server/AppOpsService.java
+++ b/services/core/java/com/android/server/AppOpsService.java
@@ -22,6 +22,7 @@
import android.app.AppGlobals;
import android.app.AppOpsManager;
import android.app.AppOpsManagerInternal;
+import android.app.AppOpsManagerInternal.CheckOpsDelegate;
import android.content.ContentResolver;
import android.content.Context;
import android.content.pm.ApplicationInfo;
@@ -207,6 +208,8 @@
SparseIntArray mProfileOwners;
+ private CheckOpsDelegate mCheckOpsDelegate;
+
/**
* All times are in milliseconds. These constants are kept synchronized with the system
* global Settings. Any access to this class or its fields should be done while
@@ -1411,15 +1414,39 @@
}
}
+ public CheckOpsDelegate getAppOpsServiceDelegate() {
+ synchronized (this) {
+ return mCheckOpsDelegate;
+ }
+ }
+
+ public void setAppOpsServiceDelegate(CheckOpsDelegate delegate) {
+ synchronized (this) {
+ mCheckOpsDelegate = delegate;
+ }
+ }
+
@Override
public int checkOperation(int code, int uid, String packageName) {
- verifyIncomingUid(uid);
- verifyIncomingOp(code);
- String resolvedPackageName = resolvePackageName(uid, packageName);
- if (resolvedPackageName == null) {
- return AppOpsManager.MODE_IGNORED;
- }
+ final CheckOpsDelegate delegate;
synchronized (this) {
+ if (mCheckOpsDelegate == null) {
+ return checkOperationImpl(code, uid, packageName);
+ }
+ delegate = mCheckOpsDelegate;
+ }
+ return delegate.checkOperation(code, uid, packageName,
+ AppOpsService.this::checkOperationImpl);
+ }
+
+ private int checkOperationImpl(int code, int uid, String packageName) {
+ synchronized (this) {
+ verifyIncomingUid(uid);
+ verifyIncomingOp(code);
+ String resolvedPackageName = resolvePackageName(uid, packageName);
+ if (resolvedPackageName == null) {
+ return AppOpsManager.MODE_IGNORED;
+ }
if (isOpRestrictedLocked(uid, code, resolvedPackageName)) {
return AppOpsManager.MODE_IGNORED;
}
@@ -1439,20 +1466,33 @@
@Override
public int checkAudioOperation(int code, int usage, int uid, String packageName) {
- boolean suspended;
- try {
- suspended = isPackageSuspendedForUser(packageName, uid);
- } catch (IllegalArgumentException ex) {
- // Package not found.
- suspended = false;
- }
-
- if (suspended) {
- Slog.i(TAG, "Audio disabled for suspended package=" + packageName + " for uid=" + uid);
- return AppOpsManager.MODE_IGNORED;
- }
-
+ final CheckOpsDelegate delegate;
synchronized (this) {
+ if (mCheckOpsDelegate == null) {
+ return checkAudioOperationImpl(code, usage, uid, packageName);
+ }
+ delegate = mCheckOpsDelegate;
+ }
+ return delegate.checkAudioOperation(code, usage, uid, packageName,
+ AppOpsService.this::checkAudioOperationImpl);
+ }
+
+ private int checkAudioOperationImpl(int code, int usage, int uid, String packageName) {
+ synchronized (this) {
+ boolean suspended;
+ try {
+ suspended = isPackageSuspendedForUser(packageName, uid);
+ } catch (IllegalArgumentException ex) {
+ // Package not found.
+ suspended = false;
+ }
+
+ if (suspended) {
+ Slog.i(TAG, "Audio disabled for suspended package=" + packageName
+ + " for uid=" + uid);
+ return AppOpsManager.MODE_IGNORED;
+ }
+
final int mode = checkRestrictionLocked(code, usage, uid, packageName);
if (mode != AppOpsManager.MODE_ALLOWED) {
return mode;
@@ -1530,10 +1570,10 @@
}
@Override
- public int noteProxyOperation(int code, String proxyPackageName,
- int proxiedUid, String proxiedPackageName) {
+ public int noteProxyOperation(int code, int proxyUid,
+ String proxyPackageName, int proxiedUid, String proxiedPackageName) {
+ verifyIncomingUid(proxyUid);
verifyIncomingOp(code);
- final int proxyUid = Binder.getCallingUid();
String resolveProxyPackageName = resolvePackageName(proxyUid, proxyPackageName);
if (resolveProxyPackageName == null) {
return AppOpsManager.MODE_IGNORED;
@@ -1553,6 +1593,18 @@
@Override
public int noteOperation(int code, int uid, String packageName) {
+ final CheckOpsDelegate delegate;
+ synchronized (this) {
+ if (mCheckOpsDelegate == null) {
+ return noteOperationImpl(code, uid, packageName);
+ }
+ delegate = mCheckOpsDelegate;
+ }
+ return delegate.noteOperation(code, uid, packageName,
+ AppOpsService.this::noteOperationImpl);
+ }
+
+ private int noteOperationImpl(int code, int uid, String packageName) {
verifyIncomingUid(uid);
verifyIncomingOp(code);
String resolvedPackageName = resolvePackageName(uid, packageName);
diff --git a/services/core/java/com/android/server/BinderCallsStatsService.java b/services/core/java/com/android/server/BinderCallsStatsService.java
index ce1be6f..3d779d8 100644
--- a/services/core/java/com/android/server/BinderCallsStatsService.java
+++ b/services/core/java/com/android/server/BinderCallsStatsService.java
@@ -17,15 +17,20 @@
package com.android.server;
import android.app.AppGlobals;
+import android.content.Context;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
+import android.database.ContentObserver;
+import android.net.Uri;
import android.os.Binder;
import android.os.RemoteException;
-import android.os.ServiceManager;
import android.os.SystemProperties;
import android.os.UserHandle;
+import android.provider.Settings;
+import android.util.KeyValueListParser;
import android.util.Slog;
+import com.android.internal.os.BackgroundThread;
import com.android.internal.os.BinderCallsStats;
import java.io.FileDescriptor;
@@ -41,18 +46,90 @@
private static final String PERSIST_SYS_BINDER_CALLS_DETAILED_TRACKING
= "persist.sys.binder_calls_detailed_tracking";
- public static void start() {
- BinderCallsStatsService service = new BinderCallsStatsService();
- ServiceManager.addService("binder_calls_stats", service);
- boolean detailedTrackingEnabled = SystemProperties.getBoolean(
- PERSIST_SYS_BINDER_CALLS_DETAILED_TRACKING, false);
+ /** Listens for flag changes. */
+ private static class SettingsObserver extends ContentObserver {
+ private static final String SETTINGS_ENABLED_KEY = "enabled";
+ private static final String SETTINGS_DETAILED_TRACKING_KEY = "detailed_tracking";
+ private static final String SETTINGS_UPLOAD_DATA_KEY = "upload_data";
+ private static final String SETTINGS_SAMPLING_INTERVAL_KEY = "sampling_interval";
- if (detailedTrackingEnabled) {
- Slog.i(TAG, "Enabled CPU usage tracking for binder calls. Controlled by "
- + PERSIST_SYS_BINDER_CALLS_DETAILED_TRACKING
- + " or via dumpsys binder_calls_stats --enable-detailed-tracking");
- BinderCallsStats.getInstance().setDetailedTracking(true);
+ private final Uri mUri = Settings.Global.getUriFor(Settings.Global.BINDER_CALLS_STATS);
+ private final Context mContext;
+ private final KeyValueListParser mParser = new KeyValueListParser(',');
+
+ public SettingsObserver(Context context) {
+ super(BackgroundThread.getHandler());
+ mContext = context;
+ context.getContentResolver().registerContentObserver(mUri, false, this,
+ UserHandle.USER_SYSTEM);
+ // Always kick once to ensure that we match current state
+ onChange();
}
+
+ @Override
+ public void onChange(boolean selfChange, Uri uri, int userId) {
+ if (mUri.equals(uri)) {
+ onChange();
+ }
+ }
+
+ public void onChange() {
+ // Do not overwrite the default set manually.
+ if (!SystemProperties.get(PERSIST_SYS_BINDER_CALLS_DETAILED_TRACKING).isEmpty()) {
+ return;
+ }
+
+ BinderCallsStats stats = BinderCallsStats.getInstance();
+ try {
+ mParser.setString(Settings.Global.getString(mContext.getContentResolver(),
+ Settings.Global.BINDER_CALLS_STATS));
+ } catch (IllegalArgumentException e) {
+ Slog.e(TAG, "Bad binder call stats settings", e);
+ }
+ stats.setEnabled(
+ mParser.getBoolean(SETTINGS_ENABLED_KEY, BinderCallsStats.ENABLED_DEFAULT));
+ stats.setDetailedTracking(mParser.getBoolean(
+ SETTINGS_DETAILED_TRACKING_KEY, BinderCallsStats.DETAILED_TRACKING_DEFAULT));
+ stats.setSamplingInterval(mParser.getInt(
+ SETTINGS_SAMPLING_INTERVAL_KEY,
+ BinderCallsStats.PERIODIC_SAMPLING_INTERVAL_DEFAULT));
+ }
+ }
+
+ public static class LifeCycle extends SystemService {
+ private BinderCallsStatsService mService;
+
+ public LifeCycle(Context context) {
+ super(context);
+ }
+
+ @Override
+ public void onStart() {
+ mService = new BinderCallsStatsService();
+ publishBinderService("binder_calls_stats", mService);
+ boolean detailedTrackingEnabled = SystemProperties.getBoolean(
+ PERSIST_SYS_BINDER_CALLS_DETAILED_TRACKING, false);
+
+ if (detailedTrackingEnabled) {
+ Slog.i(TAG, "Enabled CPU usage tracking for binder calls. Controlled by "
+ + PERSIST_SYS_BINDER_CALLS_DETAILED_TRACKING
+ + " or via dumpsys binder_calls_stats --enable-detailed-tracking");
+ BinderCallsStats.getInstance().setDetailedTracking(true);
+ }
+ }
+
+ @Override
+ public void onBootPhase(int phase) {
+ if (SystemService.PHASE_SYSTEM_SERVICES_READY == phase) {
+ mService.systemReady(getContext());
+ }
+ }
+ }
+
+ private SettingsObserver mSettingsObserver;
+
+ public void systemReady(Context context) {
+ mSettingsObserver = new SettingsObserver(context);
}
public static void reset() {
@@ -106,7 +183,13 @@
}
Map<Integer,String> map = new HashMap<>();
for (PackageInfo pkg : packages) {
- map.put(pkg.applicationInfo.uid, pkg.packageName);
+ String name = pkg.packageName;
+ int uid = pkg.applicationInfo.uid;
+ // Use sharedUserId string as package name if there are collisions
+ if (pkg.sharedUserId != null && map.containsKey(uid)) {
+ name = "shared:" + pkg.sharedUserId;
+ }
+ map.put(uid, name);
}
return map;
}
diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java
index cc3d73f..015d4a4 100644
--- a/services/core/java/com/android/server/am/ActivityManagerService.java
+++ b/services/core/java/com/android/server/am/ActivityManagerService.java
@@ -86,7 +86,6 @@
import static android.os.Process.setThreadScheduler;
import static android.os.Process.startWebView;
import static android.os.Process.zygoteProcess;
-import static android.os.Trace.TRACE_TAG_ACTIVITY_MANAGER;
import static android.provider.Settings.Global.ALWAYS_FINISH_ACTIVITIES;
import static android.provider.Settings.Global.DEBUG_APP;
import static android.provider.Settings.Global.NETWORK_ACCESS_TIMEOUT_MS;
@@ -164,9 +163,9 @@
import android.app.ActivityManagerProto;
import android.app.ActivityOptions;
import android.app.ActivityThread;
-import android.app.AlertDialog;
import android.app.AppGlobals;
import android.app.AppOpsManager;
+import android.app.AppOpsManagerInternal.CheckOpsDelegate;
import android.app.ApplicationErrorReport;
import android.app.ApplicationThreadConstants;
import android.app.BroadcastOptions;
@@ -205,7 +204,6 @@
import android.content.ContentProvider;
import android.content.ContentResolver;
import android.content.Context;
-import android.content.DialogInterface;
import android.content.IContentProvider;
import android.content.IIntentReceiver;
import android.content.IIntentSender;
@@ -222,6 +220,7 @@
import android.content.pm.PackageManager;
import android.content.pm.PackageManager.NameNotFoundException;
import android.content.pm.PackageManagerInternal;
+import android.content.pm.PackageManagerInternal.CheckPermissionDelegate;
import android.content.pm.ParceledListSlice;
import android.content.pm.PathPermission;
import android.content.pm.PermissionInfo;
@@ -260,7 +259,6 @@
import android.os.Message;
import android.os.Parcel;
import android.os.ParcelFileDescriptor;
-import android.os.PowerManager;
import android.os.PowerManager.ServiceType;
import android.os.PowerManagerInternal;
import android.os.Process;
@@ -283,7 +281,6 @@
import android.os.storage.StorageManagerInternal;
import android.provider.Downloads;
import android.provider.Settings;
-import android.service.voice.IVoiceInteractionSession;
import android.text.TextUtils;
import android.text.format.DateUtils;
import android.text.style.SuggestionSpan;
@@ -321,10 +318,8 @@
import com.android.internal.app.DumpHeapActivity;
import com.android.internal.app.IAppOpsCallback;
import com.android.internal.app.IAppOpsService;
-import com.android.internal.app.IVoiceInteractor;
import com.android.internal.app.ProcessMap;
import com.android.internal.app.SystemUserHomeActivity;
-import com.android.internal.app.procstats.AssociationState;
import com.android.internal.app.procstats.ProcessStats;
import com.android.internal.messages.nano.SystemMessageProto.SystemMessage;
import com.android.internal.notification.SystemNotificationChannels;
@@ -343,6 +338,8 @@
import com.android.internal.util.FastXmlSerializer;
import com.android.internal.util.MemInfoReader;
import com.android.internal.util.Preconditions;
+import com.android.internal.util.function.QuadFunction;
+import com.android.internal.util.function.TriFunction;
import com.android.server.AlarmManagerInternal;
import com.android.server.AppOpsService;
import com.android.server.AttributeCache;
@@ -360,21 +357,9 @@
import com.android.server.SystemServiceManager;
import com.android.server.ThreadPriorityBooster;
import com.android.server.Watchdog;
-import com.android.server.am.ActivityManagerServiceDumpActivitiesProto;
-import com.android.server.am.ActivityManagerServiceDumpBroadcastsProto;
-import com.android.server.am.ActivityManagerServiceDumpProcessesProto;
import com.android.server.am.ActivityManagerServiceDumpProcessesProto.UidObserverRegistrationProto;
-import com.android.server.am.ActivityManagerServiceDumpServicesProto;
-import com.android.server.am.ActivityManagerServiceProto;
import com.android.server.am.ActivityStack.ActivityState;
-import com.android.server.am.GrantUriProto;
-import com.android.server.am.ImportanceTokenProto;
-import com.android.server.am.MemInfoDumpProto;
import com.android.server.am.MemoryStatUtil.MemoryStat;
-import com.android.server.am.NeededUriGrantsProto;
-import com.android.server.am.ProcessOomProto;
-import com.android.server.am.ProcessToGcProto;
-import com.android.server.am.StickyBroadcastProto;
import com.android.server.firewall.IntentFirewall;
import com.android.server.job.JobSchedulerInternal;
import com.android.server.pm.Installer;
@@ -383,7 +368,6 @@
import com.android.server.utils.PriorityDump;
import com.android.server.vr.VrManagerInternal;
import com.android.server.wm.ActivityTaskManagerInternal;
-import com.android.server.wm.ActivityTaskManagerInternal.SleepToken;
import com.android.server.wm.WindowManagerService;
import org.xmlpull.v1.XmlPullParser;
@@ -423,6 +407,7 @@
import java.util.concurrent.Executor;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.atomic.AtomicLong;
+import java.util.function.BiFunction;
import dalvik.system.VMRuntime;
import libcore.io.IoUtils;
@@ -581,8 +566,6 @@
// Whether we should use SCHED_FIFO for UI and RenderThreads.
private boolean mUseFifoUiScheduling = false;
- private static final String SYSUI_COMPONENT_NAME = "com.android.systemui/.SystemUIService";
-
BroadcastQueue mFgBroadcastQueue;
BroadcastQueue mBgBroadcastQueue;
// Convenient for easy iteration over the queues. Foreground is first
@@ -639,7 +622,7 @@
boolean asProto) {
if (asProto) return;
doDump(fd, pw, new String[]{"activities"}, asProto);
- doDump(fd, pw, new String[]{"service", SYSUI_COMPONENT_NAME}, asProto);
+ doDump(fd, pw, new String[]{"service", "all-platform-critical"}, asProto);
}
@Override
@@ -9017,7 +9000,8 @@
}
ContentProviderConnection incProviderCountLocked(ProcessRecord r,
- final ContentProviderRecord cpr, IBinder externalProcessToken, boolean stable) {
+ final ContentProviderRecord cpr, IBinder externalProcessToken, int callingUid,
+ String callingTag, boolean stable) {
if (r != null) {
for (int i=0; i<r.conProviders.size(); i++) {
ContentProviderConnection conn = r.conProviders.get(i);
@@ -9052,7 +9036,7 @@
cpr.uid, cpr.appInfo.longVersionCode, cpr.name, cpr.info.processName);
return conn;
}
- cpr.addExternalProcessHandleLocked(externalProcessToken);
+ cpr.addExternalProcessHandleLocked(externalProcessToken, callingUid, callingTag);
return null;
}
@@ -9129,7 +9113,8 @@
}
private ContentProviderHolder getContentProviderImpl(IApplicationThread caller,
- String name, IBinder token, boolean stable, int userId) {
+ String name, IBinder token, int callingUid, String callingTag, boolean stable,
+ int userId) {
ContentProviderRecord cpr;
ContentProviderConnection conn = null;
ProviderInfo cpi = null;
@@ -9222,7 +9207,7 @@
// In this case the provider instance already exists, so we can
// return it right away.
- conn = incProviderCountLocked(r, cpr, token, stable);
+ conn = incProviderCountLocked(r, cpr, token, callingUid, callingTag, stable);
if (conn != null && (conn.stableCount+conn.unstableCount) == 1) {
if (cpr.proc != null && r.setAdj <= ProcessList.PERCEPTIBLE_APP_ADJ) {
// If this is a perceptible app accessing the provider,
@@ -9466,7 +9451,7 @@
}
mProviderMap.putProviderByName(name, cpr);
- conn = incProviderCountLocked(r, cpr, token, stable);
+ conn = incProviderCountLocked(r, cpr, token, callingUid, callingTag, stable);
if (conn != null) {
conn.waiting = true;
}
@@ -9577,21 +9562,23 @@
}
// The incoming user check is now handled in checkContentProviderPermissionLocked() to deal
// with cross-user grant.
- return getContentProviderImpl(caller, name, null, stable, userId);
+ return getContentProviderImpl(caller, name, null, Binder.getCallingUid(), null, stable,
+ userId);
}
public ContentProviderHolder getContentProviderExternal(
- String name, int userId, IBinder token) {
+ String name, int userId, IBinder token, String tag) {
enforceCallingPermission(android.Manifest.permission.ACCESS_CONTENT_PROVIDERS_EXTERNALLY,
"Do not have permission in call getContentProviderExternal()");
userId = mUserController.handleIncomingUser(Binder.getCallingPid(), Binder.getCallingUid(),
userId, false, ALLOW_FULL_ONLY, "getContentProvider", null);
- return getContentProviderExternalUnchecked(name, token, userId);
+ return getContentProviderExternalUnchecked(name, token, Binder.getCallingUid(),
+ tag != null ? tag : "*external*", userId);
}
private ContentProviderHolder getContentProviderExternalUnchecked(String name,
- IBinder token, int userId) {
- return getContentProviderImpl(null, name, token, true, userId);
+ IBinder token, int callingUid, String callingTag, int userId) {
+ return getContentProviderImpl(null, name, token, callingUid, callingTag, true, userId);
}
/**
@@ -9983,7 +9970,8 @@
}
ContentProviderHolder holder = null;
try {
- holder = getContentProviderExternalUnchecked(name, null, userId);
+ holder = getContentProviderExternalUnchecked(name, null, callingUid,
+ "*getmimetype*", userId);
if (holder != null) {
return holder.provider.getType(uri);
}
@@ -10198,7 +10186,8 @@
final int userId = UserHandle.getCallingUserId();
final Uri uri = Uri.parse(uriString);
String name = uri.getAuthority();
- ContentProviderHolder cph = getContentProviderExternalUnchecked(name, null, userId);
+ ContentProviderHolder cph = getContentProviderExternalUnchecked(name, null,
+ Binder.getCallingUid(), "*opencontent*", userId);
ParcelFileDescriptor pfd = null;
if (cph != null) {
// We record the binder invoker's uid in thread-local storage before
@@ -12124,7 +12113,7 @@
return imp;
}
- private void fillInProcMemInfoLocked(ProcessRecord app,
+ private void fillInProcMemInfo(ProcessRecord app,
ActivityManager.RunningAppProcessInfo outInfo,
int clientTargetSdk) {
outInfo.pid = app.pid;
@@ -12144,8 +12133,6 @@
outInfo.importance = procStateToImportance(procState, adj, outInfo, clientTargetSdk);
outInfo.importanceReasonCode = app.adjTypeCode;
outInfo.processState = app.curProcState;
- outInfo.isFocused = (app == getTopAppLocked());
- outInfo.lastActivityTime = app.lastActivityTime;
}
@Override
@@ -12176,7 +12163,7 @@
ActivityManager.RunningAppProcessInfo currApp =
new ActivityManager.RunningAppProcessInfo(app.processName,
app.pid, app.getPackageList());
- fillInProcMemInfoLocked(app, currApp, clientTargetSdk);
+ fillInProcMemInfo(app, currApp, clientTargetSdk);
if (app.adjSource instanceof ProcessRecord) {
currApp.importanceReasonPid = ((ProcessRecord)app.adjSource).pid;
currApp.importanceReasonImportance =
@@ -12245,7 +12232,7 @@
proc = mPidsSelfLocked.get(Binder.getCallingPid());
}
if (proc != null) {
- fillInProcMemInfoLocked(proc, outState, clientTargetSdk);
+ fillInProcMemInfo(proc, outState, clientTargetSdk);
}
}
}
@@ -16028,6 +16015,7 @@
}
updateCpuStatsNow();
long[] memtrackTmp = new long[1];
+ long[] swaptrackTmp = new long[2];
final List<ProcessCpuTracker.Stats> stats;
// Get a list of Stats that have vsize > 0
synchronized (mProcessCpuTracker) {
@@ -16038,12 +16026,13 @@
final int statsCount = stats.size();
for (int i = 0; i < statsCount; i++) {
ProcessCpuTracker.Stats st = stats.get(i);
- long pss = Debug.getPss(st.pid, null, memtrackTmp);
+ long pss = Debug.getPss(st.pid, swaptrackTmp, memtrackTmp);
if (pss > 0) {
if (infoMap.indexOfKey(st.pid) < 0) {
ProcessMemInfo mi = new ProcessMemInfo(st.name, st.pid,
ProcessList.NATIVE_ADJ, -1, "native", null);
mi.pss = pss;
+ mi.swapPss = swaptrackTmp[1];
mi.memtrack = memtrackTmp[0];
memInfos.add(mi);
}
@@ -16051,14 +16040,17 @@
}
long totalPss = 0;
+ long totalSwapPss = 0;
long totalMemtrack = 0;
for (int i=0, N=memInfos.size(); i<N; i++) {
ProcessMemInfo mi = memInfos.get(i);
if (mi.pss == 0) {
- mi.pss = Debug.getPss(mi.pid, null, memtrackTmp);
+ mi.pss = Debug.getPss(mi.pid, swaptrackTmp, memtrackTmp);
+ mi.swapPss = swaptrackTmp[1];
mi.memtrack = memtrackTmp[0];
}
totalPss += mi.pss;
+ totalSwapPss += mi.swapPss;
totalMemtrack += mi.memtrack;
}
Collections.sort(memInfos, new Comparator<ProcessMemInfo>() {
@@ -16220,7 +16212,7 @@
memInfoBuilder.append("\n");
memInfoBuilder.append(" Lost RAM: ");
memInfoBuilder.append(stringifyKBSize(memInfo.getTotalSizeKb()
- - totalPss - memInfo.getFreeSizeKb() - memInfo.getCachedSizeKb()
+ - (totalPss - totalSwapPss) - memInfo.getFreeSizeKb() - memInfo.getCachedSizeKb()
- memInfo.getKernelUsedSizeKb() - memInfo.getZramTotalSizeKb()));
memInfoBuilder.append("\n");
Slog.i(TAG, "Low on memory:");
@@ -18506,6 +18498,8 @@
// Can't call out of the system process with a lock held, so post a message.
if (app.instr.mUiAutomationConnection != null) {
+ mAppOpsService.setAppOpsServiceDelegate(null);
+ getPackageManagerInternalLocked().setCheckPermissionDelegate(null);
mHandler.obtainMessage(SHUTDOWN_UI_AUTOMATION_CONNECTION_MSG,
app.instr.mUiAutomationConnection).sendToTarget();
}
@@ -18751,6 +18745,129 @@
}
}
+ private final ComputeOomAdjWindowCallback mTmpComputeOomAdjWindowCallback =
+ new ComputeOomAdjWindowCallback();
+
+ private final class ComputeOomAdjWindowCallback
+ implements WindowProcessController.ComputeOomAdjCallback {
+
+ ProcessRecord app;
+ int adj;
+ boolean foregroundActivities;
+ int procState;
+ int schedGroup;
+ int appUid;
+ int logUid;
+ int processStateCurTop;
+
+ void initialize(ProcessRecord app, int adj, boolean foregroundActivities,
+ int procState, int schedGroup, int appUid, int logUid, int processStateCurTop) {
+ this.app = app;
+ this.adj = adj;
+ this.foregroundActivities = foregroundActivities;
+ this.procState = procState;
+ this.schedGroup = schedGroup;
+ this.appUid = appUid;
+ this.logUid = logUid;
+ this.processStateCurTop = processStateCurTop;
+ }
+
+ @Override
+ public void onVisibleActivity() {
+ // App has a visible activity; only upgrade adjustment.
+ if (adj > ProcessList.VISIBLE_APP_ADJ) {
+ adj = ProcessList.VISIBLE_APP_ADJ;
+ app.adjType = "vis-activity";
+ if (DEBUG_OOM_ADJ_REASON || logUid == appUid) {
+ reportOomAdjMessageLocked(TAG_OOM_ADJ, "Raise adj to vis-activity: " + app);
+ }
+ }
+ if (procState > processStateCurTop) {
+ procState = processStateCurTop;
+ app.adjType = "vis-activity";
+ if (DEBUG_OOM_ADJ_REASON || logUid == appUid) {
+ reportOomAdjMessageLocked(TAG_OOM_ADJ,
+ "Raise procstate to vis-activity (top): " + app);
+ }
+ }
+ if (schedGroup < ProcessList.SCHED_GROUP_DEFAULT) {
+ schedGroup = ProcessList.SCHED_GROUP_DEFAULT;
+ }
+ app.cached = false;
+ app.empty = false;
+ foregroundActivities = true;
+ }
+
+ @Override
+ public void onPausedActivity() {
+ if (adj > ProcessList.PERCEPTIBLE_APP_ADJ) {
+ adj = ProcessList.PERCEPTIBLE_APP_ADJ;
+ app.adjType = "pause-activity";
+ if (DEBUG_OOM_ADJ_REASON || logUid == appUid) {
+ reportOomAdjMessageLocked(TAG_OOM_ADJ, "Raise adj to pause-activity: " + app);
+ }
+ }
+ if (procState > processStateCurTop) {
+ procState = processStateCurTop;
+ app.adjType = "pause-activity";
+ if (DEBUG_OOM_ADJ_REASON || logUid == appUid) {
+ reportOomAdjMessageLocked(TAG_OOM_ADJ,
+ "Raise procstate to pause-activity (top): " + app);
+ }
+ }
+ if (schedGroup < ProcessList.SCHED_GROUP_DEFAULT) {
+ schedGroup = ProcessList.SCHED_GROUP_DEFAULT;
+ }
+ app.cached = false;
+ app.empty = false;
+ foregroundActivities = true;
+ }
+
+ @Override
+ public void onStoppingActivity(boolean finishing) {
+ if (adj > ProcessList.PERCEPTIBLE_APP_ADJ) {
+ adj = ProcessList.PERCEPTIBLE_APP_ADJ;
+ app.adjType = "stop-activity";
+ if (DEBUG_OOM_ADJ_REASON || logUid == appUid) {
+ reportOomAdjMessageLocked(TAG_OOM_ADJ,
+ "Raise adj to stop-activity: " + app);
+ }
+ }
+
+ // For the process state, we will at this point consider the process to be cached. It
+ // will be cached either as an activity or empty depending on whether the activity is
+ // finishing. We do this so that we can treat the process as cached for purposes of
+ // memory trimming (determining current memory level, trim command to send to process)
+ // since there can be an arbitrary number of stopping processes and they should soon all
+ // go into the cached state.
+ if (!finishing) {
+ if (procState > PROCESS_STATE_LAST_ACTIVITY) {
+ procState = PROCESS_STATE_LAST_ACTIVITY;
+ app.adjType = "stop-activity";
+ if (DEBUG_OOM_ADJ_REASON || logUid == appUid) {
+ reportOomAdjMessageLocked(TAG_OOM_ADJ,
+ "Raise procstate to stop-activity: " + app);
+ }
+ }
+ }
+ app.cached = false;
+ app.empty = false;
+ foregroundActivities = true;
+ }
+
+ @Override
+ public void onOtherActivity() {
+ if (procState > PROCESS_STATE_CACHED_ACTIVITY) {
+ procState = PROCESS_STATE_CACHED_ACTIVITY;
+ app.adjType = "cch-act";
+ if (DEBUG_OOM_ADJ_REASON || logUid == appUid) {
+ reportOomAdjMessageLocked(TAG_OOM_ADJ,
+ "Raise procstate to cached activity: " + app);
+ }
+ }
+ }
+ }
+
private final boolean computeOomAdjLocked(ProcessRecord app, int cachedAdj, ProcessRecord TOP_APP,
boolean doingAll, long now) {
if (mAdjSeq == app.adjSeq) {
@@ -18922,119 +19039,15 @@
// Examine all activities if not already foreground.
if (!foregroundActivities && wpc.hasActivities()) {
- final int[] adjHolder = new int[1];
- adjHolder[0] = adj;
- final boolean[] foregroundActivitiesHolder = new boolean[1];
- foregroundActivitiesHolder[0] = foregroundActivities;
- int[] procStateHolder = new int[1];
- procStateHolder[0] = procState;
- int[] schedGroupHolder = new int[1];
- schedGroupHolder[0] = schedGroup;
+ mTmpComputeOomAdjWindowCallback.initialize(app, adj, foregroundActivities, procState,
+ schedGroup, appUid, logUid, PROCESS_STATE_CUR_TOP);
+ final int minLayer = wpc.computeOomAdjFromActivities(
+ ProcessList.VISIBLE_APP_LAYER_MAX, mTmpComputeOomAdjWindowCallback);
- int minLayer = wpc.computeOomAdjFromActivities(ProcessList.VISIBLE_APP_LAYER_MAX,
- new WindowProcessController.ComputeOomAdjCallback() {
- @Override
- public void onVisibleActivity() {
- // App has a visible activity; only upgrade adjustment.
- if (adjHolder[0] > ProcessList.VISIBLE_APP_ADJ) {
- adjHolder[0] = ProcessList.VISIBLE_APP_ADJ;
- app.adjType = "vis-activity";
- if (DEBUG_OOM_ADJ_REASON || logUid == appUid) {
- reportOomAdjMessageLocked(TAG_OOM_ADJ,
- "Raise adj to vis-activity: " + app);
- }
- }
- if (procStateHolder[0] > PROCESS_STATE_CUR_TOP) {
- procStateHolder[0] = PROCESS_STATE_CUR_TOP;
- app.adjType = "vis-activity";
- if (DEBUG_OOM_ADJ_REASON || logUid == appUid) {
- reportOomAdjMessageLocked(TAG_OOM_ADJ,
- "Raise procstate to vis-activity (top): " + app);
- }
- }
- if (schedGroupHolder[0] < ProcessList.SCHED_GROUP_DEFAULT) {
- schedGroupHolder[0] = ProcessList.SCHED_GROUP_DEFAULT;
- }
- app.cached = false;
- app.empty = false;
- foregroundActivitiesHolder[0] = true;
- }
-
- @Override
- public void onPausedActivity() {
- if (adjHolder[0] > ProcessList.PERCEPTIBLE_APP_ADJ) {
- adjHolder[0] = ProcessList.PERCEPTIBLE_APP_ADJ;
- app.adjType = "pause-activity";
- if (DEBUG_OOM_ADJ_REASON || logUid == appUid) {
- reportOomAdjMessageLocked(TAG_OOM_ADJ,
- "Raise adj to pause-activity: " + app);
- }
- }
- if (procStateHolder[0] > PROCESS_STATE_CUR_TOP) {
- procStateHolder[0] = PROCESS_STATE_CUR_TOP;
- app.adjType = "pause-activity";
- if (DEBUG_OOM_ADJ_REASON || logUid == appUid) {
- reportOomAdjMessageLocked(TAG_OOM_ADJ,
- "Raise procstate to pause-activity (top): " + app);
- }
- }
- if (schedGroupHolder[0] < ProcessList.SCHED_GROUP_DEFAULT) {
- schedGroupHolder[0] = ProcessList.SCHED_GROUP_DEFAULT;
- }
- app.cached = false;
- app.empty = false;
- foregroundActivitiesHolder[0] = true;
- }
-
- @Override
- public void onStoppingActivity(boolean finishing) {
- if (adjHolder[0] > ProcessList.PERCEPTIBLE_APP_ADJ) {
- adjHolder[0] = ProcessList.PERCEPTIBLE_APP_ADJ;
- app.adjType = "stop-activity";
- if (DEBUG_OOM_ADJ_REASON || logUid == appUid) {
- reportOomAdjMessageLocked(TAG_OOM_ADJ,
- "Raise adj to stop-activity: " + app);
- }
- }
- // For the process state, we will at this point consider the process to
- // be cached. It will be cached either as an activity or empty depending
- // on whether the activity is finishing. We do this so that we can treat
- // the process as cached for purposes of memory trimming (determining
- // current memory level, trim command to send to process) since there
- // can be an arbitrary number of stopping processes and they should soon
- // all go into the cached state.
- if (!finishing) {
- if (procStateHolder[0] > PROCESS_STATE_LAST_ACTIVITY) {
- procStateHolder[0] = PROCESS_STATE_LAST_ACTIVITY;
- app.adjType = "stop-activity";
- if (DEBUG_OOM_ADJ_REASON || logUid == appUid) {
- reportOomAdjMessageLocked(TAG_OOM_ADJ,
- "Raise procstate to stop-activity: " + app);
- }
- }
- }
- app.cached = false;
- app.empty = false;
- foregroundActivitiesHolder[0] = true;
- }
-
- @Override
- public void onOtherActivity() {
- if (procStateHolder[0] > PROCESS_STATE_CACHED_ACTIVITY) {
- procStateHolder[0] = PROCESS_STATE_CACHED_ACTIVITY;
- app.adjType = "cch-act";
- if (DEBUG_OOM_ADJ_REASON || logUid == appUid) {
- reportOomAdjMessageLocked(TAG_OOM_ADJ,
- "Raise procstate to cached activity: " + app);
- }
- }
- }
- });
-
- adj = adjHolder[0];
- foregroundActivities = foregroundActivitiesHolder[0];
- procState = procStateHolder[0];
- schedGroup = schedGroupHolder[0];
+ adj = mTmpComputeOomAdjWindowCallback.adj;
+ foregroundActivities = mTmpComputeOomAdjWindowCallback.foregroundActivities;
+ procState = mTmpComputeOomAdjWindowCallback.procState;
+ schedGroup = mTmpComputeOomAdjWindowCallback.schedGroup;
if (adj == ProcessList.VISIBLE_APP_ADJ) {
adj += minLayer;
@@ -19257,10 +19270,11 @@
// all connected clients.
ConnectionRecord cr = clist.get(i);
if (cr.binding.client == app) {
- // Binding to ourself is not interesting.
+ // Binding to oneself is not interesting.
continue;
}
+ boolean trackedProcState = false;
if ((cr.flags&Context.BIND_WAIVE_PRIORITY) == 0) {
ProcessRecord client = cr.binding.client;
computeOomAdjLocked(client, cachedAdj, TOP_APP, doingAll, now);
@@ -19332,6 +19346,8 @@
newAdj = ProcessList.PERSISTENT_SERVICE_ADJ;
schedGroup = ProcessList.SCHED_GROUP_DEFAULT;
procState = ActivityManager.PROCESS_STATE_PERSISTENT;
+ cr.trackProcState(procState, mAdjSeq, now);
+ trackedProcState = true;
}
} else if ((cr.flags&Context.BIND_NOT_VISIBLE) != 0
&& clientAdj < ProcessList.PERCEPTIBLE_APP_ADJ
@@ -19417,6 +19433,9 @@
ActivityManager.PROCESS_STATE_IMPORTANT_BACKGROUND;
}
}
+ if (!trackedProcState) {
+ cr.trackProcState(clientProcState, mAdjSeq, now);
+ }
if (procState > clientProcState) {
procState = clientProcState;
if (adjType == null) {
@@ -19546,6 +19565,7 @@
}
}
}
+ conn.trackProcState(clientProcState, mAdjSeq, now);
if (procState > clientProcState) {
procState = clientProcState;
}
@@ -20644,23 +20664,21 @@
}
@GuardedBy("this")
- ProcessRecord getTopAppLocked() {
- final ActivityRecord TOP_ACT = resumedAppLocked();
- if (TOP_ACT != null && TOP_ACT.hasProcess()) {
- return (ProcessRecord) TOP_ACT.app.mOwner;
- } else {
- return null;
- }
- }
-
- @GuardedBy("this")
final void updateOomAdjLocked() {
- final ProcessRecord TOP_APP = getTopAppLocked();
+ final ActivityRecord TOP_ACT = resumedAppLocked();
+ final ProcessRecord TOP_APP = TOP_ACT != null && TOP_ACT.hasProcess()
+ ? (ProcessRecord) TOP_ACT.app.mOwner : null;
final long now = SystemClock.uptimeMillis();
final long nowElapsed = SystemClock.elapsedRealtime();
final long oldTime = now - ProcessList.MAX_EMPTY_TIME;
final int N = mLruProcesses.size();
+ if (false) {
+ RuntimeException e = new RuntimeException();
+ e.fillInStackTrace();
+ Slog.i(TAG, "updateOomAdj: top=" + TOP_ACT, e);
+ }
+
// Reset state in all uid records.
for (int i=mActiveUids.size()-1; i>=0; i--) {
final UidRecord uidRec = mActiveUids.valueAt(i);
@@ -20815,6 +20833,7 @@
}
}
}
+
for (int i=N-1; i>=0; i--) {
ProcessRecord app = mLruProcesses.get(i);
if (!app.killedByAm && app.thread != null) {
@@ -20878,6 +20897,8 @@
}
}
+ mProcessStats.updateTrackingAssociationsLocked(mAdjSeq, now);
+
incrementProcStateSeqAndNotifyAppsLocked();
mNumServiceProcs = mNewNumServiceProcs;
@@ -22308,9 +22329,8 @@
@Override
public boolean isUserRunning(int userId, int flags) {
- synchronized (ActivityManagerService.this) {
- return mUserController.isUserRunning(userId, flags);
- }
+ // Holding am lock isn't required to call into user controller.
+ return mUserController.isUserRunning(userId, flags);
}
@Override
@@ -22381,6 +22401,41 @@
public void sendForegroundProfileChanged(int userId) {
mUserController.sendForegroundProfileChanged(userId);
}
+
+ @Override
+ public boolean shouldConfirmCredentials(int userId) {
+ return mUserController.shouldConfirmCredentials(userId);
+ }
+
+ @Override
+ public int[] getCurrentProfileIds() {
+ return mUserController.getCurrentProfileIds();
+ }
+
+ @Override
+ public UserInfo getCurrentUser() {
+ return mUserController.getCurrentUser();
+ }
+
+ @Override
+ public void ensureNotSpecialUser(int userId) {
+ mUserController.ensureNotSpecialUser(userId);
+ }
+
+ @Override
+ public boolean isCurrentProfile(int userId) {
+ return mUserController.isCurrentProfile(userId);
+ }
+
+ @Override
+ public boolean hasStartedUserState(int userId) {
+ return mUserController.hasStartedUserState(userId);
+ }
+
+ @Override
+ public void finishUserSwitch(Object uss) {
+ mUserController.finishUserSwitch((UserState) uss);
+ }
}
/**
@@ -22631,4 +22686,143 @@
return mNmi != null;
}
}
+
+ @Override
+ public void startDelegateShellPermissionIdentity(int delegateUid) {
+ if (UserHandle.getCallingAppId() != Process.SHELL_UID
+ && UserHandle.getCallingAppId() != Process.ROOT_UID) {
+ throw new SecurityException("Only the shell can delegate its permissions");
+ }
+
+ // We allow delegation only to one instrumentation started from the shell
+ synchronized (ActivityManagerService.this) {
+ // If there is a delegate it should be the same instance for app ops and permissions.
+ if (mAppOpsService.getAppOpsServiceDelegate()
+ != getPackageManagerInternalLocked().getCheckPermissionDelegate()) {
+ throw new IllegalStateException("Bad shell delegate state");
+ }
+
+ // If the delegate is already set up for the target UID, nothing to do.
+ if (mAppOpsService.getAppOpsServiceDelegate() != null) {
+ if (!(mAppOpsService.getAppOpsServiceDelegate() instanceof ShellDelegate)) {
+ throw new IllegalStateException("Bad shell delegate state");
+ }
+ if (((ShellDelegate) mAppOpsService.getAppOpsServiceDelegate())
+ .getDelegateUid() != delegateUid) {
+ throw new SecurityException("Shell can delegate permissions only "
+ + "to one instrumentation at a time");
+ }
+ return;
+ }
+
+ final int instrCount = mActiveInstrumentation.size();
+ for (int i = 0; i < instrCount; i++) {
+ final ActiveInstrumentation instr = mActiveInstrumentation.get(i);
+ if (instr.mTargetInfo.uid != delegateUid) {
+ continue;
+ }
+ // If instrumentation started from the shell the connection is not null
+ if (instr.mUiAutomationConnection == null) {
+ throw new SecurityException("Shell can delegate its permissions" +
+ " only to an instrumentation started from the shell");
+ }
+
+ // Hook them up...
+ final ShellDelegate shellDelegate = new ShellDelegate(
+ instr.mTargetInfo.packageName, delegateUid);
+ mAppOpsService.setAppOpsServiceDelegate(shellDelegate);
+ getPackageManagerInternalLocked().setCheckPermissionDelegate(shellDelegate);
+ return;
+ }
+ }
+ }
+
+ @Override
+ public void stopDelegateShellPermissionIdentity() {
+ if (UserHandle.getCallingAppId() != Process.SHELL_UID
+ && UserHandle.getCallingAppId() != Process.ROOT_UID) {
+ throw new SecurityException("Only the shell can delegate its permissions");
+ }
+ synchronized (ActivityManagerService.this) {
+ mAppOpsService.setAppOpsServiceDelegate(null);
+ getPackageManagerInternalLocked().setCheckPermissionDelegate(null);
+ }
+ }
+
+ private class ShellDelegate implements CheckOpsDelegate, CheckPermissionDelegate {
+ private final String mTargetPackageName;
+ private final int mTargetUid;
+
+ ShellDelegate(String targetPacakgeName, int targetUid) {
+ mTargetPackageName = targetPacakgeName;
+ mTargetUid = targetUid;
+ }
+
+ int getDelegateUid() {
+ return mTargetUid;
+ }
+
+ @Override
+ public int checkOperation(int code, int uid, String packageName,
+ TriFunction<Integer, Integer, String, Integer> superImpl) {
+ if (uid == mTargetUid) {
+ final long identity = Binder.clearCallingIdentity();
+ try {
+ return superImpl.apply(code, Process.SHELL_UID,
+ "com.android.shell");
+ } finally {
+ Binder.restoreCallingIdentity(identity);
+ }
+ }
+ return superImpl.apply(code, uid, packageName);
+ }
+
+ @Override
+ public int checkAudioOperation(int code, int usage, int uid, String packageName,
+ QuadFunction<Integer, Integer, Integer, String, Integer> superImpl) {
+ if (uid == mTargetUid) {
+ final long identity = Binder.clearCallingIdentity();
+ try {
+ return superImpl.apply(code, usage, Process.SHELL_UID,
+ "com.android.shell");
+ } finally {
+ Binder.restoreCallingIdentity(identity);
+ }
+ }
+ return superImpl.apply(code, usage, uid, packageName);
+ }
+
+ @Override
+ public int noteOperation(int code, int uid, String packageName,
+ TriFunction<Integer, Integer, String, Integer> superImpl) {
+ if (uid == mTargetUid) {
+ final long identity = Binder.clearCallingIdentity();
+ try {
+ return mAppOpsService.noteProxyOperation(code, Process.SHELL_UID,
+ "com.android.shell", uid, packageName);
+ } finally {
+ Binder.restoreCallingIdentity(identity);
+ }
+ }
+ return superImpl.apply(code, uid, packageName);
+ }
+
+ @Override
+ public int checkPermission(String permName, String pkgName, int userId,
+ TriFunction<String, String, Integer, Integer> superImpl) {
+ if (mTargetPackageName.equals(pkgName)) {
+ return superImpl.apply(permName, "com.android.shell", userId);
+ }
+ return superImpl.apply(permName, pkgName, userId);
+ }
+
+ @Override
+ public int checkUidPermission(String permName, int uid,
+ BiFunction<String, Integer, Integer> superImpl) {
+ if (uid == mTargetUid) {
+ return superImpl.apply(permName, Process.SHELL_UID);
+ }
+ return superImpl.apply(permName, uid);
+ }
+ }
}
diff --git a/services/core/java/com/android/server/am/ActivityRecord.java b/services/core/java/com/android/server/am/ActivityRecord.java
index b44ce9a..70f638d 100644
--- a/services/core/java/com/android/server/am/ActivityRecord.java
+++ b/services/core/java/com/android/server/am/ActivityRecord.java
@@ -1877,7 +1877,7 @@
// TODO: To be more accurate, the mark should be before the onCreate,
// not after the onResume. But for subsequent starts, onResume is fine.
if (hasProcess()) {
- cpuTimeAtResume = service.mAm.mProcessCpuTracker.getCpuTimeForPid(app.getPid());
+ cpuTimeAtResume = app.getCpuTime();
} else {
cpuTimeAtResume = 0; // Couldn't get the cpu time of process
}
@@ -2186,7 +2186,7 @@
return (info.flags & FLAG_SHOW_FOR_ALL_USERS) != 0
|| (mStackSupervisor.isCurrentProfileLocked(userId)
- && service.mAm.mUserController.isUserRunning(userId, 0 /* flags */));
+ && service.mAmInternal.isUserRunning(userId, 0 /* flags */));
}
/**
diff --git a/services/core/java/com/android/server/am/ActivityStack.java b/services/core/java/com/android/server/am/ActivityStack.java
index c76df8b..b0f1c45 100644
--- a/services/core/java/com/android/server/am/ActivityStack.java
+++ b/services/core/java/com/android/server/am/ActivityStack.java
@@ -457,7 +457,7 @@
mHandler = new ActivityStackHandler(supervisor.mLooper);
mWindowManager = mService.mWindowManager;
mStackId = stackId;
- mCurrentUser = mService.mAm.mUserController.getCurrentUserId();
+ mCurrentUser = mService.mAmInternal.getCurrentUserId();
mTmpRect2.setEmpty();
// Set display id before setting activity and window type to make sure it won't affect
// stacks on a wrong display.
@@ -1622,8 +1622,7 @@
if (prev.hasProcess() && prev.cpuTimeAtResume > 0
&& mService.mAm.mBatteryStatsService.isOnBattery()) {
- long diff = mService.mAm.mProcessCpuTracker.getCpuTimeForPid(prev.app.getPid())
- - prev.cpuTimeAtResume;
+ long diff = prev.app.getCpuTime() - prev.cpuTimeAtResume;
if (diff > 0) {
BatteryStatsImpl bsi = mService.mAm.mBatteryStatsService.getActiveStatistics();
synchronized (bsi) {
@@ -2398,7 +2397,7 @@
// Make sure that the user who owns this activity is started. If not,
// we will just leave it as is because someone should be bringing
// another user's activities to the top of the stack.
- if (!mService.mAm.mUserController.hasStartedUserState(next.userId)) {
+ if (!mService.mAmInternal.hasStartedUserState(next.userId)) {
Slog.w(TAG, "Skipping resume of top activity " + next
+ ": user " + next.userId + " is stopped");
if (DEBUG_STACK) mStackSupervisor.validateTopActivitiesLocked();
diff --git a/services/core/java/com/android/server/am/ActivityStackSupervisor.java b/services/core/java/com/android/server/am/ActivityStackSupervisor.java
index 7f749b3..e3e1c48 100644
--- a/services/core/java/com/android/server/am/ActivityStackSupervisor.java
+++ b/services/core/java/com/android/server/am/ActivityStackSupervisor.java
@@ -2112,12 +2112,12 @@
// Complete user switch
if (startingUsers != null) {
for (int i = 0; i < startingUsers.size(); i++) {
- mService.mAm.mUserController.finishUserSwitch(startingUsers.get(i));
+ mService.mAmInternal.finishUserSwitch(startingUsers.get(i));
}
}
}
- mService.mAm.trimApplications();
+ mService.mAmInternal.trimApplications();
//dump();
//mWindowManager.dump();
@@ -3837,7 +3837,7 @@
/** Checks whether the userid is a profile of the current user. */
boolean isCurrentProfileLocked(int userId) {
if (userId == mCurrentUser) return true;
- return mService.mAm.mUserController.isCurrentProfile(userId);
+ return mService.mAmInternal.isCurrentProfile(userId);
}
/**
@@ -4789,7 +4789,7 @@
// If the user must confirm credentials (e.g. when first launching a work app and the
// Work Challenge is present) let startActivityInPackage handle the intercepting.
- if (!mService.mAm.mUserController.shouldConfirmCredentials(task.userId)
+ if (!mService.mAmInternal.shouldConfirmCredentials(task.userId)
&& task.getRootActivity() != null) {
final ActivityRecord targetActivity = task.getTopActivity();
diff --git a/services/core/java/com/android/server/am/ActivityStartController.java b/services/core/java/com/android/server/am/ActivityStartController.java
index f7ea4b2..1107671 100644
--- a/services/core/java/com/android/server/am/ActivityStartController.java
+++ b/services/core/java/com/android/server/am/ActivityStartController.java
@@ -240,7 +240,7 @@
return mService.handleIncomingUser(
realCallingPid, realCallingUid, targetUserId, reason);
} else {
- mService.mAm.mUserController.ensureNotSpecialUser(targetUserId);
+ mService.mAmInternal.ensureNotSpecialUser(targetUserId);
return targetUserId;
}
}
diff --git a/services/core/java/com/android/server/am/ActivityStartInterceptor.java b/services/core/java/com/android/server/am/ActivityStartInterceptor.java
index 171c0bb..ca12716 100644
--- a/services/core/java/com/android/server/am/ActivityStartInterceptor.java
+++ b/services/core/java/com/android/server/am/ActivityStartInterceptor.java
@@ -69,7 +69,6 @@
private final ActivityTaskManagerService mService;
private final ActivityStackSupervisor mSupervisor;
private final Context mServiceContext;
- private final UserController mUserController;
// UserManager cannot be final as it's not ready when this class is instantiated during boot
private UserManager mUserManager;
@@ -101,16 +100,15 @@
ActivityStartInterceptor(
ActivityTaskManagerService service, ActivityStackSupervisor supervisor) {
- this(service, supervisor, service.mContext, service.mAm.mUserController);
+ this(service, supervisor, service.mContext);
}
@VisibleForTesting
ActivityStartInterceptor(ActivityTaskManagerService service, ActivityStackSupervisor supervisor,
- Context context, UserController userController) {
+ Context context) {
mService = service;
mSupervisor = supervisor;
mServiceContext = context;
- mUserController = userController;
}
/**
@@ -298,7 +296,7 @@
* @return The intercepting intent if needed.
*/
private Intent interceptWithConfirmCredentialsIfNeeded(ActivityInfo aInfo, int userId) {
- if (!mUserController.shouldConfirmCredentials(userId)) {
+ if (!mService.mAmInternal.shouldConfirmCredentials(userId)) {
return null;
}
// TODO(b/28935539): should allow certain activities to bypass work challenge
diff --git a/services/core/java/com/android/server/am/ActivityTaskManagerService.java b/services/core/java/com/android/server/am/ActivityTaskManagerService.java
index 50d0212..3ed2875 100644
--- a/services/core/java/com/android/server/am/ActivityTaskManagerService.java
+++ b/services/core/java/com/android/server/am/ActivityTaskManagerService.java
@@ -4547,9 +4547,9 @@
return mShowDialogs && !mSleeping && !mShuttingDown
&& !mKeyguardController.isKeyguardOrAodShowing(DEFAULT_DISPLAY)
&& !hasUserRestriction(UserManager.DISALLOW_SYSTEM_ERROR_DIALOGS,
- mAm.mUserController.getCurrentUserId())
+ mAmInternal.getCurrentUserId())
&& !(UserManager.isDeviceInDemoMode(mContext)
- && mAm.mUserController.getCurrentUser().isDemo());
+ && mAmInternal.getCurrentUser().isDemo());
}
/**
diff --git a/services/core/java/com/android/server/am/ConnectionRecord.java b/services/core/java/com/android/server/am/ConnectionRecord.java
index c348aee..2cea4fa 100644
--- a/services/core/java/com/android/server/am/ConnectionRecord.java
+++ b/services/core/java/com/android/server/am/ConnectionRecord.java
@@ -106,7 +106,10 @@
}
public void startAssociationIfNeeded() {
- if (association == null) {
+ // If we don't already have an active association, create one... but only if this
+ // is an association between two different processes.
+ if (association == null && (binding.service.appInfo.uid != clientUid
+ || !binding.service.processName.equals(clientProcessName))) {
ProcessStats.ProcessStateHolder holder = binding.service.app != null
? binding.service.app.pkgList.get(binding.service.name.getPackageName()) : null;
if (holder == null) {
@@ -116,7 +119,7 @@
Slog.wtf(TAG_AM, "Inactive holder in referenced service "
+ binding.service.name.toShortString() + ": proc=" + binding.service.app);
} else {
- association = holder.pkg.getAssociationStateLocked(binding.service.processName,
+ association = holder.pkg.getAssociationStateLocked(holder.state,
binding.service.name.getClassName()).startSource(clientUid,
clientProcessName);
@@ -124,6 +127,12 @@
}
}
+ public void trackProcState(int procState, int seq, long now) {
+ if (association != null) {
+ association.trackProcState(procState, seq, now);
+ }
+ }
+
public void stopAssociation() {
if (association != null) {
association.stop();
diff --git a/services/core/java/com/android/server/am/ContentProviderConnection.java b/services/core/java/com/android/server/am/ContentProviderConnection.java
index 0320b10..36d3f4f 100644
--- a/services/core/java/com/android/server/am/ContentProviderConnection.java
+++ b/services/core/java/com/android/server/am/ContentProviderConnection.java
@@ -53,7 +53,10 @@
}
public void startAssociationIfNeeded() {
- if (association == null) {
+ // If we don't already have an active association, create one... but only if this
+ // is an association between two different processes.
+ if (association == null && (provider.appInfo.uid != client.uid
+ || !provider.info.processName.equals(client.processName))) {
ProcessStats.ProcessStateHolder holder = provider.proc != null
? provider.proc.pkgList.get(provider.name.getPackageName()) : null;
if (holder == null) {
@@ -63,13 +66,19 @@
Slog.wtf(TAG_AM, "Inactive holder in referenced provider "
+ provider.name.toShortString() + ": proc=" + provider.proc);
} else {
- association = holder.pkg.getAssociationStateLocked(provider.info.processName,
+ association = holder.pkg.getAssociationStateLocked(holder.state,
provider.name.getClassName()).startSource(client.uid, client.processName);
}
}
}
+ public void trackProcState(int procState, int seq, long now) {
+ if (association != null) {
+ association.trackProcState(procState, seq, now);
+ }
+ }
+
public void stopAssociation() {
if (association != null) {
association.stop();
diff --git a/services/core/java/com/android/server/am/ContentProviderRecord.java b/services/core/java/com/android/server/am/ContentProviderRecord.java
index 07ae1ae..53783be 100644
--- a/services/core/java/com/android/server/am/ContentProviderRecord.java
+++ b/services/core/java/com/android/server/am/ContentProviderRecord.java
@@ -16,6 +16,8 @@
package com.android.server.am;
+import static com.android.server.am.ActivityManagerDebugConfig.TAG_AM;
+
import android.app.ContentProviderHolder;
import android.content.ComponentName;
import android.content.IContentProvider;
@@ -26,11 +28,14 @@
import android.os.Process;
import android.os.RemoteException;
import android.os.UserHandle;
+import android.util.ArrayMap;
import android.util.Slog;
+import com.android.internal.app.procstats.AssociationState;
+import com.android.internal.app.procstats.ProcessStats;
+
import java.io.PrintWriter;
import java.util.ArrayList;
-import java.util.HashMap;
final class ContentProviderRecord implements ComponentName.WithComponentName {
final ActivityManagerService service;
@@ -46,7 +51,7 @@
= new ArrayList<ContentProviderConnection>();
//final HashSet<ProcessRecord> clients = new HashSet<ProcessRecord>();
// Handles for non-framework processes supported by this provider
- HashMap<IBinder, ExternalProcessHandle> externalProcessTokenToHandle;
+ ArrayMap<IBinder, ExternalProcessHandle> externalProcessTokenToHandle;
// Count for external process for which we have no handles.
int externalProcessNoHandleCount;
ProcessRecord proc; // if non-null, hosting process.
@@ -93,6 +98,16 @@
conn.stopAssociation();
}
}
+ if (externalProcessTokenToHandle != null) {
+ for (int iext = externalProcessTokenToHandle.size() - 1; iext >= 0; iext--) {
+ final ExternalProcessHandle handle = externalProcessTokenToHandle.valueAt(iext);
+ if (proc != null) {
+ handle.startAssociationIfNeeded(this);
+ } else {
+ handle.stopAssociation();
+ }
+ }
+ }
}
public boolean canRunHere(ProcessRecord app) {
@@ -100,17 +115,18 @@
&& uid == app.info.uid;
}
- public void addExternalProcessHandleLocked(IBinder token) {
+ public void addExternalProcessHandleLocked(IBinder token, int callingUid, String callingTag) {
if (token == null) {
externalProcessNoHandleCount++;
} else {
if (externalProcessTokenToHandle == null) {
- externalProcessTokenToHandle = new HashMap<IBinder, ExternalProcessHandle>();
+ externalProcessTokenToHandle = new ArrayMap<>();
}
ExternalProcessHandle handle = externalProcessTokenToHandle.get(token);
if (handle == null) {
- handle = new ExternalProcessHandle(token);
+ handle = new ExternalProcessHandle(token, callingUid, callingTag);
externalProcessTokenToHandle.put(token, handle);
+ handle.startAssociationIfNeeded(this);
}
handle.mAcquisitionCount++;
}
@@ -141,6 +157,7 @@
private void removeExternalProcessHandleInternalLocked(IBinder token) {
ExternalProcessHandle handle = externalProcessTokenToHandle.get(token);
handle.unlinkFromOwnDeathLocked();
+ handle.stopAssociation();
externalProcessTokenToHandle.remove(token);
if (externalProcessTokenToHandle.size() == 0) {
externalProcessTokenToHandle = null;
@@ -246,11 +263,16 @@
private class ExternalProcessHandle implements DeathRecipient {
private static final String LOG_TAG = "ExternalProcessHanldle";
- private final IBinder mToken;
- private int mAcquisitionCount;
+ final IBinder mToken;
+ final int mOwningUid;
+ final String mOwningProcessName;
+ int mAcquisitionCount;
+ AssociationState.SourceState mAssociation;
- public ExternalProcessHandle(IBinder token) {
+ public ExternalProcessHandle(IBinder token, int owningUid, String owningProcessName) {
mToken = token;
+ mOwningUid = owningUid;
+ mOwningProcessName = owningProcessName;
try {
token.linkToDeath(this, 0);
} catch (RemoteException re) {
@@ -262,6 +284,35 @@
mToken.unlinkToDeath(this, 0);
}
+ public void startAssociationIfNeeded(ContentProviderRecord provider) {
+ // If we don't already have an active association, create one... but only if this
+ // is an association between two different processes.
+ if (mAssociation == null && (provider.appInfo.uid != mOwningUid
+ || !provider.info.processName.equals(mOwningProcessName))) {
+ ProcessStats.ProcessStateHolder holder = provider.proc != null
+ ? provider.proc.pkgList.get(provider.name.getPackageName()) : null;
+ if (holder == null) {
+ Slog.wtf(TAG_AM, "No package in referenced provider "
+ + provider.name.toShortString() + ": proc=" + provider.proc);
+ } else if (holder.pkg == null) {
+ Slog.wtf(TAG_AM, "Inactive holder in referenced provider "
+ + provider.name.toShortString() + ": proc=" + provider.proc);
+ } else {
+ mAssociation = holder.pkg.getAssociationStateLocked(holder.state,
+ provider.name.getClassName()).startSource(mOwningUid,
+ mOwningProcessName);
+
+ }
+ }
+ }
+
+ public void stopAssociation() {
+ if (mAssociation != null) {
+ mAssociation.stop();
+ mAssociation = null;
+ }
+ }
+
@Override
public void binderDied() {
synchronized (service) {
diff --git a/services/core/java/com/android/server/am/ProcessMemInfo.java b/services/core/java/com/android/server/am/ProcessMemInfo.java
index 83d29e2..6c10a2a 100644
--- a/services/core/java/com/android/server/am/ProcessMemInfo.java
+++ b/services/core/java/com/android/server/am/ProcessMemInfo.java
@@ -24,6 +24,7 @@
final String adjType;
final String adjReason;
long pss;
+ long swapPss;
long memtrack;
public ProcessMemInfo(String _name, int _pid, int _oomAdj, int _procState,
diff --git a/services/core/java/com/android/server/am/ProcessRecord.java b/services/core/java/com/android/server/am/ProcessRecord.java
index 940e079..ea6d134 100644
--- a/services/core/java/com/android/server/am/ProcessRecord.java
+++ b/services/core/java/com/android/server/am/ProcessRecord.java
@@ -1002,4 +1002,11 @@
}
}
+ /**
+ * Returns the total time (in milliseconds) spent executing in both user and system code.
+ * Safe to call without lock held.
+ */
+ public long getCpuTime() {
+ return mService.mProcessCpuTracker.getCpuTimeForPid(pid);
+ }
}
diff --git a/services/core/java/com/android/server/am/ProcessStatsService.java b/services/core/java/com/android/server/am/ProcessStatsService.java
index e1bc1bc..f0bd8fa 100644
--- a/services/core/java/com/android/server/am/ProcessStatsService.java
+++ b/services/core/java/com/android/server/am/ProcessStatsService.java
@@ -32,7 +32,6 @@
import android.util.proto.ProtoOutputStream;
import com.android.internal.annotations.GuardedBy;
-import com.android.internal.app.procstats.AssociationState;
import com.android.internal.app.procstats.DumpUtils;
import com.android.internal.app.procstats.IProcessStats;
import com.android.internal.app.procstats.ProcessState;
@@ -194,6 +193,11 @@
}
@GuardedBy("mAm")
+ public void updateTrackingAssociationsLocked(int curSeq, long now) {
+ mProcessStats.updateTrackingAssociationsLocked(curSeq, now);
+ }
+
+ @GuardedBy("mAm")
public boolean shouldWriteNowLocked(long now) {
if (now > (mLastWriteTime+WRITE_PERIOD)) {
if (SystemClock.elapsedRealtime()
diff --git a/services/core/java/com/android/server/am/RecentTasks.java b/services/core/java/com/android/server/am/RecentTasks.java
index 749589b..1967c76 100644
--- a/services/core/java/com/android/server/am/RecentTasks.java
+++ b/services/core/java/com/android/server/am/RecentTasks.java
@@ -78,6 +78,7 @@
import java.util.Collections;
import java.util.Comparator;
import java.util.HashMap;
+import java.util.List;
import java.util.Set;
import java.util.concurrent.TimeUnit;
@@ -140,7 +141,6 @@
private final TaskPersister mTaskPersister;
private final ActivityTaskManagerService mService;
private final ActivityStackSupervisor mSupervisor;
- private final UserController mUserController;
/**
* Keeps track of the static recents package/component which is granted additional permissions
@@ -181,11 +181,9 @@
private final TaskActivitiesReport mTmpReport = new TaskActivitiesReport();
@VisibleForTesting
- RecentTasks(ActivityTaskManagerService service, TaskPersister taskPersister,
- UserController userController) {
+ RecentTasks(ActivityTaskManagerService service, TaskPersister taskPersister) {
mService = service;
mSupervisor = mService.mStackSupervisor;
- mUserController = userController;
mTaskPersister = taskPersister;
mGlobalMaxNumTasks = ActivityTaskManager.getMaxRecentTasksStatic();
mHasVisibleRecentTasks = true;
@@ -196,7 +194,6 @@
final Resources res = service.mContext.getResources();
mService = service;
mSupervisor = mService.mStackSupervisor;
- mUserController = service.mAm.mUserController;
mTaskPersister = new TaskPersister(systemDir, stackSupervisor, service, this);
mGlobalMaxNumTasks = ActivityTaskManager.getMaxRecentTasksStatic();
mHasVisibleRecentTasks = res.getBoolean(com.android.internal.R.bool.config_hasRecents);
@@ -712,6 +709,27 @@
return list;
}
+ @VisibleForTesting
+ Set<Integer> getProfileIds(int userId) {
+ Set<Integer> userIds = new ArraySet<>();
+ final List<UserInfo> profiles = mService.getUserManager().getProfiles(userId,
+ false /* enabledOnly */);
+ for (int i = profiles.size() - 1; i >= 0; --i) {
+ userIds.add(profiles.get(i).id);
+ }
+ return userIds;
+ }
+
+ @VisibleForTesting
+ UserInfo getUserInfo(int userId) {
+ return mService.getUserManager().getUserInfo(userId);
+ }
+
+ @VisibleForTesting
+ int[] getCurrentProfileIds() {
+ return mService.mAmInternal.getCurrentProfileIds();
+ }
+
/**
* @return the list of recent tasks for presentation.
*/
@@ -725,7 +743,7 @@
}
loadUserRecentsLocked(userId);
- final Set<Integer> includedUsers = mUserController.getProfileIds(userId);
+ final Set<Integer> includedUsers = getProfileIds(userId);
includedUsers.add(Integer.valueOf(userId));
final ArrayList<ActivityManager.RecentTaskInfo> res = new ArrayList<>();
@@ -1040,10 +1058,10 @@
}
// Remove any tasks that belong to currently quiet profiles
- final int[] profileUserIds = mUserController.getCurrentProfileIds();
+ final int[] profileUserIds = getCurrentProfileIds();
mTmpQuietProfileUserIds.clear();
for (int userId : profileUserIds) {
- final UserInfo userInfo = mUserController.getUserInfo(userId);
+ final UserInfo userInfo = getUserInfo(userId);
if (userInfo != null && userInfo.isManagedProfile() && userInfo.isQuietModeEnabled()) {
mTmpQuietProfileUserIds.put(userId, true);
}
diff --git a/services/core/java/com/android/server/am/UserController.java b/services/core/java/com/android/server/am/UserController.java
index 992179a..fa670a2 100644
--- a/services/core/java/com/android/server/am/UserController.java
+++ b/services/core/java/com/android/server/am/UserController.java
@@ -259,11 +259,14 @@
}
void finishUserSwitch(UserState uss) {
- finishUserBoot(uss);
- startProfiles();
- synchronized (mLock) {
- stopRunningUsersLU(mMaxRunningUsers);
- }
+ // This call holds the AM lock so we post to the handler.
+ mHandler.post(() -> {
+ finishUserBoot(uss);
+ startProfiles();
+ synchronized (mLock) {
+ stopRunningUsersLU(mMaxRunningUsers);
+ }
+ });
}
List<Integer> getRunningUsersLU() {
@@ -1573,7 +1576,9 @@
}
boolean hasStartedUserState(int userId) {
- return mStartedUsers.get(userId) != null;
+ synchronized (mLock) {
+ return mStartedUsers.get(userId) != null;
+ }
}
private void updateStartedUserArrayLU() {
@@ -1749,7 +1754,7 @@
return ums != null ? ums.getUserIds() : new int[] { 0 };
}
- UserInfo getUserInfo(int userId) {
+ private UserInfo getUserInfo(int userId) {
return mInjector.getUserManager().getUserInfo(userId);
}
@@ -1775,7 +1780,7 @@
return mInjector.getUserManager().exists(userId);
}
- void enforceShellRestriction(String restriction, int userHandle) {
+ private void enforceShellRestriction(String restriction, int userHandle) {
if (Binder.getCallingUid() == SHELL_UID) {
if (userHandle < 0 || hasUserRestriction(restriction, userHandle)) {
throw new SecurityException("Shell does not have permission to access user "
@@ -1788,16 +1793,6 @@
return mInjector.getUserManager().hasUserRestriction(restriction, userId);
}
- Set<Integer> getProfileIds(int userId) {
- Set<Integer> userIds = new HashSet<>();
- final List<UserInfo> profiles = mInjector.getUserManager().getProfiles(userId,
- false /* enabledOnly */);
- for (UserInfo user : profiles) {
- userIds.add(user.id);
- }
- return userIds;
- }
-
boolean isSameProfileGroup(int callingUserId, int targetUserId) {
if (callingUserId == targetUserId) {
return true;
diff --git a/services/core/java/com/android/server/am/WindowProcessController.java b/services/core/java/com/android/server/am/WindowProcessController.java
index 64a273e..817905a 100644
--- a/services/core/java/com/android/server/am/WindowProcessController.java
+++ b/services/core/java/com/android/server/am/WindowProcessController.java
@@ -478,6 +478,11 @@
mAtm.mH.post(r);
}
+ /** Returns the total time (in milliseconds) spent executing in both user and system code. */
+ public long getCpuTime() {
+ return (mListener != null) ? mListener.getCpuTime() : 0;
+ }
+
void addRecentTask(TaskRecord task) {
mRecentTasks.add(task);
}
diff --git a/services/core/java/com/android/server/am/WindowProcessListener.java b/services/core/java/com/android/server/am/WindowProcessListener.java
index 92e4461..2de3e37 100644
--- a/services/core/java/com/android/server/am/WindowProcessListener.java
+++ b/services/core/java/com/android/server/am/WindowProcessListener.java
@@ -44,4 +44,7 @@
/** Set process package been removed from device. */
void setRemoved(boolean removed);
+
+ /** Returns the total time (in milliseconds) spent executing in both user and system code. */
+ long getCpuTime();
}
diff --git a/services/core/java/com/android/server/audio/AudioService.java b/services/core/java/com/android/server/audio/AudioService.java
index 6971f71..d1fd0d5 100644
--- a/services/core/java/com/android/server/audio/AudioService.java
+++ b/services/core/java/com/android/server/audio/AudioService.java
@@ -3814,6 +3814,10 @@
int delay = checkSendBecomingNoisyIntent(
AudioSystem.DEVICE_OUT_BLUETOOTH_A2DP, intState,
AudioSystem.DEVICE_NONE);
+ final String addr = btDevice == null ? "null" : btDevice.getAddress();
+ mDeviceLogger.log(new AudioEventLogger.StringEvent(
+ "A2DP service connected: device addr=" + addr
+ + " state=" + state));
queueMsgUnderWakeLock(mAudioHandler,
MSG_SET_A2DP_SINK_CONNECTION_STATE,
state,
@@ -4677,7 +4681,14 @@
public int setBluetoothA2dpDeviceConnectionStateSuppressNoisyIntent(BluetoothDevice device,
int state, int profile, boolean suppressNoisyIntent, int a2dpVolume)
{
+ mDeviceLogger.log(new AudioEventLogger.StringEvent(
+ "setBluetoothA2dpDeviceConnectionStateSuppressNoisyIntent state=" + state
+ // only querying address as this is the only readily available field on the device
+ + " addr=" + device.getAddress()
+ + " prof=" + profile + " supprNoisy=" + suppressNoisyIntent
+ + " vol=" + a2dpVolume));
if (mAudioHandler.hasMessages(MSG_SET_A2DP_SINK_CONNECTION_STATE, device)) {
+ mDeviceLogger.log(new AudioEventLogger.StringEvent("A2DP connection state ignored"));
return 0;
}
return setBluetoothA2dpDeviceConnectionStateInt(
@@ -5630,7 +5641,7 @@
case MSG_SET_WIRED_DEVICE_CONNECTION_STATE:
{ WiredDeviceConnectionState connectState =
(WiredDeviceConnectionState)msg.obj;
- mWiredDevLogger.log(new WiredDevConnectEvent(connectState));
+ mDeviceLogger.log(new WiredDevConnectEvent(connectState));
onSetWiredDeviceConnectionState(connectState.mType, connectState.mState,
connectState.mAddress, connectState.mName, connectState.mCaller);
mAudioEventWakeLock.release();
@@ -6085,10 +6096,14 @@
if (!BluetoothAdapter.checkBluetoothAddress(address)) {
address = "";
}
+ mDeviceLogger.log(new AudioEventLogger.StringEvent(
+ "onBluetoothA2dpDeviceConfigChange addr=" + address));
int device = AudioSystem.DEVICE_OUT_BLUETOOTH_A2DP;
synchronized (mConnectedDevices) {
if (mAudioHandler.hasMessages(MSG_SET_A2DP_SINK_CONNECTION_STATE, btDevice)) {
+ mDeviceLogger.log(new AudioEventLogger.StringEvent(
+ "A2dp config change ignored"));
return;
}
final String key = makeDeviceListKey(device, address);
@@ -7185,19 +7200,20 @@
//==========================================================================================
// AudioService logging and dumpsys
//==========================================================================================
- final int LOG_NB_EVENTS_PHONE_STATE = 20;
- final int LOG_NB_EVENTS_WIRED_DEV_CONNECTION = 30;
- final int LOG_NB_EVENTS_FORCE_USE = 20;
- final int LOG_NB_EVENTS_VOLUME = 40;
- final int LOG_NB_EVENTS_DYN_POLICY = 10;
+ static final int LOG_NB_EVENTS_PHONE_STATE = 20;
+ static final int LOG_NB_EVENTS_DEVICE_CONNECTION = 30;
+ static final int LOG_NB_EVENTS_FORCE_USE = 20;
+ static final int LOG_NB_EVENTS_VOLUME = 40;
+ static final int LOG_NB_EVENTS_DYN_POLICY = 10;
final private AudioEventLogger mModeLogger = new AudioEventLogger(LOG_NB_EVENTS_PHONE_STATE,
"phone state (logged after successfull call to AudioSystem.setPhoneState(int))");
- final private AudioEventLogger mWiredDevLogger = new AudioEventLogger(
- LOG_NB_EVENTS_WIRED_DEV_CONNECTION,
- "wired device connection (logged before onSetWiredDeviceConnectionState() is executed)"
- );
+ // logs for wired + A2DP device connections:
+ // - wired: logged before onSetWiredDeviceConnectionState() is executed
+ // - A2DP: logged at reception of method call
+ final private AudioEventLogger mDeviceLogger = new AudioEventLogger(
+ LOG_NB_EVENTS_DEVICE_CONNECTION, "wired/A2DP device connection");
final private AudioEventLogger mForceUseLogger = new AudioEventLogger(
LOG_NB_EVENTS_FORCE_USE,
@@ -7286,7 +7302,7 @@
pw.println("\nEvent logs:");
mModeLogger.dump(pw);
pw.println("\n");
- mWiredDevLogger.dump(pw);
+ mDeviceLogger.dump(pw);
pw.println("\n");
mForceUseLogger.dump(pw);
pw.println("\n");
diff --git a/services/core/java/com/android/server/hdmi/HdmiCecLocalDevice.java b/services/core/java/com/android/server/hdmi/HdmiCecLocalDevice.java
index 2949b92..c7cdbef 100755
--- a/services/core/java/com/android/server/hdmi/HdmiCecLocalDevice.java
+++ b/services/core/java/com/android/server/hdmi/HdmiCecLocalDevice.java
@@ -264,14 +264,28 @@
return handleRoutingChange(message);
case Constants.MESSAGE_ROUTING_INFORMATION:
return handleRoutingInformation(message);
+ case Constants.MESSAGE_REQUEST_ARC_INITIATION:
+ return handleRequestArcInitiate(message);
+ case Constants.MESSAGE_REQUEST_ARC_TERMINATION:
+ return handleRequestArcTermination(message);
case Constants.MESSAGE_INITIATE_ARC:
return handleInitiateArc(message);
case Constants.MESSAGE_TERMINATE_ARC:
return handleTerminateArc(message);
+ case Constants.MESSAGE_REPORT_ARC_INITIATED:
+ return handleReportArcInitiate(message);
+ case Constants.MESSAGE_REPORT_ARC_TERMINATED:
+ return handleReportArcTermination(message);
+ case Constants.MESSAGE_SYSTEM_AUDIO_MODE_REQUEST:
+ return handleSystemAudioModeRequest(message);
case Constants.MESSAGE_SET_SYSTEM_AUDIO_MODE:
return handleSetSystemAudioMode(message);
case Constants.MESSAGE_SYSTEM_AUDIO_MODE_STATUS:
return handleSystemAudioModeStatus(message);
+ case Constants.MESSAGE_GIVE_SYSTEM_AUDIO_MODE_STATUS:
+ return handleGiveSystemAudioModeStatus(message);
+ case Constants.MESSAGE_GIVE_AUDIO_STATUS:
+ return handleGiveAudioStatus(message);
case Constants.MESSAGE_REPORT_AUDIO_STATUS:
return handleReportAudioStatus(message);
case Constants.MESSAGE_STANDBY:
@@ -419,10 +433,18 @@
return false;
}
+ protected boolean handleGiveSystemAudioModeStatus(HdmiCecMessage message) {
+ return false;
+ }
+
protected boolean handleSetSystemAudioMode(HdmiCecMessage message) {
return false;
}
+ protected boolean handleSystemAudioModeRequest(HdmiCecMessage message) {
+ return false;
+ }
+
protected boolean handleTerminateArc(HdmiCecMessage message) {
return false;
}
@@ -431,10 +453,30 @@
return false;
}
+ protected boolean handleRequestArcInitiate(HdmiCecMessage message) {
+ return false;
+ }
+
+ protected boolean handleRequestArcTermination(HdmiCecMessage message) {
+ return false;
+ }
+
+ protected boolean handleReportArcInitiate(HdmiCecMessage message) {
+ return false;
+ }
+
+ protected boolean handleReportArcTermination(HdmiCecMessage message) {
+ return false;
+ }
+
protected boolean handleReportAudioStatus(HdmiCecMessage message) {
return false;
}
+ protected boolean handleGiveAudioStatus(HdmiCecMessage message) {
+ return false;
+ }
+
@ServiceThreadOnly
protected boolean handleStandby(HdmiCecMessage message) {
assertRunOnServiceThread();
diff --git a/services/core/java/com/android/server/input/InputForwarder.java b/services/core/java/com/android/server/input/InputForwarder.java
index 38a1cd7..00af839 100644
--- a/services/core/java/com/android/server/input/InputForwarder.java
+++ b/services/core/java/com/android/server/input/InputForwarder.java
@@ -19,7 +19,6 @@
import android.app.IInputForwarder;
import android.hardware.input.InputManagerInternal;
import android.view.InputEvent;
-import android.view.MotionEvent;
import com.android.server.LocalServices;
@@ -40,9 +39,7 @@
@Override
public boolean forwardEvent(InputEvent event) {
- if (event instanceof MotionEvent) {
- ((MotionEvent) event).setDisplayId(mDisplayId);
- }
+ event.setDisplayId(mDisplayId);
return mInputManagerInternal.injectInputEvent(event, INJECT_INPUT_EVENT_MODE_ASYNC);
}
}
\ No newline at end of file
diff --git a/services/core/java/com/android/server/media/MediaSessionRecord.java b/services/core/java/com/android/server/media/MediaSessionRecord.java
index 442354b..a49cf44 100644
--- a/services/core/java/com/android/server/media/MediaSessionRecord.java
+++ b/services/core/java/com/android/server/media/MediaSessionRecord.java
@@ -481,7 +481,7 @@
mAudioManagerInternal.adjustStreamVolumeForUid(stream, direction, flags,
packageName, uid);
}
- } catch (IllegalArgumentException e) {
+ } catch (IllegalArgumentException | SecurityException e) {
Log.e(TAG, "Cannot adjust volume: direction=" + direction + ", stream="
+ stream + ", flags=" + flags + ", packageName=" + packageName
+ ", uid=" + uid + ", useSuggested=" + useSuggested
diff --git a/services/core/java/com/android/server/notification/ManagedServices.java b/services/core/java/com/android/server/notification/ManagedServices.java
index 5eb7397..af4f426 100644
--- a/services/core/java/com/android/server/notification/ManagedServices.java
+++ b/services/core/java/com/android/server/notification/ManagedServices.java
@@ -54,6 +54,7 @@
import android.util.ArrayMap;
import android.util.ArraySet;
import android.util.Log;
+import android.util.Pair;
import android.util.Slog;
import android.util.SparseArray;
import android.util.proto.ProtoOutputStream;
@@ -116,9 +117,12 @@
// contains connections to all connected services, including app services
// and system services
private final ArrayList<ManagedServiceInfo> mServices = new ArrayList<>();
- // things that will be put into mServices as soon as they're ready
- private final ArrayList<String> mServicesBinding = new ArrayList<>();
- private final ArraySet<String> mServicesRebinding = new ArraySet<>();
+ /**
+ * The services that have been bound by us. If the service is also connected, it will also
+ * be in {@link #mServices}.
+ */
+ private final ArrayList<Pair<ComponentName, Integer>> mServicesBound = new ArrayList<>();
+ private final ArraySet<Pair<ComponentName, Integer>> mServicesRebinding = new ArraySet<>();
// lists the component names of all enabled (and therefore potentially connected)
// app services for current profiles.
@@ -917,13 +921,13 @@
final boolean isSystem) {
if (DEBUG) Slog.v(TAG, "registerService: " + name + " u=" + userid);
- final String servicesBindingTag = name.toString() + "/" + userid;
- if (mServicesBinding.contains(servicesBindingTag)) {
- Slog.v(TAG, "Not registering " + name + " as bind is already in progress");
+ final Pair<ComponentName, Integer> servicesBindingTag = Pair.create(name, userid);
+ if (mServicesBound.contains(servicesBindingTag)) {
+ Slog.v(TAG, "Not registering " + name + " is already bound");
// stop registering this thing already! we're working on it
return;
}
- mServicesBinding.add(servicesBindingTag);
+ mServicesBound.add(servicesBindingTag);
final int N = mServices.size();
for (int i = N - 1; i >= 0; i--) {
@@ -934,11 +938,7 @@
Slog.v(TAG, " disconnecting old " + getCaption() + ": " + info.service);
removeServiceLocked(i);
if (info.connection != null) {
- try {
- mContext.unbindService(info.connection);
- } catch (IllegalArgumentException e) {
- Slog.e(TAG, "failed to unbind " + name, e);
- }
+ unbindService(info.connection, info.component, info.userid);
}
}
}
@@ -969,11 +969,11 @@
@Override
public void onServiceConnected(ComponentName name, IBinder binder) {
+ Slog.v(TAG, getCaption() + " service connected: " + name);
boolean added = false;
ManagedServiceInfo info = null;
synchronized (mMutex) {
mServicesRebinding.remove(servicesBindingTag);
- mServicesBinding.remove(servicesBindingTag);
try {
mService = asInterface(binder);
info = newServiceInfo(mService, name,
@@ -991,7 +991,6 @@
@Override
public void onServiceDisconnected(ComponentName name) {
- mServicesBinding.remove(servicesBindingTag);
Slog.v(TAG, getCaption() + " connection lost: " + name);
}
@@ -999,12 +998,7 @@
public void onBindingDied(ComponentName name) {
Slog.w(TAG, getCaption() + " binding died: " + name);
synchronized (mMutex) {
- mServicesBinding.remove(servicesBindingTag);
- try {
- mContext.unbindService(this);
- } catch (IllegalArgumentException e) {
- Slog.e(TAG, "failed to unbind " + name, e);
- }
+ unbindService(this, name, userid);
if (!mServicesRebinding.contains(servicesBindingTag)) {
mServicesRebinding.add(servicesBindingTag);
mHandler.postDelayed(new Runnable() {
@@ -1024,12 +1018,12 @@
serviceConnection,
BIND_AUTO_CREATE | BIND_FOREGROUND_SERVICE | BIND_ALLOW_WHITELIST_MANAGEMENT,
new UserHandle(userid))) {
- mServicesBinding.remove(servicesBindingTag);
+ mServicesBound.remove(servicesBindingTag);
Slog.w(TAG, "Unable to bind " + getCaption() + " service: " + intent);
return;
}
} catch (SecurityException ex) {
- mServicesBinding.remove(servicesBindingTag);
+ mServicesBound.remove(servicesBindingTag);
Slog.e(TAG, "Unable to bind " + getCaption() + " service: " + intent, ex);
}
}
@@ -1050,13 +1044,7 @@
if (name.equals(info.component) && info.userid == userid) {
removeServiceLocked(i);
if (info.connection != null) {
- try {
- mContext.unbindService(info.connection);
- } catch (IllegalArgumentException ex) {
- // something happened to the service: we think we have a connection
- // but it's bogus.
- Slog.e(TAG, getCaption() + " " + name + " could not be unbound: " + ex);
- }
+ unbindService(info.connection, info.component, info.userid);
}
}
}
@@ -1121,7 +1109,18 @@
private void unregisterServiceImpl(IInterface service, int userid) {
ManagedServiceInfo info = removeServiceImpl(service, userid);
if (info != null && info.connection != null && !info.isGuest(this)) {
- mContext.unbindService(info.connection);
+ unbindService(info.connection, info.component, info.userid);
+ }
+ }
+
+ private void unbindService(ServiceConnection connection, ComponentName component, int userId) {
+ try {
+ mContext.unbindService(connection);
+ } catch (IllegalArgumentException e) {
+ Slog.e(TAG, getCaption() + " " + component + " could not be unbound", e);
+ }
+ synchronized (mMutex) {
+ mServicesBound.remove(Pair.create(component, userId));
}
}
diff --git a/services/core/java/com/android/server/notification/NotificationManagerService.java b/services/core/java/com/android/server/notification/NotificationManagerService.java
index 88edc95..71c7c88 100644
--- a/services/core/java/com/android/server/notification/NotificationManagerService.java
+++ b/services/core/java/com/android/server/notification/NotificationManagerService.java
@@ -329,6 +329,8 @@
private long[] mFallbackVibrationPattern;
private boolean mUseAttentionLight;
+ boolean mHasLight = true;
+ boolean mLightEnabled;
boolean mSystemReady;
private boolean mDisableNotificationEffects;
@@ -343,9 +345,9 @@
private int mInterruptionFilter = NotificationListenerService.INTERRUPTION_FILTER_UNKNOWN;
// for enabling and disabling notification pulse behavior
- private boolean mScreenOn = true;
+ boolean mScreenOn = true;
protected boolean mInCall = false;
- private boolean mNotificationPulseEnabled;
+ boolean mNotificationPulseEnabled;
private Uri mInCallNotificationUri;
private AudioAttributes mInCallNotificationAudioAttributes;
@@ -1196,7 +1198,8 @@
ContentResolver resolver = getContext().getContentResolver();
if (uri == null || NOTIFICATION_LIGHT_PULSE_URI.equals(uri)) {
boolean pulseEnabled = Settings.System.getIntForUser(resolver,
- Settings.System.NOTIFICATION_LIGHT_PULSE, 0, UserHandle.USER_CURRENT) != 0;
+ Settings.System.NOTIFICATION_LIGHT_PULSE, 0, UserHandle.USER_CURRENT)
+ != 0;
if (mNotificationPulseEnabled != pulseEnabled) {
mNotificationPulseEnabled = pulseEnabled;
updateNotificationPulse();
@@ -1458,6 +1461,8 @@
mInCallNotificationVolume = resources.getFloat(R.dimen.config_inCallNotificationVolume);
mUseAttentionLight = resources.getBoolean(R.bool.config_useAttentionLight);
+ mHasLight =
+ resources.getBoolean(com.android.internal.R.bool.config_intrusiveNotificationLed);
// Don't start allowing notifications until the setup wizard has run once.
// After that, including subsequent boots, init with notifications turned on.
@@ -3843,6 +3848,7 @@
pw.println(" ");
}
pw.println(" mUseAttentionLight=" + mUseAttentionLight);
+ pw.println(" mHasLight=" + mHasLight);
pw.println(" mNotificationPulseEnabled=" + mNotificationPulseEnabled);
pw.println(" mSoundNotificationKey=" + mSoundNotificationKey);
pw.println(" mVibrateNotificationKey=" + mVibrateNotificationKey);
@@ -4840,8 +4846,7 @@
// light
// release the light
boolean wasShowLights = mLights.remove(key);
- if (record.getLight() != null && aboveThreshold
- && ((record.getSuppressedVisualEffects() & SUPPRESSED_EFFECT_LIGHTS) == 0)) {
+ if (canShowLightsLocked(record, aboveThreshold)) {
mLights.add(key);
updateLightsLocked();
if (mUseAttentionLight) {
@@ -4852,7 +4857,19 @@
updateLightsLocked();
}
if (buzz || beep || blink) {
- record.setInterruptive(true);
+ // Ignore summary updates because we don't display most of the information.
+ if (record.sbn.isGroup() && record.sbn.getNotification().isGroupSummary()) {
+ if (DEBUG_INTERRUPTIVENESS) {
+ Log.v(TAG, "INTERRUPTIVENESS: "
+ + record.getKey() + " is not interruptive: summary");
+ }
+ } else {
+ if (DEBUG_INTERRUPTIVENESS) {
+ Log.v(TAG, "INTERRUPTIVENESS: "
+ + record.getKey() + " is interruptive: alerted");
+ }
+ record.setInterruptive(true);
+ }
MetricsLogger.action(record.getLogMaker()
.setCategory(MetricsEvent.NOTIFICATION_ALERT)
.setType(MetricsEvent.TYPE_OPEN)
@@ -4862,11 +4879,49 @@
}
@GuardedBy("mNotificationLock")
+ boolean canShowLightsLocked(final NotificationRecord record, boolean aboveThreshold) {
+ // device lacks light
+ if (!mHasLight) {
+ return false;
+ }
+ // user turned lights off globally
+ if (!mNotificationPulseEnabled) {
+ return false;
+ }
+ // the notification/channel has no light
+ if (record.getLight() == null) {
+ return false;
+ }
+ // unimportant notification
+ if (!aboveThreshold) {
+ return false;
+ }
+ // suppressed due to DND
+ if ((record.getSuppressedVisualEffects() & SUPPRESSED_EFFECT_LIGHTS) != 0) {
+ return false;
+ }
+ // Suppressed because it's a silent update
+ final Notification notification = record.getNotification();
+ if (record.isUpdate && (notification.flags & Notification.FLAG_ONLY_ALERT_ONCE) != 0) {
+ return false;
+ }
+ // Suppressed because another notification in its group handles alerting
+ if (record.sbn.isGroup() && record.getNotification().suppressAlertingDueToGrouping()) {
+ return false;
+ }
+ // not if in call or the screen's on
+ if (mInCall || mScreenOn) {
+ return false;
+ }
+
+ return true;
+ }
+
+ @GuardedBy("mNotificationLock")
boolean shouldMuteNotificationLocked(final NotificationRecord record) {
// Suppressed because it's a silent update
final Notification notification = record.getNotification();
- if(record.isUpdate
- && (notification.flags & Notification.FLAG_ONLY_ALERT_ONCE) != 0) {
+ if (record.isUpdate && (notification.flags & Notification.FLAG_ONLY_ALERT_ONCE) != 0) {
return true;
}
diff --git a/services/core/java/com/android/server/notification/RankingHelper.java b/services/core/java/com/android/server/notification/RankingHelper.java
index 61b5415..63d0b0c 100644
--- a/services/core/java/com/android/server/notification/RankingHelper.java
+++ b/services/core/java/com/android/server/notification/RankingHelper.java
@@ -1173,9 +1173,7 @@
pw.println();
for (NotificationChannel channel : r.channels.values()) {
pw.print(prefix);
- pw.print(" ");
- pw.print(" ");
- pw.println(channel);
+ channel.dump(pw, " ", filter.redact);
}
for (NotificationChannelGroup group : r.groups.values()) {
pw.print(prefix);
diff --git a/services/core/java/com/android/server/notification/ZenModeHelper.java b/services/core/java/com/android/server/notification/ZenModeHelper.java
index 24fd331..1954ed4 100644
--- a/services/core/java/com/android/server/notification/ZenModeHelper.java
+++ b/services/core/java/com/android/server/notification/ZenModeHelper.java
@@ -1190,6 +1190,11 @@
&& Settings.Global.getInt(mContext.getContentResolver(),
Settings.Global.SHOW_ZEN_UPGRADE_NOTIFICATION, 0) != 0;
+ if (isWatch) {
+ Settings.Global.putInt(mContext.getContentResolver(),
+ Global.SHOW_ZEN_UPGRADE_NOTIFICATION, 0);
+ }
+
if (showNotification) {
mNotificationManager.notify(TAG, SystemMessage.NOTE_ZEN_UPGRADE,
createZenUpgradeNotification());
diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java
index c536e4d..734a872 100644
--- a/services/core/java/com/android/server/pm/PackageManagerService.java
+++ b/services/core/java/com/android/server/pm/PackageManagerService.java
@@ -169,6 +169,7 @@
import android.content.pm.PackageManager;
import android.content.pm.PackageManager.LegacyPackageDeleteObserver;
import android.content.pm.PackageManagerInternal;
+import android.content.pm.PackageManagerInternal.CheckPermissionDelegate;
import android.content.pm.PackageManagerInternal.PackageListObserver;
import android.content.pm.PackageParser;
import android.content.pm.PackageParser.ActivityIntentInfo;
@@ -289,6 +290,8 @@
import com.android.internal.util.IndentingPrintWriter;
import com.android.internal.util.Preconditions;
import com.android.internal.util.XmlUtils;
+import com.android.internal.util.function.QuadFunction;
+import com.android.internal.util.function.TriFunction;
import com.android.server.AttributeCache;
import com.android.server.DeviceIdleController;
import com.android.server.EventLogTags;
@@ -363,6 +366,7 @@
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.atomic.AtomicInteger;
+import java.util.function.BiFunction;
import java.util.function.Predicate;
import dalvik.system.CloseGuard;
@@ -1031,6 +1035,9 @@
void receiveVerificationResponse(int verificationId);
}
+ @GuardedBy("mPackages")
+ private CheckPermissionDelegate mCheckPermissionDelegate;
+
private class IntentVerifierProxy implements IntentFilterVerifier<ActivityIntentInfo> {
private Context mContext;
private ComponentName mIntentFilterVerifierComponent;
@@ -5260,11 +5267,35 @@
@Override
public int checkPermission(String permName, String pkgName, int userId) {
+ final CheckPermissionDelegate checkPermissionDelegate;
+ synchronized (mPackages) {
+ if (mCheckPermissionDelegate == null) {
+ return checkPermissionImpl(permName, pkgName, userId);
+ }
+ checkPermissionDelegate = mCheckPermissionDelegate;
+ }
+ return checkPermissionDelegate.checkPermission(permName, pkgName, userId,
+ PackageManagerService.this::checkPermissionImpl);
+ }
+
+ private int checkPermissionImpl(String permName, String pkgName, int userId) {
return mPermissionManager.checkPermission(permName, pkgName, getCallingUid(), userId);
}
@Override
public int checkUidPermission(String permName, int uid) {
+ final CheckPermissionDelegate checkPermissionDelegate;
+ synchronized (mPackages) {
+ if (mCheckPermissionDelegate == null) {
+ return checkUidPermissionImpl(permName, uid);
+ }
+ checkPermissionDelegate = mCheckPermissionDelegate;
+ }
+ return checkPermissionDelegate.checkUidPermission(permName, uid,
+ PackageManagerService.this::checkUidPermissionImpl);
+ }
+
+ private int checkUidPermissionImpl(String permName, int uid) {
synchronized (mPackages) {
final String[] packageNames = getPackagesForUid(uid);
final PackageParser.Package pkg = (packageNames != null && packageNames.length > 0)
@@ -9150,6 +9181,16 @@
}
@GuardedBy("mPackages")
+ public CheckPermissionDelegate getCheckPermissionDelegateLocked() {
+ return mCheckPermissionDelegate;
+ }
+
+ @GuardedBy("mPackages")
+ public void setCheckPermissionDelegateLocked(CheckPermissionDelegate delegate) {
+ mCheckPermissionDelegate = delegate;
+ }
+
+ @GuardedBy("mPackages")
private void notifyPackageUseLocked(String packageName, int reason) {
final PackageParser.Package p = mPackages.get(packageName);
if (p == null) {
@@ -24150,6 +24191,20 @@
PackageManagerService.this.notifyPackageUseLocked(packageName, reason);
}
}
+
+ @Override
+ public CheckPermissionDelegate getCheckPermissionDelegate() {
+ synchronized (mPackages) {
+ return PackageManagerService.this.getCheckPermissionDelegateLocked();
+ }
+ }
+
+ @Override
+ public void setCheckPermissionDelegate(CheckPermissionDelegate delegate) {
+ synchronized (mPackages) {
+ PackageManagerService.this.setCheckPermissionDelegateLocked(delegate);
+ }
+ }
}
@Override
diff --git a/services/core/java/com/android/server/pm/permission/PermissionManagerInternal.java b/services/core/java/com/android/server/pm/permission/PermissionManagerInternal.java
index a042fed..ec15c16 100644
--- a/services/core/java/com/android/server/pm/permission/PermissionManagerInternal.java
+++ b/services/core/java/com/android/server/pm/permission/PermissionManagerInternal.java
@@ -21,19 +21,11 @@
import android.content.pm.PackageParser;
import android.content.pm.PermissionGroupInfo;
import android.content.pm.PermissionInfo;
-import android.content.pm.PackageManager.NameNotFoundException;
import android.content.pm.PackageManager.PermissionInfoFlags;
-import android.content.pm.PackageParser.Permission;
-
-import com.android.server.pm.SharedUserSetting;
-import com.android.server.pm.permission.PermissionManagerInternal.PermissionCallback;
import java.util.ArrayList;
import java.util.Collection;
-import java.util.Iterator;
import java.util.List;
-import java.util.Map;
-import java.util.Set;
/**
* Internal interfaces to be used by other components within the system server.
diff --git a/services/core/java/com/android/server/policy/BarController.java b/services/core/java/com/android/server/policy/BarController.java
index eca6f9f..14c985c 100644
--- a/services/core/java/com/android/server/policy/BarController.java
+++ b/services/core/java/com/android/server/policy/BarController.java
@@ -196,7 +196,7 @@
}
protected boolean skipAnimation() {
- return false;
+ return !mWin.isDrawnLw();
}
private int computeStateLw(boolean wasVis, boolean wasAnim, WindowState win, boolean change) {
diff --git a/services/core/java/com/android/server/policy/PhoneWindowManager.java b/services/core/java/com/android/server/policy/PhoneWindowManager.java
index b99f8d6..5bc35e7 100644
--- a/services/core/java/com/android/server/policy/PhoneWindowManager.java
+++ b/services/core/java/com/android/server/policy/PhoneWindowManager.java
@@ -76,6 +76,7 @@
import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_IS_SCREEN_DECOR;
import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_KEYGUARD;
import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_SHOW_FOR_ALL_USERS;
+import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_STATUS_BAR_EXPANDED;
import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_SYSTEM_ERROR;
import static android.view.WindowManager.LayoutParams.ROTATION_ANIMATION_CROSSFADE;
import static android.view.WindowManager.LayoutParams.ROTATION_ANIMATION_JUMPCUT;
@@ -4686,8 +4687,7 @@
navTranslucent &= areTranslucentBarsAllowed();
}
boolean statusBarExpandedNotKeyguard = !isKeyguardShowing && mStatusBar != null
- && mStatusBar.getAttrs().height == MATCH_PARENT
- && mStatusBar.getAttrs().width == MATCH_PARENT;
+ && (mStatusBar.getAttrs().privateFlags & PRIVATE_FLAG_STATUS_BAR_EXPANDED) != 0;
// When the navigation bar isn't visible, we put up a fake input window to catch all
// touch events. This way we can detect when the user presses anywhere to bring back the
@@ -5690,7 +5690,7 @@
}
// Take note if a window wants to acquire a sleep token.
- if (win.isVisibleLw() && (attrs.privateFlags & PRIVATE_FLAG_ACQUIRES_SLEEP_TOKEN) != 0
+ if ((attrs.privateFlags & PRIVATE_FLAG_ACQUIRES_SLEEP_TOKEN) != 0
&& win.canAcquireSleepToken()) {
mWindowSleepTokenNeeded = true;
}
@@ -5746,9 +5746,8 @@
mStatusBarController.setShowTransparent(true /* transparent */);
}
- WindowManager.LayoutParams statusBarAttrs = mStatusBar.getAttrs();
- boolean statusBarExpanded = statusBarAttrs.height == MATCH_PARENT
- && statusBarAttrs.width == MATCH_PARENT;
+ boolean statusBarExpanded =
+ (mStatusBar.getAttrs().privateFlags & PRIVATE_FLAG_STATUS_BAR_EXPANDED) != 0;
boolean topAppHidesStatusBar = topAppHidesStatusBar();
if (mForceStatusBar || mForceStatusBarFromKeyguard || mForceStatusBarTransparent
|| statusBarExpanded) {
diff --git a/services/core/java/com/android/server/slice/PinnedSliceState.java b/services/core/java/com/android/server/slice/PinnedSliceState.java
index 4e7fb96..e139ab8 100644
--- a/services/core/java/com/android/server/slice/PinnedSliceState.java
+++ b/services/core/java/com/android/server/slice/PinnedSliceState.java
@@ -154,8 +154,8 @@
}
ContentProviderClient getClient() {
- ContentProviderClient client =
- mService.getContext().getContentResolver().acquireContentProviderClient(mUri);
+ ContentProviderClient client = mService.getContext().getContentResolver()
+ .acquireUnstableContentProviderClient(mUri);
if (client == null) return null;
client.setDetectNotResponding(SLICE_TIMEOUT);
return client;
diff --git a/services/core/java/com/android/server/slice/SliceManagerService.java b/services/core/java/com/android/server/slice/SliceManagerService.java
index ea34346..ded2c15 100644
--- a/services/core/java/com/android/server/slice/SliceManagerService.java
+++ b/services/core/java/com/android/server/slice/SliceManagerService.java
@@ -42,6 +42,7 @@
import android.content.IntentFilter;
import android.content.pm.PackageManager;
import android.content.pm.PackageManagerInternal;
+import android.content.pm.ProviderInfo;
import android.content.pm.ResolveInfo;
import android.net.Uri;
import android.os.Binder;
@@ -396,30 +397,11 @@
private String getProviderPkg(Uri uri, int user) {
long ident = Binder.clearCallingIdentity();
try {
- IBinder token = new Binder();
- IActivityManager activityManager = ActivityManager.getService();
- ContentProviderHolder holder = null;
String providerName = getUriWithoutUserId(uri).getAuthority();
- try {
- try {
- holder = activityManager.getContentProviderExternal(
- providerName, getUserIdFromUri(uri, user), token);
- if (holder != null && holder.info != null) {
- return holder.info.packageName;
- } else {
- return null;
- }
- } finally {
- if (holder != null && holder.provider != null) {
- activityManager.removeContentProviderExternal(providerName, token);
- }
- }
- } catch (RemoteException e) {
- // Can't happen.
- throw e.rethrowAsRuntimeException();
- }
+ ProviderInfo provider = mContext.getPackageManager().resolveContentProviderAsUser(
+ providerName, 0, getUserIdFromUri(uri, user));
+ return provider.packageName;
} finally {
- // I know, the double finally seems ugly, but seems safest for the identity.
Binder.restoreCallingIdentity(ident);
}
}
diff --git a/services/core/java/com/android/server/wallpaper/WallpaperManagerService.java b/services/core/java/com/android/server/wallpaper/WallpaperManagerService.java
index 547ab0e..9d68c63 100644
--- a/services/core/java/com/android/server/wallpaper/WallpaperManagerService.java
+++ b/services/core/java/com/android/server/wallpaper/WallpaperManagerService.java
@@ -51,7 +51,6 @@
import android.content.pm.ServiceInfo;
import android.content.pm.UserInfo;
import android.content.res.Resources;
-import android.database.ContentObserver;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.BitmapRegionDecoder;
@@ -76,7 +75,6 @@
import android.os.SystemClock;
import android.os.UserHandle;
import android.os.UserManager;
-import android.provider.Settings;
import android.service.wallpaper.IWallpaperConnection;
import android.service.wallpaper.IWallpaperEngine;
import android.service.wallpaper.IWallpaperService;
@@ -338,102 +336,6 @@
}
}
- /**
- * Observes changes of theme settings. It will check whether to call
- * notifyWallpaperColorsChanged by the current theme and updated theme.
- * The light theme and dark theme are controlled by the hint values in Wallpaper colors,
- * threrfore, if light theme mode is chosen, HINT_SUPPORTS_DARK_THEME in hint will be
- * removed and then notify listeners.
- */
- private class ThemeSettingsObserver extends ContentObserver {
-
- public ThemeSettingsObserver(Handler handler) {
- super(handler);
- }
-
- public void startObserving(Context context) {
- context.getContentResolver().registerContentObserver(
- Settings.Secure.getUriFor(Settings.Secure.THEME_MODE),
- false,
- this);
- }
-
- public void stopObserving(Context context) {
- context.getContentResolver().unregisterContentObserver(this);
- }
-
- @Override
- public void onChange(boolean selfChange) {
- onThemeSettingsChanged();
- }
- }
-
- /**
- * Check whether to call notifyWallpaperColorsChanged. Assumed that the theme mode
- * was wallpaper theme mode and dark wallpaper was set, therefoe, the theme was dark.
- * Then theme mode changing to dark theme mode, however, theme should not update since
- * theme was dark already.
- */
- private boolean needUpdateLocked(WallpaperColors colors, int themeMode) {
- if (colors == null) {
- return false;
- }
-
- if (themeMode == mThemeMode) {
- return false;
- }
-
- boolean result = true;
- boolean supportDarkTheme =
- (colors.getColorHints() & WallpaperColors.HINT_SUPPORTS_DARK_THEME) != 0;
- switch (themeMode) {
- case Settings.Secure.THEME_MODE_WALLPAPER:
- if (mThemeMode == Settings.Secure.THEME_MODE_LIGHT) {
- result = supportDarkTheme;
- } else {
- result = !supportDarkTheme;
- }
- break;
- case Settings.Secure.THEME_MODE_LIGHT:
- if (mThemeMode == Settings.Secure.THEME_MODE_WALLPAPER) {
- result = supportDarkTheme;
- }
- break;
- case Settings.Secure.THEME_MODE_DARK:
- if (mThemeMode == Settings.Secure.THEME_MODE_WALLPAPER) {
- result = !supportDarkTheme;
- }
- break;
- default:
- Slog.w(TAG, "unkonwn theme mode " + themeMode);
- return false;
- }
- mThemeMode = themeMode;
- return result;
- }
-
- void onThemeSettingsChanged() {
- WallpaperData wallpaper;
- synchronized (mLock) {
- wallpaper = mWallpaperMap.get(mCurrentUserId);
- int updatedThemeMode = Settings.Secure.getInt(
- mContext.getContentResolver(), Settings.Secure.THEME_MODE,
- Settings.Secure.THEME_MODE_WALLPAPER);
-
- if (DEBUG) {
- Slog.v(TAG, "onThemeSettingsChanged, mode = " + updatedThemeMode);
- }
-
- if (!needUpdateLocked(wallpaper.primaryColors, updatedThemeMode)) {
- return;
- }
- }
-
- if (wallpaper != null) {
- notifyWallpaperColorsChanged(wallpaper, FLAG_SYSTEM);
- }
- }
-
void notifyLockWallpaperChanged() {
final IWallpaperManagerCallback cb = mKeyguardListener;
if (cb != null) {
@@ -511,7 +413,6 @@
}
userAllColorListeners.finishBroadcast();
}
- wallpaperColors = getThemeColorsLocked(wallpaperColors);
}
final int count = colorListeners.size();
@@ -580,40 +481,6 @@
}
/**
- * We can easily change theme by modified colors hint. This function will check
- * current theme mode and return the WallpaperColors fit current theme mode.
- * If color need modified, it will return a copied WallpaperColors which
- * its ColorsHint is modified to fit current theme mode.
- *
- * @param colors a wallpaper primary colors representation
- */
- private WallpaperColors getThemeColorsLocked(WallpaperColors colors) {
- if (colors == null) {
- Slog.w(TAG, "Cannot get theme colors because WallpaperColors is null.");
- return null;
- }
-
- int colorHints = colors.getColorHints();
- boolean supportDarkTheme = (colorHints & WallpaperColors.HINT_SUPPORTS_DARK_THEME) != 0;
- if (mThemeMode == Settings.Secure.THEME_MODE_WALLPAPER ||
- (mThemeMode == Settings.Secure.THEME_MODE_LIGHT && !supportDarkTheme) ||
- (mThemeMode == Settings.Secure.THEME_MODE_DARK && supportDarkTheme)) {
- return colors;
- }
-
- WallpaperColors themeColors = new WallpaperColors(colors.getPrimaryColor(),
- colors.getSecondaryColor(), colors.getTertiaryColor());
-
- if (mThemeMode == Settings.Secure.THEME_MODE_LIGHT) {
- colorHints &= ~WallpaperColors.HINT_SUPPORTS_DARK_THEME;
- } else if (mThemeMode == Settings.Secure.THEME_MODE_DARK) {
- colorHints |= WallpaperColors.HINT_SUPPORTS_DARK_THEME;
- }
- themeColors.setColorHints(colorHints);
- return themeColors;
- }
-
- /**
* Once a new wallpaper has been written via setWallpaper(...), it needs to be cropped
* for display.
*/
@@ -809,7 +676,6 @@
final SparseArray<Boolean> mUserRestorecon = new SparseArray<Boolean>();
int mCurrentUserId = UserHandle.USER_NULL;
boolean mInAmbientMode;
- int mThemeMode;
static class WallpaperData {
@@ -868,7 +734,6 @@
long lastDiedTime;
boolean wallpaperUpdating;
WallpaperObserver wallpaperObserver;
- ThemeSettingsObserver themeSettingsObserver;
/**
* List of callbacks registered they should each be notified when the wallpaper is changed.
@@ -1414,10 +1279,6 @@
wallpaper.wallpaperObserver.stopWatching();
wallpaper.wallpaperObserver = null;
}
- if (wallpaper.themeSettingsObserver != null) {
- wallpaper.themeSettingsObserver.stopObserving(mContext);
- wallpaper.themeSettingsObserver = null;
- }
}
}
@@ -1501,13 +1362,6 @@
systemWallpaper.wallpaperObserver = new WallpaperObserver(systemWallpaper);
systemWallpaper.wallpaperObserver.startWatching();
}
- if (systemWallpaper.themeSettingsObserver == null) {
- systemWallpaper.themeSettingsObserver = new ThemeSettingsObserver(null);
- systemWallpaper.themeSettingsObserver.startObserving(mContext);
- }
- mThemeMode = Settings.Secure.getInt(
- mContext.getContentResolver(), Settings.Secure.THEME_MODE,
- Settings.Secure.THEME_MODE_WALLPAPER);
switchWallpaper(systemWallpaper, reply);
}
@@ -1981,7 +1835,7 @@
}
synchronized (mLock) {
- return getThemeColorsLocked(wallpaperData.primaryColors);
+ return wallpaperData.primaryColors;
}
}
diff --git a/services/core/java/com/android/server/wm/BoundsAnimationController.java b/services/core/java/com/android/server/wm/BoundsAnimationController.java
index 0a49c13..bc8c17d 100644
--- a/services/core/java/com/android/server/wm/BoundsAnimationController.java
+++ b/services/core/java/com/android/server/wm/BoundsAnimationController.java
@@ -196,12 +196,6 @@
@Override
public void onAnimationStart(Animator animation) {
- if (!mTarget.isAttached()) {
- // No point of trying to animate something that isn't attached to the hierarchy
- // anymore.
- cancel();
- }
-
if (DEBUG) Slog.d(TAG, "onAnimationStart: mTarget=" + mTarget
+ " mPrevSchedulePipModeChangedState=" + mPrevSchedulePipModeChangedState
+ " mSchedulePipModeChangedState=" + mSchedulePipModeChangedState);
@@ -216,13 +210,15 @@
// Ensure that we have prepared the target for animation before we trigger any size
// changes, so it can swap surfaces in to appropriate modes, or do as it wishes
// otherwise.
+ boolean continueAnimation;
if (mPrevSchedulePipModeChangedState == NO_PIP_MODE_CHANGED_CALLBACKS) {
- mTarget.onAnimationStart(mSchedulePipModeChangedState ==
+ continueAnimation = mTarget.onAnimationStart(mSchedulePipModeChangedState ==
SCHEDULE_PIP_MODE_CHANGED_ON_START, false /* forceUpdate */);
// When starting an animation from fullscreen, pause here and wait for the
// windows-drawn signal before we start the rest of the transition down into PiP.
- if (mMoveFromFullscreen && mTarget.shouldDeferStartOnMoveToFullscreen()) {
+ if (continueAnimation && mMoveFromFullscreen
+ && mTarget.shouldDeferStartOnMoveToFullscreen()) {
pause();
}
} else if (mPrevSchedulePipModeChangedState == SCHEDULE_PIP_MODE_CHANGED_ON_END &&
@@ -231,8 +227,19 @@
// client will not currently receive any picture-in-picture mode change callbacks.
// However, we still need to report to them that they are leaving PiP, so this will
// force an update via a mode changed callback.
- mTarget.onAnimationStart(true /* schedulePipModeChangedCallback */,
- true /* forceUpdate */);
+ continueAnimation = mTarget.onAnimationStart(
+ true /* schedulePipModeChangedCallback */, true /* forceUpdate */);
+ } else {
+ // The animation is already running, but we should check that the TaskStack is still
+ // valid before continuing with the animation
+ continueAnimation = mTarget.isAttached();
+ }
+
+ if (!continueAnimation) {
+ // No point of trying to animate something that isn't attached to the hierarchy
+ // anymore.
+ cancel();
+ return;
}
// Immediately update the task bounds if they have to become larger, but preserve
@@ -354,6 +361,9 @@
if (DEBUG) Slog.d(TAG, "cancel: mTarget=" + mTarget);
mSkipAnimationEnd = true;
super.cancel();
+
+ // Reset the thread priority of the animation thread if the bounds animation is canceled
+ updateBooster();
}
/**
diff --git a/services/core/java/com/android/server/wm/BoundsAnimationTarget.java b/services/core/java/com/android/server/wm/BoundsAnimationTarget.java
index d66b42f..5cb80de 100644
--- a/services/core/java/com/android/server/wm/BoundsAnimationTarget.java
+++ b/services/core/java/com/android/server/wm/BoundsAnimationTarget.java
@@ -30,8 +30,9 @@
*
* @param schedulePipModeChangedCallback whether or not to schedule the PiP mode changed
* callbacks
+ * @return whether to continue the animation
*/
- void onAnimationStart(boolean schedulePipModeChangedCallback, boolean forceUpdate);
+ boolean onAnimationStart(boolean schedulePipModeChangedCallback, boolean forceUpdate);
/**
* @return Whether the animation should be paused waiting for the windows to draw before
diff --git a/services/core/java/com/android/server/wm/TaskStack.java b/services/core/java/com/android/server/wm/TaskStack.java
index e01cebd..9075b6c 100644
--- a/services/core/java/com/android/server/wm/TaskStack.java
+++ b/services/core/java/com/android/server/wm/TaskStack.java
@@ -1645,9 +1645,14 @@
}
@Override // AnimatesBounds
- public void onAnimationStart(boolean schedulePipModeChangedCallback, boolean forceUpdate) {
+ public boolean onAnimationStart(boolean schedulePipModeChangedCallback, boolean forceUpdate) {
// Hold the lock since this is called from the BoundsAnimator running on the UiThread
synchronized (mService.mWindowMap) {
+ if (!isAttached()) {
+ // Don't run the animation if the stack is already detached
+ return false;
+ }
+
mBoundsAnimatingRequested = false;
mBoundsAnimating = true;
mCancelCurrentBoundsAnimation = false;
@@ -1677,6 +1682,7 @@
controller.updatePictureInPictureModeForPinnedStackAnimation(null, forceUpdate);
}
}
+ return true;
}
@Override // AnimatesBounds
@@ -1720,41 +1726,47 @@
@Override
public boolean isAttached() {
- return mDisplayContent != null;
+ synchronized (mService.mWindowMap) {
+ return mDisplayContent != null;
+ }
}
/**
* Called immediately prior to resizing the tasks at the end of the pinned stack animation.
*/
public void onPipAnimationEndResize() {
- mBoundsAnimating = false;
- for (int i = 0; i < mChildren.size(); i++) {
- final Task t = mChildren.get(i);
- t.clearPreserveNonFloatingState();
+ synchronized (mService.mWindowMap) {
+ mBoundsAnimating = false;
+ for (int i = 0; i < mChildren.size(); i++) {
+ final Task t = mChildren.get(i);
+ t.clearPreserveNonFloatingState();
+ }
+ mService.requestTraversal();
}
- mService.requestTraversal();
}
@Override
public boolean shouldDeferStartOnMoveToFullscreen() {
- // Workaround for the recents animation -- normally we need to wait for the new activity to
- // show before starting the PiP animation, but because we start and show the home activity
- // early for the recents animation prior to the PiP animation starting, there is no
- // subsequent all-drawn signal. In this case, we can skip the pause when the home stack is
- // already visible and drawn.
- final TaskStack homeStack = mDisplayContent.getHomeStack();
- if (homeStack == null) {
- return true;
+ synchronized (mService.mWindowMap) {
+ // Workaround for the recents animation -- normally we need to wait for the new activity
+ // to show before starting the PiP animation, but because we start and show the home
+ // activity early for the recents animation prior to the PiP animation starting, there
+ // is no subsequent all-drawn signal. In this case, we can skip the pause when the home
+ // stack is already visible and drawn.
+ final TaskStack homeStack = mDisplayContent.getHomeStack();
+ if (homeStack == null) {
+ return true;
+ }
+ final Task homeTask = homeStack.getTopChild();
+ if (homeTask == null) {
+ return true;
+ }
+ final AppWindowToken homeApp = homeTask.getTopVisibleAppToken();
+ if (!homeTask.isVisible() || homeApp == null) {
+ return true;
+ }
+ return !homeApp.allDrawn;
}
- final Task homeTask = homeStack.getTopChild();
- if (homeTask == null) {
- return true;
- }
- final AppWindowToken homeApp = homeTask.getTopVisibleAppToken();
- if (!homeTask.isVisible() || homeApp == null) {
- return true;
- }
- return !homeApp.allDrawn;
}
/**
diff --git a/services/core/java/com/android/server/wm/WindowManagerService.java b/services/core/java/com/android/server/wm/WindowManagerService.java
index 399078a..54703b3 100644
--- a/services/core/java/com/android/server/wm/WindowManagerService.java
+++ b/services/core/java/com/android/server/wm/WindowManagerService.java
@@ -2180,8 +2180,6 @@
result |= mInTouchMode ? WindowManagerGlobal.RELAYOUT_RES_IN_TOUCH_MODE : 0;
- mInputMonitor.updateInputWindowsLw(true /*force*/);
-
if (DEBUG_LAYOUT) {
Slog.v(TAG_WM, "Relayout complete " + win + ": outFrame=" + outFrame.toShortString());
}
@@ -5666,9 +5664,9 @@
boolean imWindowChanged = false;
if (mInputMethodWindow != null) {
final WindowState prevTarget = mInputMethodTarget;
+
final WindowState newTarget =
displayContent.computeImeTarget(true /* updateImeTarget*/);
-
imWindowChanged = prevTarget != newTarget;
if (mode != UPDATE_FOCUS_WILL_ASSIGN_LAYERS
diff --git a/services/core/jni/Android.bp b/services/core/jni/Android.bp
index 89efe12..9e1191d 100644
--- a/services/core/jni/Android.bp
+++ b/services/core/jni/Android.bp
@@ -2,6 +2,8 @@
name: "libservices.core",
defaults: ["libservices.core-libs"],
+ cpp_std: "c++17",
+
cflags: [
"-Wall",
"-Werror",
diff --git a/services/java/com/android/server/SystemServer.java b/services/java/com/android/server/SystemServer.java
index 1f1b3f8..252a1fd 100644
--- a/services/java/com/android/server/SystemServer.java
+++ b/services/java/com/android/server/SystemServer.java
@@ -722,7 +722,7 @@
// Tracks cpu time spent in binder calls
traceBeginAndSlog("StartBinderCallsStatsService");
- BinderCallsStatsService.start();
+ mSystemServiceManager.startService(BinderCallsStatsService.LifeCycle.class);
traceEnd();
}
diff --git a/services/net/java/android/net/netlink/NetlinkSocket.java b/services/net/java/android/net/netlink/NetlinkSocket.java
index 5af3c29..cfcba3a 100644
--- a/services/net/java/android/net/netlink/NetlinkSocket.java
+++ b/services/net/java/android/net/netlink/NetlinkSocket.java
@@ -59,10 +59,9 @@
final String errPrefix = "Error in NetlinkSocket.sendOneShotKernelMessage";
final long IO_TIMEOUT = 300L;
- FileDescriptor fd;
+ final FileDescriptor fd = forProto(nlProto);
try {
- fd = forProto(nlProto);
connectToKernel(fd);
sendMessage(fd, msg, 0, msg.length, IO_TIMEOUT);
final ByteBuffer bytes = recvMessage(fd, DEFAULT_RECV_BUFSIZE, IO_TIMEOUT);
@@ -96,9 +95,9 @@
} catch (SocketException e) {
Log.e(TAG, errPrefix, e);
throw new ErrnoException(errPrefix, EIO, e);
+ } finally {
+ IoUtils.closeQuietly(fd);
}
-
- IoUtils.closeQuietly(fd);
}
public static FileDescriptor forProto(int nlProto) throws ErrnoException {
diff --git a/services/tests/servicestests/src/com/android/server/am/ActivityStartInterceptorTest.java b/services/tests/servicestests/src/com/android/server/am/ActivityStartInterceptorTest.java
index 7f55824..420987d 100644
--- a/services/tests/servicestests/src/com/android/server/am/ActivityStartInterceptorTest.java
+++ b/services/tests/servicestests/src/com/android/server/am/ActivityStartInterceptorTest.java
@@ -27,6 +27,7 @@
import static org.mockito.ArgumentMatchers.nullable;
import static org.mockito.Mockito.when;
+import android.app.ActivityManagerInternal;
import android.app.KeyguardManager;
import android.app.admin.DevicePolicyManagerInternal;
import android.content.Context;
@@ -94,11 +95,11 @@
@Mock
private UserManager mUserManager;
@Mock
- private UserController mUserController;
- @Mock
private KeyguardManager mKeyguardManager;
@Mock
private PackageManagerService mPackageManager;
+ @Mock
+ private ActivityManagerInternal mAmInternal;
private ActivityStartInterceptor mInterceptor;
private ActivityInfo mAInfo = new ActivityInfo();
@@ -107,11 +108,15 @@
public void setUp() {
MockitoAnnotations.initMocks(this);
mService.mAm = mAm;
- mInterceptor = new ActivityStartInterceptor(mService, mSupervisor, mContext,
- mUserController);
+ mService.mAmInternal = mAmInternal;
+ mInterceptor = new ActivityStartInterceptor(mService, mSupervisor, mContext);
mInterceptor.setStates(TEST_USER_ID, TEST_REAL_CALLING_PID, TEST_REAL_CALLING_UID,
TEST_START_FLAGS, TEST_CALLING_PACKAGE);
+ // Mock ActivityManagerInternal
+ LocalServices.removeServiceForTest(ActivityManagerInternal.class);
+ LocalServices.addService(ActivityManagerInternal.class, mAmInternal);
+
// Mock DevicePolicyManagerInternal
LocalServices.removeServiceForTest(DevicePolicyManagerInternal.class);
LocalServices.addService(DevicePolicyManagerInternal.class,
@@ -193,7 +198,7 @@
@Test
public void testWorkChallenge() {
// GIVEN that the user the activity is starting as is currently locked
- when(mUserController.shouldConfirmCredentials(TEST_USER_ID)).thenReturn(true);
+ when(mAmInternal.shouldConfirmCredentials(TEST_USER_ID)).thenReturn(true);
// THEN calling intercept returns true
mInterceptor.intercept(null, null, mAInfo, null, null, 0, 0, null);
diff --git a/services/tests/servicestests/src/com/android/server/am/ActivityTestsBase.java b/services/tests/servicestests/src/com/android/server/am/ActivityTestsBase.java
index 41c8955..f2d3eb6 100644
--- a/services/tests/servicestests/src/com/android/server/am/ActivityTestsBase.java
+++ b/services/tests/servicestests/src/com/android/server/am/ActivityTestsBase.java
@@ -106,13 +106,15 @@
}
protected ActivityTaskManagerService createActivityTaskManagerService() {
- final TestActivityTaskManagerService atm = spy(new TestActivityTaskManagerService(mContext));
+ final TestActivityTaskManagerService atm =
+ spy(new TestActivityTaskManagerService(mContext));
setupActivityManagerService(atm);
return atm;
}
- protected ActivityManagerService createActivityManagerService() {
- final TestActivityTaskManagerService atm = spy(new TestActivityTaskManagerService(mContext));
+ ActivityManagerService createActivityManagerService() {
+ final TestActivityTaskManagerService atm =
+ spy(new TestActivityTaskManagerService(mContext));
return setupActivityManagerService(atm);
}
diff --git a/services/tests/servicestests/src/com/android/server/am/RecentTasksTest.java b/services/tests/servicestests/src/com/android/server/am/RecentTasksTest.java
index a4e4409..3547b0d 100644
--- a/services/tests/servicestests/src/com/android/server/am/RecentTasksTest.java
+++ b/services/tests/servicestests/src/com/android/server/am/RecentTasksTest.java
@@ -108,37 +108,6 @@
private CallbacksRecorder mCallbacksRecorder;
- class TestUserController extends UserController {
- TestUserController(ActivityManagerService service) {
- super(service);
- }
-
- @Override
- int[] getCurrentProfileIds() {
- return new int[] { TEST_USER_0_ID, TEST_QUIET_USER_ID };
- }
-
- @Override
- Set<Integer> getProfileIds(int userId) {
- Set<Integer> profileIds = new HashSet<>();
- profileIds.add(TEST_USER_0_ID);
- profileIds.add(TEST_QUIET_USER_ID);
- return profileIds;
- }
-
- @Override
- UserInfo getUserInfo(int userId) {
- switch (userId) {
- case TEST_USER_0_ID:
- case TEST_USER_1_ID:
- return DEFAULT_USER_INFO;
- case TEST_QUIET_USER_ID:
- return QUIET_USER_INFO;
- }
- return null;
- }
- }
-
@Before
@Override
public void setUp() throws Exception {
@@ -829,7 +798,7 @@
@Override
protected RecentTasks createRecentTasks() {
- return new TestRecentTasks(this, mTaskPersister, new TestUserController(mAm));
+ return new TestRecentTasks(this, mTaskPersister);
}
@Override
@@ -954,9 +923,33 @@
boolean lastAllowed;
- TestRecentTasks(ActivityTaskManagerService service, TaskPersister taskPersister,
- UserController userController) {
- super(service, taskPersister, userController);
+ TestRecentTasks(ActivityTaskManagerService service, TaskPersister taskPersister) {
+ super(service, taskPersister);
+ }
+
+ @Override
+ Set<Integer> getProfileIds(int userId) {
+ Set<Integer> profileIds = new HashSet<>();
+ profileIds.add(TEST_USER_0_ID);
+ profileIds.add(TEST_QUIET_USER_ID);
+ return profileIds;
+ }
+
+ @Override
+ UserInfo getUserInfo(int userId) {
+ switch (userId) {
+ case TEST_USER_0_ID:
+ case TEST_USER_1_ID:
+ return DEFAULT_USER_INFO;
+ case TEST_QUIET_USER_ID:
+ return QUIET_USER_INFO;
+ }
+ return null;
+ }
+
+ @Override
+ int[] getCurrentProfileIds() {
+ return new int[] { TEST_USER_0_ID, TEST_QUIET_USER_ID };
}
@Override
diff --git a/services/tests/servicestests/src/com/android/server/wm/BoundsAnimationControllerTests.java b/services/tests/servicestests/src/com/android/server/wm/BoundsAnimationControllerTests.java
index ff631e7..08b522c 100644
--- a/services/tests/servicestests/src/com/android/server/wm/BoundsAnimationControllerTests.java
+++ b/services/tests/servicestests/src/com/android/server/wm/BoundsAnimationControllerTests.java
@@ -151,11 +151,13 @@
}
@Override
- public void onAnimationStart(boolean schedulePipModeChangedCallback, boolean forceUpdate) {
+ public boolean onAnimationStart(boolean schedulePipModeChangedCallback,
+ boolean forceUpdate) {
mAwaitingAnimationStart = false;
mAnimationStarted = true;
mSchedulePipModeChangedOnStart = schedulePipModeChangedCallback;
mForcePipModeChangedCallback = forceUpdate;
+ return true;
}
@Override
diff --git a/services/tests/servicestests/src/com/android/server/wm/TaskSnapshotSurfaceTest.java b/services/tests/servicestests/src/com/android/server/wm/TaskSnapshotSurfaceTest.java
index b19373e..21402ce 100644
--- a/services/tests/servicestests/src/com/android/server/wm/TaskSnapshotSurfaceTest.java
+++ b/services/tests/servicestests/src/com/android/server/wm/TaskSnapshotSurfaceTest.java
@@ -59,7 +59,7 @@
private void setupSurface(int width, int height, Rect contentInsets, int sysuiVis,
int windowFlags, Rect taskBounds) {
final GraphicBuffer buffer = GraphicBuffer.create(width, height, PixelFormat.RGBA_8888,
- GraphicBuffer.USAGE_SW_READ_NEVER | GraphicBuffer.USAGE_SW_WRITE_NEVER);
+ GraphicBuffer.USAGE_SW_READ_RARELY | GraphicBuffer.USAGE_SW_WRITE_NEVER);
final TaskSnapshot snapshot = new TaskSnapshot(buffer,
ORIENTATION_PORTRAIT, contentInsets, false, 1.0f, true /* isRealSnapshot */,
WINDOWING_MODE_FULLSCREEN, 0 /* systemUiVisibility */, false /* isTranslucent */);
diff --git a/services/tests/uiservicestests/src/com/android/server/notification/BuzzBeepBlinkTest.java b/services/tests/uiservicestests/src/com/android/server/notification/BuzzBeepBlinkTest.java
index 7809999..bdba3d5 100644
--- a/services/tests/uiservicestests/src/com/android/server/notification/BuzzBeepBlinkTest.java
+++ b/services/tests/uiservicestests/src/com/android/server/notification/BuzzBeepBlinkTest.java
@@ -19,7 +19,9 @@
import static android.app.Notification.GROUP_ALERT_CHILDREN;
import static android.app.Notification.GROUP_ALERT_SUMMARY;
import static android.app.NotificationManager.IMPORTANCE_HIGH;
+import static android.app.NotificationManager.IMPORTANCE_LOW;
import static android.app.NotificationManager.IMPORTANCE_MIN;
+import static android.app.NotificationManager.Policy.SUPPRESSED_EFFECT_LIGHTS;
import static junit.framework.Assert.assertFalse;
import static junit.framework.Assert.assertNull;
@@ -149,6 +151,9 @@
mService.setFallbackVibrationPattern(FALLBACK_VIBRATION_PATTERN);
mService.setUsageStats(mUsageStats);
mService.setAccessibilityManager(accessibilityManager);
+ mService.mScreenOn = false;
+ mService.mInCall = false;
+ mService.mNotificationPulseEnabled = true;
}
//
@@ -216,8 +221,13 @@
}
private NotificationRecord getLightsNotification() {
+ return getNotificationRecord(mId, false /* insistent */, false /* once */,
+ false /* noisy */, false /* buzzy*/, true /* lights */);
+ }
+
+ private NotificationRecord getLightsOnceNotification() {
return getNotificationRecord(mId, false /* insistent */, true /* once */,
- false /* noisy */, true /* buzzy*/, true /* lights */);
+ false /* noisy */, false /* buzzy*/, true /* lights */);
}
private NotificationRecord getCustomLightsNotification() {
@@ -244,6 +254,12 @@
groupKey, groupAlertBehavior, false);
}
+ private NotificationRecord getLightsNotificationRecord(String groupKey,
+ int groupAlertBehavior) {
+ return getNotificationRecord(mId, false, false, false, false, true /*lights*/, true, true,
+ true, groupKey, groupAlertBehavior, false);
+ }
+
private NotificationRecord getNotificationRecord(int id, boolean insistent, boolean once,
boolean noisy, boolean buzzy, boolean lights, boolean defaultVibration,
boolean defaultSound, boolean defaultLights, String groupKey, int groupAlertBehavior,
@@ -369,6 +385,10 @@
verify(mVibrator, never()).cancel();
}
+ private void verifyNeverLights() {
+ verify(mLight, never()).setFlashing(anyInt(), anyInt(), anyInt(), anyInt());
+ }
+
private void verifyLights() {
verify(mLight, times(1)).setFlashing(anyInt(), anyInt(), anyInt(), anyInt());
}
@@ -712,7 +732,8 @@
mService.buzzBeepBlinkLocked(summary);
verifyBeepLooped();
- assertTrue(summary.isInterruptive());
+ // summaries are never interruptive for notification counts
+ assertFalse(summary.isInterruptive());
}
@Test
@@ -990,6 +1011,156 @@
verify(mAccessibilityService, times(1)).sendAccessibilityEvent(any(), anyInt());
}
+ @Test
+ public void testLightsScreenOn() {
+ mService.mScreenOn = true;
+ NotificationRecord r = getLightsNotification();
+ mService.buzzBeepBlinkLocked(r);
+ verifyNeverLights();
+ assertFalse(r.isInterruptive());
+ }
+
+ @Test
+ public void testLightsInCall() {
+ mService.mInCall = true;
+ NotificationRecord r = getLightsNotification();
+ mService.buzzBeepBlinkLocked(r);
+ verifyNeverLights();
+ assertFalse(r.isInterruptive());
+ }
+
+ @Test
+ public void testLightsSilentUpdate() {
+ NotificationRecord r = getLightsOnceNotification();
+ mService.buzzBeepBlinkLocked(r);
+ verifyLights();
+ assertTrue(r.isInterruptive());
+
+ r = getLightsOnceNotification();
+ r.isUpdate = true;
+ mService.buzzBeepBlinkLocked(r);
+ // checks that lights happened once, i.e. this new call didn't trigger them again
+ verifyLights();
+ assertFalse(r.isInterruptive());
+ }
+
+ @Test
+ public void testLightsUnimportant() {
+ NotificationRecord r = getLightsNotification();
+ r.setImportance(IMPORTANCE_LOW, "testing");
+ mService.buzzBeepBlinkLocked(r);
+ verifyNeverLights();
+ assertFalse(r.isInterruptive());
+ }
+
+ @Test
+ public void testLightsNoLights() {
+ NotificationRecord r = getQuietNotification();
+ mService.buzzBeepBlinkLocked(r);
+ verifyNeverLights();
+ assertFalse(r.isInterruptive());
+ }
+
+ @Test
+ public void testLightsNoLightOnDevice() {
+ mService.mHasLight = false;
+ NotificationRecord r = getLightsNotification();
+ mService.buzzBeepBlinkLocked(r);
+ verifyNeverLights();
+ assertFalse(r.isInterruptive());
+ }
+
+ @Test
+ public void testLightsLightsOffGlobally() {
+ mService.mNotificationPulseEnabled = false;
+ NotificationRecord r = getLightsNotification();
+ mService.buzzBeepBlinkLocked(r);
+ verifyNeverLights();
+ assertFalse(r.isInterruptive());
+ }
+
+ @Test
+ public void testLightsDndIntercepted() {
+ NotificationRecord r = getLightsNotification();
+ r.setSuppressedVisualEffects(SUPPRESSED_EFFECT_LIGHTS);
+ mService.buzzBeepBlinkLocked(r);
+ verifyNeverLights();
+ assertFalse(r.isInterruptive());
+ }
+
+ @Test
+ public void testGroupAlertSummaryNoLightsChild() {
+ NotificationRecord child = getLightsNotificationRecord("a", GROUP_ALERT_SUMMARY);
+
+ mService.buzzBeepBlinkLocked(child);
+
+ verifyNeverLights();
+ assertFalse(child.isInterruptive());
+ }
+
+ @Test
+ public void testGroupAlertSummaryLightsSummary() {
+ NotificationRecord summary = getLightsNotificationRecord("a", GROUP_ALERT_SUMMARY);
+ summary.getNotification().flags |= Notification.FLAG_GROUP_SUMMARY;
+
+ mService.buzzBeepBlinkLocked(summary);
+
+ verifyLights();
+ // summaries should never count for interruptiveness counts
+ assertFalse(summary.isInterruptive());
+ }
+
+ @Test
+ public void testGroupAlertSummaryLightsNonGroupChild() {
+ NotificationRecord nonGroup = getLightsNotificationRecord(null, GROUP_ALERT_SUMMARY);
+
+ mService.buzzBeepBlinkLocked(nonGroup);
+
+ verifyLights();
+ assertTrue(nonGroup.isInterruptive());
+ }
+
+ @Test
+ public void testGroupAlertChildNoLightsSummary() {
+ NotificationRecord summary = getLightsNotificationRecord("a", GROUP_ALERT_CHILDREN);
+ summary.getNotification().flags |= Notification.FLAG_GROUP_SUMMARY;
+
+ mService.buzzBeepBlinkLocked(summary);
+
+ verifyNeverLights();
+ assertFalse(summary.isInterruptive());
+ }
+
+ @Test
+ public void testGroupAlertChildLightsChild() {
+ NotificationRecord child = getLightsNotificationRecord("a", GROUP_ALERT_CHILDREN);
+
+ mService.buzzBeepBlinkLocked(child);
+
+ verifyLights();
+ assertTrue(child.isInterruptive());
+ }
+
+ @Test
+ public void testGroupAlertChildLightsNonGroupSummary() {
+ NotificationRecord nonGroup = getLightsNotificationRecord(null, GROUP_ALERT_CHILDREN);
+
+ mService.buzzBeepBlinkLocked(nonGroup);
+
+ verifyLights();
+ assertTrue(nonGroup.isInterruptive());
+ }
+
+ @Test
+ public void testGroupAlertAllLightsGroup() {
+ NotificationRecord group = getLightsNotificationRecord("a", GROUP_ALERT_ALL);
+
+ mService.buzzBeepBlinkLocked(group);
+
+ verifyLights();
+ assertTrue(group.isInterruptive());
+ }
+
static class VibrateRepeatMatcher implements ArgumentMatcher<VibrationEffect> {
private final int mRepeatIndex;
diff --git a/services/tests/uiservicestests/src/com/android/server/slice/PinnedSliceStateTest.java b/services/tests/uiservicestests/src/com/android/server/slice/PinnedSliceStateTest.java
index 3c4e333..82e0fbe 100644
--- a/services/tests/uiservicestests/src/com/android/server/slice/PinnedSliceStateTest.java
+++ b/services/tests/uiservicestests/src/com/android/server/slice/PinnedSliceStateTest.java
@@ -1,16 +1,16 @@
package com.android.server.slice;
+import static android.testing.TestableContentResolver.UNSTABLE;
+
import static org.junit.Assert.assertArrayEquals;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertTrue;
-import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyInt;
import static org.mockito.ArgumentMatchers.anyString;
import static org.mockito.ArgumentMatchers.argThat;
import static org.mockito.ArgumentMatchers.eq;
-import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
@@ -71,11 +71,12 @@
mSliceService = mock(SliceManagerService.class);
when(mSliceService.getContext()).thenReturn(mContext);
when(mSliceService.getLock()).thenReturn(new Object());
- when(mSliceService.getHandler()).thenReturn(new Handler(TestableLooper.get(this).getLooper()));
+ when(mSliceService.getHandler()).thenReturn(
+ new Handler(TestableLooper.get(this).getLooper()));
mContentProvider = mock(ContentProvider.class);
mIContentProvider = mock(IContentProvider.class);
when(mContentProvider.getIContentProvider()).thenReturn(mIContentProvider);
- mContext.getContentResolver().addProvider(AUTH, mContentProvider);
+ mContext.getContentResolver().addProvider(AUTH, mContentProvider, UNSTABLE);
mPinnedSliceManager = new PinnedSliceState(mSliceService, TEST_URI, "pkg");
}
diff --git a/services/usage/java/com/android/server/usage/IntervalStats.java b/services/usage/java/com/android/server/usage/IntervalStats.java
index 0dce738..4b7e21f 100644
--- a/services/usage/java/com/android/server/usage/IntervalStats.java
+++ b/services/usage/java/com/android/server/usage/IntervalStats.java
@@ -27,7 +27,9 @@
import java.util.List;
-class IntervalStats {
+import com.android.internal.annotations.VisibleForTesting;
+
+public class IntervalStats {
public long beginTime;
public long endTime;
public long lastTimeSaved;
@@ -149,7 +151,11 @@
&& eventType != UsageEvents.Event.STANDBY_BUCKET_CHANGED;
}
- void update(String packageName, long timeStamp, int eventType) {
+ /**
+ * @hide
+ */
+ @VisibleForTesting
+ public void update(String packageName, long timeStamp, int eventType) {
UsageStats usageStats = getOrCreateUsageStats(packageName);
// TODO(adamlesinski): Ensure that we recover from incorrect event sequences
diff --git a/services/usage/java/com/android/server/usage/UsageStatsDatabase.java b/services/usage/java/com/android/server/usage/UsageStatsDatabase.java
index 9705469..5ab5dc2 100644
--- a/services/usage/java/com/android/server/usage/UsageStatsDatabase.java
+++ b/services/usage/java/com/android/server/usage/UsageStatsDatabase.java
@@ -42,7 +42,7 @@
/**
* Provides an interface to query for UsageStat data from an XML database.
*/
-class UsageStatsDatabase {
+public class UsageStatsDatabase {
private static final int CURRENT_VERSION = 3;
// Current version of the backup schema
@@ -369,7 +369,7 @@
/**
* Figures out what to extract from the given IntervalStats object.
*/
- interface StatCombiner<T> {
+ public interface StatCombiner<T> {
/**
* Implementations should extract interesting from <code>stats</code> and add it
diff --git a/telecomm/java/android/telecom/Connection.java b/telecomm/java/android/telecom/Connection.java
index 3e97c8f..468c8fa 100644
--- a/telecomm/java/android/telecom/Connection.java
+++ b/telecomm/java/android/telecom/Connection.java
@@ -854,6 +854,8 @@
private final OutputStreamWriter mPipeToInCall;
private final ParcelFileDescriptor mFdFromInCall;
private final ParcelFileDescriptor mFdToInCall;
+
+ private final FileInputStream mFromInCallFileInputStream;
private char[] mReadBuffer = new char[READ_BUFFER_SIZE];
/**
@@ -862,11 +864,11 @@
public RttTextStream(ParcelFileDescriptor toInCall, ParcelFileDescriptor fromInCall) {
mFdFromInCall = fromInCall;
mFdToInCall = toInCall;
+ mFromInCallFileInputStream = new FileInputStream(fromInCall.getFileDescriptor());
// Wrap the FileInputStream in a Channel so that it's interruptible.
mPipeFromInCall = new InputStreamReader(
- Channels.newInputStream(Channels.newChannel(
- new FileInputStream(fromInCall.getFileDescriptor()))));
+ Channels.newInputStream(Channels.newChannel(mFromInCallFileInputStream)));
mPipeToInCall = new OutputStreamWriter(
new FileOutputStream(toInCall.getFileDescriptor()));
}
@@ -914,7 +916,7 @@
* not entered any new text yet.
*/
public String readImmediately() throws IOException {
- if (mPipeFromInCall.ready()) {
+ if (mFromInCallFileInputStream.available() > 0) {
return read();
} else {
return null;
diff --git a/telephony/java/android/telephony/CellIdentity.java b/telephony/java/android/telephony/CellIdentity.java
index 890a6ea..2a41829 100644
--- a/telephony/java/android/telephony/CellIdentity.java
+++ b/telephony/java/android/telephony/CellIdentity.java
@@ -175,7 +175,10 @@
}
CellIdentity o = (CellIdentity) other;
- return TextUtils.equals(mAlphaLong, o.mAlphaLong)
+ return mType == o.mType
+ && TextUtils.equals(mMccStr, o.mMccStr)
+ && TextUtils.equals(mMncStr, o.mMncStr)
+ && TextUtils.equals(mAlphaLong, o.mAlphaLong)
&& TextUtils.equals(mAlphaShort, o.mAlphaShort);
}
@@ -233,4 +236,4 @@
protected void log(String s) {
Rlog.w(mTag, s);
}
-}
\ No newline at end of file
+}
diff --git a/telephony/java/android/telephony/CellIdentityTdscdma.java b/telephony/java/android/telephony/CellIdentityTdscdma.java
index 18ab6d4..feff238 100644
--- a/telephony/java/android/telephony/CellIdentityTdscdma.java
+++ b/telephony/java/android/telephony/CellIdentityTdscdma.java
@@ -18,7 +18,6 @@
import android.annotation.Nullable;
import android.os.Parcel;
-import android.text.TextUtils;
import java.util.Objects;
@@ -35,6 +34,8 @@
private final int mCid;
// 8-bit Cell Parameters ID described in TS 25.331, 0..127, INT_MAX if unknown.
private final int mCpid;
+ // 16-bit UMTS Absolute RF Channel Number described in TS 25.101 sec. 5.4.3
+ private final int mUarfcn;
/**
* @hide
@@ -44,6 +45,7 @@
mLac = Integer.MAX_VALUE;
mCid = Integer.MAX_VALUE;
mCpid = Integer.MAX_VALUE;
+ mUarfcn = Integer.MAX_VALUE;
}
/**
@@ -52,11 +54,12 @@
* @param lac 16-bit Location Area Code, 0..65535, INT_MAX if unknown
* @param cid 28-bit UMTS Cell Identity described in TS 25.331, 0..268435455, INT_MAX if unknown
* @param cpid 8-bit Cell Parameters ID described in TS 25.331, 0..127, INT_MAX if unknown
+ * @param uarfcn 16-bit UMTS Absolute RF Channel Number described in TS 25.101 sec. 5.4.3
*
* @hide
*/
- public CellIdentityTdscdma(int mcc, int mnc, int lac, int cid, int cpid) {
- this(String.valueOf(mcc), String.valueOf(mnc), lac, cid, cpid, null, null);
+ public CellIdentityTdscdma(int mcc, int mnc, int lac, int cid, int cpid, int uarfcn) {
+ this(String.valueOf(mcc), String.valueOf(mnc), lac, cid, cpid, uarfcn, null, null);
}
/**
@@ -65,39 +68,24 @@
* @param lac 16-bit Location Area Code, 0..65535, INT_MAX if unknown
* @param cid 28-bit UMTS Cell Identity described in TS 25.331, 0..268435455, INT_MAX if unknown
* @param cpid 8-bit Cell Parameters ID described in TS 25.331, 0..127, INT_MAX if unknown
- *
- * FIXME: This is a temporary constructor to facilitate migration.
- * @hide
- */
- public CellIdentityTdscdma(String mcc, String mnc, int lac, int cid, int cpid) {
- super(TAG, TYPE_TDSCDMA, mcc, mnc, null, null);
- mLac = lac;
- mCid = cid;
- mCpid = cpid;
- }
-
- /**
- * @param mcc 3-digit Mobile Country Code in string format
- * @param mnc 2 or 3-digit Mobile Network Code in string format
- * @param lac 16-bit Location Area Code, 0..65535, INT_MAX if unknown
- * @param cid 28-bit UMTS Cell Identity described in TS 25.331, 0..268435455, INT_MAX if unknown
- * @param cpid 8-bit Cell Parameters ID described in TS 25.331, 0..127, INT_MAX if unknown
+ * @param uarfcn 16-bit UMTS Absolute RF Channel Number described in TS 25.101 sec. 5.4.3
* @param alphal long alpha Operator Name String or Enhanced Operator Name String
* @param alphas short alpha Operator Name String or Enhanced Operator Name String
*
* @hide
*/
- public CellIdentityTdscdma(String mcc, String mnc, int lac, int cid, int cpid,
+ public CellIdentityTdscdma(String mcc, String mnc, int lac, int cid, int cpid, int uarfcn,
String alphal, String alphas) {
super(TAG, TYPE_TDSCDMA, mcc, mnc, alphal, alphas);
mLac = lac;
mCid = cid;
mCpid = cpid;
+ mUarfcn = uarfcn;
}
private CellIdentityTdscdma(CellIdentityTdscdma cid) {
this(cid.mMccStr, cid.mMncStr, cid.mLac, cid.mCid,
- cid.mCpid, cid.mAlphaLong, cid.mAlphaShort);
+ cid.mCpid, cid.mUarfcn, cid.mAlphaLong, cid.mAlphaShort);
}
CellIdentityTdscdma copy() {
@@ -141,9 +129,32 @@
return mCpid;
}
+ /** @hide */
@Override
- public int hashCode() {
- return Objects.hash(mLac, mCid, mCpid, super.hashCode());
+ public int getChannelNumber() {
+ return mUarfcn;
+ }
+
+ /**
+ * @return The long alpha tag associated with the current scan result (may be the operator
+ * name string or extended operator name string). May be null if unknown.
+ *
+ * @hide
+ */
+ @Nullable
+ public CharSequence getOperatorAlphaLong() {
+ return mAlphaLong;
+ }
+
+ /**
+ * @return The short alpha tag associated with the current scan result (may be the operator
+ * name string or extended operator name string). May be null if unknown.
+ *
+ * @hide
+ */
+ @Nullable
+ public CharSequence getOperatorAlphaShort() {
+ return mAlphaShort;
}
@Override
@@ -157,24 +168,29 @@
}
CellIdentityTdscdma o = (CellIdentityTdscdma) other;
- return TextUtils.equals(mMccStr, o.mMccStr)
- && TextUtils.equals(mMncStr, o.mMncStr)
- && mLac == o.mLac
+ return mLac == o.mLac
&& mCid == o.mCid
&& mCpid == o.mCpid
+ && mUarfcn == o.mUarfcn
&& super.equals(other);
}
@Override
+ public int hashCode() {
+ return Objects.hash(mLac, mCid, mCpid, mUarfcn, super.hashCode());
+ }
+
+ @Override
public String toString() {
return new StringBuilder(TAG)
.append(":{ mMcc=").append(mMccStr)
.append(" mMnc=").append(mMncStr)
+ .append(" mAlphaLong=").append(mAlphaLong)
+ .append(" mAlphaShort=").append(mAlphaShort)
.append(" mLac=").append(mLac)
.append(" mCid=").append(mCid)
.append(" mCpid=").append(mCpid)
- .append(" mAlphaLong=").append(mAlphaLong)
- .append(" mAlphaShort=").append(mAlphaShort)
+ .append(" mUarfcn=").append(mUarfcn)
.append("}").toString();
}
@@ -186,6 +202,7 @@
dest.writeInt(mLac);
dest.writeInt(mCid);
dest.writeInt(mCpid);
+ dest.writeInt(mUarfcn);
}
/** Construct from Parcel, type has already been processed */
@@ -194,7 +211,7 @@
mLac = in.readInt();
mCid = in.readInt();
mCpid = in.readInt();
-
+ mUarfcn = in.readInt();
if (DBG) log(toString());
}
diff --git a/telephony/java/android/telephony/CellIdentityWcdma.java b/telephony/java/android/telephony/CellIdentityWcdma.java
index 984483e..43f9406 100644
--- a/telephony/java/android/telephony/CellIdentityWcdma.java
+++ b/telephony/java/android/telephony/CellIdentityWcdma.java
@@ -35,7 +35,7 @@
private final int mCid;
// 9-bit UMTS Primary Scrambling Code described in TS 25.331, 0..511
private final int mPsc;
- // 16-bit UMTS Absolute RF Channel Number
+ // 16-bit UMTS Absolute RF Channel Number described in TS 25.101 sec. 5.4.4
private final int mUarfcn;
/**
@@ -70,7 +70,7 @@
* @param lac 16-bit Location Area Code, 0..65535
* @param cid 28-bit UMTS Cell Identity
* @param psc 9-bit UMTS Primary Scrambling Code
- * @param uarfcn 16-bit UMTS Absolute RF Channel Number
+ * @param uarfcn 16-bit UMTS Absolute RF Channel Number described in TS 25.101 sec. 5.4.3
*
* @hide
*/
@@ -83,7 +83,7 @@
* @param lac 16-bit Location Area Code, 0..65535
* @param cid 28-bit UMTS Cell Identity
* @param psc 9-bit UMTS Primary Scrambling Code
- * @param uarfcn 16-bit UMTS Absolute RF Channel Number
+ * @param uarfcn 16-bit UMTS Absolute RF Channel Number described in TS 25.101 sec. 5.4.3
* @param mccStr 3-digit Mobile Country Code in string format
* @param mncStr 2 or 3-digit Mobile Network Code in string format
* @param alphal long alpha Operator Name String or Enhanced Operator Name String
diff --git a/telephony/java/android/telephony/CellInfo.java b/telephony/java/android/telephony/CellInfo.java
index 9232ed7..3aab3fc 100644
--- a/telephony/java/android/telephony/CellInfo.java
+++ b/telephony/java/android/telephony/CellInfo.java
@@ -19,6 +19,7 @@
import android.annotation.IntDef;
import android.os.Parcel;
import android.os.Parcelable;
+
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
@@ -36,6 +37,8 @@
protected static final int TYPE_LTE = 3;
/** @hide */
protected static final int TYPE_WCDMA = 4;
+ /** @hide */
+ protected static final int TYPE_TDCDMA = 5;
// Type to distinguish where time stamp gets recorded.
@@ -260,6 +263,7 @@
case TYPE_CDMA: return CellInfoCdma.createFromParcelBody(in);
case TYPE_LTE: return CellInfoLte.createFromParcelBody(in);
case TYPE_WCDMA: return CellInfoWcdma.createFromParcelBody(in);
+ case TYPE_TDCDMA: return CellInfoTdscdma.createFromParcelBody(in);
default: throw new RuntimeException("Bad CellInfo Parcel");
}
}
diff --git a/telephony/java/android/telephony/CellInfoCdma.java b/telephony/java/android/telephony/CellInfoCdma.java
index 6f2f1f6..6403bc5 100644
--- a/telephony/java/android/telephony/CellInfoCdma.java
+++ b/telephony/java/android/telephony/CellInfoCdma.java
@@ -21,7 +21,7 @@
import android.telephony.Rlog;
/**
- * Immutable cell information from a point in time.
+ * A {@link CellInfo} representing a CDMA cell that provides identity and measurement info.
*/
public final class CellInfoCdma extends CellInfo implements Parcelable {
diff --git a/telephony/java/android/telephony/CellInfoGsm.java b/telephony/java/android/telephony/CellInfoGsm.java
index 1bedddb..a3a9b31 100644
--- a/telephony/java/android/telephony/CellInfoGsm.java
+++ b/telephony/java/android/telephony/CellInfoGsm.java
@@ -21,7 +21,7 @@
import android.telephony.Rlog;
/**
- * Immutable cell information from a point in time.
+ * A {@link CellInfo} representing a GSM cell that provides identity and measurement info.
*/
public final class CellInfoGsm extends CellInfo implements Parcelable {
diff --git a/telephony/java/android/telephony/CellInfoLte.java b/telephony/java/android/telephony/CellInfoLte.java
index 287c9f0..b892e89 100644
--- a/telephony/java/android/telephony/CellInfoLte.java
+++ b/telephony/java/android/telephony/CellInfoLte.java
@@ -21,7 +21,7 @@
import android.telephony.Rlog;
/**
- * Immutable cell information from a point in time.
+ * A {@link CellInfo} representing an LTE cell that provides identity and measurement info.
*/
public final class CellInfoLte extends CellInfo implements Parcelable {
diff --git a/telephony/java/android/telephony/CellInfoTdscdma.java b/telephony/java/android/telephony/CellInfoTdscdma.java
new file mode 100644
index 0000000..7084c51
--- /dev/null
+++ b/telephony/java/android/telephony/CellInfoTdscdma.java
@@ -0,0 +1,151 @@
+/*
+ * Copyright (C) 2018 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.telephony;
+
+import android.os.Parcel;
+import android.os.Parcelable;
+
+import java.util.Objects;
+
+/**
+ * A {@link CellInfo} representing a TD-SCDMA cell that provides identity and measurement info.
+ *
+ * @hide
+ */
+public final class CellInfoTdscdma extends CellInfo implements Parcelable {
+
+ private static final String LOG_TAG = "CellInfoTdscdma";
+ private static final boolean DBG = false;
+
+ private CellIdentityTdscdma mCellIdentityTdscdma;
+ private CellSignalStrengthTdscdma mCellSignalStrengthTdscdma;
+
+ /** @hide */
+ public CellInfoTdscdma() {
+ super();
+ mCellIdentityTdscdma = new CellIdentityTdscdma();
+ mCellSignalStrengthTdscdma = new CellSignalStrengthTdscdma();
+ }
+
+ /** @hide */
+ public CellInfoTdscdma(CellInfoTdscdma ci) {
+ super(ci);
+ this.mCellIdentityTdscdma = ci.mCellIdentityTdscdma.copy();
+ this.mCellSignalStrengthTdscdma = ci.mCellSignalStrengthTdscdma.copy();
+ }
+
+ public CellIdentityTdscdma getCellIdentity() {
+ return mCellIdentityTdscdma;
+ }
+ /** @hide */
+ public void setCellIdentity(CellIdentityTdscdma cid) {
+ mCellIdentityTdscdma = cid;
+ }
+
+ public CellSignalStrengthTdscdma getCellSignalStrength() {
+ return mCellSignalStrengthTdscdma;
+ }
+ /** @hide */
+ public void setCellSignalStrength(CellSignalStrengthTdscdma css) {
+ mCellSignalStrengthTdscdma = css;
+ }
+
+ /**
+ * @return hash code
+ */
+ @Override
+ public int hashCode() {
+ return Objects.hash(super.hashCode(), mCellIdentityTdscdma, mCellSignalStrengthTdscdma);
+ }
+
+ @Override
+ public boolean equals(Object other) {
+ if (!super.equals(other)) {
+ return false;
+ }
+ try {
+ CellInfoTdscdma o = (CellInfoTdscdma) other;
+ return mCellIdentityTdscdma.equals(o.mCellIdentityTdscdma)
+ && mCellSignalStrengthTdscdma.equals(o.mCellSignalStrengthTdscdma);
+ } catch (ClassCastException e) {
+ return false;
+ }
+ }
+
+ @Override
+ public String toString() {
+ StringBuffer sb = new StringBuffer();
+
+ sb.append("CellInfoTdscdma:{");
+ sb.append(super.toString());
+ sb.append(" ").append(mCellIdentityTdscdma);
+ sb.append(" ").append(mCellSignalStrengthTdscdma);
+ sb.append("}");
+
+ return sb.toString();
+ }
+
+ /** Implement the Parcelable interface */
+ @Override
+ public int describeContents() {
+ return 0;
+ }
+
+ /** Implement the Parcelable interface */
+ @Override
+ public void writeToParcel(Parcel dest, int flags) {
+ super.writeToParcel(dest, flags, TYPE_TDCDMA);
+ mCellIdentityTdscdma.writeToParcel(dest, flags);
+ mCellSignalStrengthTdscdma.writeToParcel(dest, flags);
+ }
+
+ /**
+ * Construct a CellInfoTdscdma object from the given parcel
+ * where the token is already been processed.
+ */
+ private CellInfoTdscdma(Parcel in) {
+ super(in);
+ mCellIdentityTdscdma = CellIdentityTdscdma.CREATOR.createFromParcel(in);
+ mCellSignalStrengthTdscdma = CellSignalStrengthTdscdma.CREATOR.createFromParcel(in);
+ }
+
+ /** Implement the Parcelable interface */
+ public static final Creator<CellInfoTdscdma> CREATOR = new Creator<CellInfoTdscdma>() {
+ @Override
+ public CellInfoTdscdma createFromParcel(Parcel in) {
+ in.readInt(); // Skip past token, we know what it is
+ return createFromParcelBody(in);
+ }
+
+ @Override
+ public CellInfoTdscdma[] newArray(int size) {
+ return new CellInfoTdscdma[size];
+ }
+ };
+
+ /** @hide */
+ protected static CellInfoTdscdma createFromParcelBody(Parcel in) {
+ return new CellInfoTdscdma(in);
+ }
+
+ /**
+ * log
+ */
+ private static void log(String s) {
+ Rlog.w(LOG_TAG, s);
+ }
+}
diff --git a/telephony/java/android/telephony/CellInfoWcdma.java b/telephony/java/android/telephony/CellInfoWcdma.java
index 0615702..005f3d3 100644
--- a/telephony/java/android/telephony/CellInfoWcdma.java
+++ b/telephony/java/android/telephony/CellInfoWcdma.java
@@ -20,8 +20,10 @@
import android.os.Parcelable;
import android.telephony.Rlog;
+import java.util.Objects;
+
/**
- * Immutable cell information from a point in time.
+ * A {@link CellInfo} representing a WCDMA cell that provides identity and measurement info.
*/
public final class CellInfoWcdma extends CellInfo implements Parcelable {
@@ -66,7 +68,7 @@
*/
@Override
public int hashCode() {
- return super.hashCode() + mCellIdentityWcdma.hashCode() + mCellSignalStrengthWcdma.hashCode();
+ return Objects.hash(super.hashCode(), mCellIdentityWcdma, mCellSignalStrengthWcdma);
}
@Override
diff --git a/telephony/java/android/telephony/CellSignalStrengthCdma.java b/telephony/java/android/telephony/CellSignalStrengthCdma.java
index 183f96d..aa6b207 100644
--- a/telephony/java/android/telephony/CellSignalStrengthCdma.java
+++ b/telephony/java/android/telephony/CellSignalStrengthCdma.java
@@ -104,7 +104,10 @@
}
/**
- * Get signal level as an int from 0..4
+ * Retrieve an abstract level value for the overall signal strength.
+ *
+ * @return a single integer from 0 to 4 representing the general signal quality.
+ * 0 represents very poor signal strength while 4 represents a very strong signal strength.
*/
@Override
public int getLevel() {
diff --git a/telephony/java/android/telephony/CellSignalStrengthGsm.java b/telephony/java/android/telephony/CellSignalStrengthGsm.java
index 8687cd1..cff159b 100644
--- a/telephony/java/android/telephony/CellSignalStrengthGsm.java
+++ b/telephony/java/android/telephony/CellSignalStrengthGsm.java
@@ -82,7 +82,10 @@
}
/**
- * Get signal level as an int from 0..4
+ * Retrieve an abstract level value for the overall signal strength.
+ *
+ * @return a single integer from 0 to 4 representing the general signal quality.
+ * 0 represents very poor signal strength while 4 represents a very strong signal strength.
*/
@Override
public int getLevel() {
diff --git a/telephony/java/android/telephony/CellSignalStrengthLte.java b/telephony/java/android/telephony/CellSignalStrengthLte.java
index 2b6928e..2f059f4 100644
--- a/telephony/java/android/telephony/CellSignalStrengthLte.java
+++ b/telephony/java/android/telephony/CellSignalStrengthLte.java
@@ -86,7 +86,10 @@
}
/**
- * Get signal level as an int from 0..4
+ * Retrieve an abstract level value for the overall signal strength.
+ *
+ * @return a single integer from 0 to 4 representing the general signal quality.
+ * 0 represents very poor signal strength while 4 represents a very strong signal strength.
*/
@Override
public int getLevel() {
diff --git a/telephony/java/android/telephony/CellSignalStrengthTdscdma.java b/telephony/java/android/telephony/CellSignalStrengthTdscdma.java
new file mode 100644
index 0000000..41859a3
--- /dev/null
+++ b/telephony/java/android/telephony/CellSignalStrengthTdscdma.java
@@ -0,0 +1,228 @@
+/*
+ * Copyright (C) 2018 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.telephony;
+
+import android.os.Parcel;
+import android.os.Parcelable;
+
+import java.util.Objects;
+
+/**
+ * Tdscdma signal strength related information.
+ *
+ * @hide
+ */
+public final class CellSignalStrengthTdscdma extends CellSignalStrength implements Parcelable {
+
+ private static final String LOG_TAG = "CellSignalStrengthTdscdma";
+ private static final boolean DBG = false;
+
+ private static final int TDSCDMA_SIGNAL_STRENGTH_GREAT = 12;
+ private static final int TDSCDMA_SIGNAL_STRENGTH_GOOD = 8;
+ private static final int TDSCDMA_SIGNAL_STRENGTH_MODERATE = 5;
+
+ private int mSignalStrength; // in ASU; Valid values are (0-31, 99) as defined in TS 27.007 8.5
+ // or Integer.MAX_VALUE if unknown
+ private int mBitErrorRate; // bit error rate (0-7, 99) as defined in TS 27.007 8.5 or
+ // Integer.MAX_VALUE if unknown
+ private int mRscp; // Pilot power (0-96, 255) as defined in TS 27.007 8.69 or Integer.MAX_VALUE
+ // if unknown
+
+ /** @hide */
+ public CellSignalStrengthTdscdma() {
+ setDefaultValues();
+ }
+
+ /** @hide */
+ public CellSignalStrengthTdscdma(int ss, int ber, int rscp) {
+ mSignalStrength = ss;
+ mBitErrorRate = ber;
+ mRscp = rscp;
+ }
+
+ /** @hide */
+ public CellSignalStrengthTdscdma(CellSignalStrengthTdscdma s) {
+ copyFrom(s);
+ }
+
+ /** @hide */
+ protected void copyFrom(CellSignalStrengthTdscdma s) {
+ mSignalStrength = s.mSignalStrength;
+ mBitErrorRate = s.mBitErrorRate;
+ mRscp = s.mRscp;
+ }
+
+ /** @hide */
+ @Override
+ public CellSignalStrengthTdscdma copy() {
+ return new CellSignalStrengthTdscdma(this);
+ }
+
+ /** @hide */
+ @Override
+ public void setDefaultValues() {
+ mSignalStrength = Integer.MAX_VALUE;
+ mBitErrorRate = Integer.MAX_VALUE;
+ mRscp = Integer.MAX_VALUE;
+ }
+
+ /**
+ * Retrieve an abstract level value for the overall signal strength.
+ *
+ * @return a single integer from 0 to 4 representing the general signal quality.
+ * 0 represents very poor signal strength while 4 represents a very strong signal strength.
+ */
+ @Override
+ public int getLevel() {
+ int level;
+
+ // ASU ranges from 0 to 31 - TS 27.007 Sec 8.5
+ // asu = 0 (-113dB or less) is very weak
+ // signal, its better to show 0 bars to the user in such cases.
+ // asu = 99 is a special case, where the signal strength is unknown.
+ int asu = mSignalStrength;
+ if (asu <= 2 || asu == 99) {
+ level = SIGNAL_STRENGTH_NONE_OR_UNKNOWN;
+ } else if (asu >= TDSCDMA_SIGNAL_STRENGTH_GREAT) {
+ level = SIGNAL_STRENGTH_GREAT;
+ } else if (asu >= TDSCDMA_SIGNAL_STRENGTH_GOOD) {
+ level = SIGNAL_STRENGTH_GOOD;
+ } else if (asu >= TDSCDMA_SIGNAL_STRENGTH_MODERATE) {
+ level = SIGNAL_STRENGTH_MODERATE;
+ } else {
+ level = SIGNAL_STRENGTH_POOR;
+ }
+ if (DBG) log("getLevel=" + level);
+ return level;
+ }
+
+ /**
+ * Get the signal strength as dBm
+ */
+ @Override
+ public int getDbm() {
+ int dBm;
+
+ int level = mSignalStrength;
+ int asu = (level == 99 ? Integer.MAX_VALUE : level);
+ if (asu != Integer.MAX_VALUE) {
+ dBm = -113 + (2 * asu);
+ } else {
+ dBm = Integer.MAX_VALUE;
+ }
+ if (DBG) log("getDbm=" + dBm);
+ return dBm;
+ }
+
+ /**
+ * Get the signal level as an asu value between 0..31, 99 is unknown
+ * Asu is calculated based on 3GPP RSRP. Refer to 3GPP 27.007 (Ver 10.3.0) Sec 8.69
+ */
+ @Override
+ public int getAsuLevel() {
+ // ASU ranges from 0 to 31 - TS 27.007 Sec 8.5
+ // asu = 0 (-113dB or less) is very weak
+ // signal, its better to show 0 bars to the user in such cases.
+ // asu = 99 is a special case, where the signal strength is unknown.
+ int level = mSignalStrength;
+ if (DBG) log("getAsuLevel=" + level);
+ return level;
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(mSignalStrength, mBitErrorRate);
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ CellSignalStrengthTdscdma s;
+
+ try {
+ s = (CellSignalStrengthTdscdma) o;
+ } catch (ClassCastException ex) {
+ return false;
+ }
+
+ if (o == null) {
+ return false;
+ }
+
+ return mSignalStrength == s.mSignalStrength
+ && mBitErrorRate == s.mBitErrorRate
+ && mRscp == s.mRscp;
+ }
+
+ /**
+ * @return string representation.
+ */
+ @Override
+ public String toString() {
+ return "CellSignalStrengthTdscdma:"
+ + " ss=" + mSignalStrength
+ + " ber=" + mBitErrorRate
+ + " rscp=" + mRscp;
+ }
+
+ /** Implement the Parcelable interface */
+ @Override
+ public void writeToParcel(Parcel dest, int flags) {
+ if (DBG) log("writeToParcel(Parcel, int): " + toString());
+ dest.writeInt(mSignalStrength);
+ dest.writeInt(mBitErrorRate);
+ dest.writeInt(mRscp);
+ }
+
+ /**
+ * Construct a SignalStrength object from the given parcel
+ * where the token is already been processed.
+ */
+ private CellSignalStrengthTdscdma(Parcel in) {
+ mSignalStrength = in.readInt();
+ mBitErrorRate = in.readInt();
+ mRscp = in.readInt();
+ if (DBG) log("CellSignalStrengthTdscdma(Parcel): " + toString());
+ }
+
+ /** Implement the Parcelable interface */
+ @Override
+ public int describeContents() {
+ return 0;
+ }
+
+ /** Implement the Parcelable interface */
+ @SuppressWarnings("hiding")
+ public static final Parcelable.Creator<CellSignalStrengthTdscdma> CREATOR =
+ new Parcelable.Creator<CellSignalStrengthTdscdma>() {
+ @Override
+ public CellSignalStrengthTdscdma createFromParcel(Parcel in) {
+ return new CellSignalStrengthTdscdma(in);
+ }
+
+ @Override
+ public CellSignalStrengthTdscdma[] newArray(int size) {
+ return new CellSignalStrengthTdscdma[size];
+ }
+ };
+
+ /**
+ * log
+ */
+ private static void log(String s) {
+ Rlog.w(LOG_TAG, s);
+ }
+}
diff --git a/telephony/java/android/telephony/CellSignalStrengthWcdma.java b/telephony/java/android/telephony/CellSignalStrengthWcdma.java
index dd32a96..21cf0be 100644
--- a/telephony/java/android/telephony/CellSignalStrengthWcdma.java
+++ b/telephony/java/android/telephony/CellSignalStrengthWcdma.java
@@ -35,7 +35,13 @@
private static final int WCDMA_SIGNAL_STRENGTH_MODERATE = 5;
private int mSignalStrength; // in ASU; Valid values are (0-31, 99) as defined in TS 27.007 8.5
- private int mBitErrorRate; // bit error rate (0-7, 99) as defined in TS 27.007 8.5
+ // or Integer.MAX_VALUE if unknown
+ private int mBitErrorRate; // bit error rate (0-7, 99) as defined in TS 27.007 8.5 or
+ // Integer.MAX_VALUE if unknown
+ private int mRscp; // bit error rate (0-96, 255) as defined in TS 27.007 8.69 or
+ // Integer.MAX_VALUE if unknown
+ private int mEcNo; // signal to noise radio (0-49, 255) as defined in TS 27.007 8.69 or
+ // Integer.MAX_VALUE if unknown
/** @hide */
public CellSignalStrengthWcdma() {
@@ -43,9 +49,11 @@
}
/** @hide */
- public CellSignalStrengthWcdma(int ss, int ber) {
+ public CellSignalStrengthWcdma(int ss, int ber, int rscp, int ecno) {
mSignalStrength = ss;
mBitErrorRate = ber;
+ mRscp = rscp;
+ mEcNo = ecno;
}
/** @hide */
@@ -57,6 +65,8 @@
protected void copyFrom(CellSignalStrengthWcdma s) {
mSignalStrength = s.mSignalStrength;
mBitErrorRate = s.mBitErrorRate;
+ mRscp = s.mRscp;
+ mEcNo = s.mEcNo;
}
/** @hide */
@@ -70,10 +80,15 @@
public void setDefaultValues() {
mSignalStrength = Integer.MAX_VALUE;
mBitErrorRate = Integer.MAX_VALUE;
+ mRscp = Integer.MAX_VALUE;
+ mEcNo = Integer.MAX_VALUE;
}
/**
- * Get signal level as an int from 0..4
+ * Retrieve an abstract level value for the overall signal strength.
+ *
+ * @return a single integer from 0 to 4 representing the general signal quality.
+ * 0 represents very poor signal strength while 4 represents a very strong signal strength.
*/
@Override
public int getLevel() {
@@ -145,7 +160,10 @@
return false;
}
- return mSignalStrength == s.mSignalStrength && mBitErrorRate == s.mBitErrorRate;
+ return mSignalStrength == s.mSignalStrength
+ && mBitErrorRate == s.mBitErrorRate
+ && mRscp == s.mRscp
+ && mEcNo == s.mEcNo;
}
/**
@@ -155,7 +173,9 @@
public String toString() {
return "CellSignalStrengthWcdma:"
+ " ss=" + mSignalStrength
- + " ber=" + mBitErrorRate;
+ + " ber=" + mBitErrorRate
+ + " rscp=" + mRscp
+ + " ecno=" + mEcNo;
}
/** Implement the Parcelable interface */
@@ -164,6 +184,8 @@
if (DBG) log("writeToParcel(Parcel, int): " + toString());
dest.writeInt(mSignalStrength);
dest.writeInt(mBitErrorRate);
+ dest.writeInt(mRscp);
+ dest.writeInt(mEcNo);
}
/**
@@ -173,6 +195,8 @@
private CellSignalStrengthWcdma(Parcel in) {
mSignalStrength = in.readInt();
mBitErrorRate = in.readInt();
+ mRscp = in.readInt();
+ mEcNo = in.readInt();
if (DBG) log("CellSignalStrengthWcdma(Parcel): " + toString());
}
diff --git a/telephony/java/android/telephony/SubscriptionInfo.java b/telephony/java/android/telephony/SubscriptionInfo.java
index 936505c..d76e39b 100644
--- a/telephony/java/android/telephony/SubscriptionInfo.java
+++ b/telephony/java/android/telephony/SubscriptionInfo.java
@@ -33,9 +33,9 @@
import android.os.Parcel;
import android.os.Parcelable;
import android.util.DisplayMetrics;
+import android.util.Log;
import java.util.Arrays;
-import java.util.ArrayList;
import java.util.List;
/**
@@ -105,12 +105,12 @@
/**
* Mobile Country Code
*/
- private int mMcc;
+ private String mMcc;
/**
* Mobile Network Code
*/
- private int mMnc;
+ private String mMnc;
/**
* ISO Country code for the subscription's provider
@@ -138,11 +138,11 @@
* @hide
*/
public SubscriptionInfo(int id, String iccId, int simSlotIndex, CharSequence displayName,
- CharSequence carrierName, int nameSource, int iconTint, String number, int roaming,
- Bitmap icon, int mcc, int mnc, String countryIso) {
+ CharSequence carrierName, int nameSource, int iconTint, String number, int roaming,
+ Bitmap icon, String mcc, String mnc, String countryIso) {
this(id, iccId, simSlotIndex, displayName, carrierName, nameSource, iconTint, number,
- roaming, icon, mcc, mnc, countryIso, false /* isEmbedded */,
- null /* accessRules */, null /* accessRules */);
+ roaming, icon, mcc, mnc, countryIso, false /* isEmbedded */,
+ null /* accessRules */, null /* accessRules */);
}
/**
@@ -150,7 +150,7 @@
*/
public SubscriptionInfo(int id, String iccId, int simSlotIndex, CharSequence displayName,
CharSequence carrierName, int nameSource, int iconTint, String number, int roaming,
- Bitmap icon, int mcc, int mnc, String countryIso, boolean isEmbedded,
+ Bitmap icon, String mcc, String mnc, String countryIso, boolean isEmbedded,
@Nullable UiccAccessRule[] accessRules) {
this(id, iccId, simSlotIndex, displayName, carrierName, nameSource, iconTint, number,
roaming, icon, mcc, mnc, countryIso, isEmbedded, accessRules, null /* cardId */);
@@ -161,7 +161,7 @@
*/
public SubscriptionInfo(int id, String iccId, int simSlotIndex, CharSequence displayName,
CharSequence carrierName, int nameSource, int iconTint, String number, int roaming,
- Bitmap icon, int mcc, int mnc, String countryIso, boolean isEmbedded,
+ Bitmap icon, String mcc, String mnc, String countryIso, boolean isEmbedded,
@Nullable UiccAccessRule[] accessRules, String cardId) {
this.mId = id;
this.mIccId = iccId;
@@ -316,15 +316,43 @@
/**
* @return the MCC.
+ * @deprecated Use {@link #getMccString()} instead.
*/
+ @Deprecated
public int getMcc() {
- return this.mMcc;
+ try {
+ return this.mMcc == null ? 0 : Integer.valueOf(this.mMcc);
+ } catch (NumberFormatException e) {
+ Log.w(SubscriptionInfo.class.getSimpleName(), "MCC string is not a number");
+ return 0;
+ }
}
/**
* @return the MNC.
+ * @deprecated Use {@link #getMncString()} instead.
*/
+ @Deprecated
public int getMnc() {
+ try {
+ return this.mMnc == null ? 0 : Integer.valueOf(this.mMnc);
+ } catch (NumberFormatException e) {
+ Log.w(SubscriptionInfo.class.getSimpleName(), "MNC string is not a number");
+ return 0;
+ }
+ }
+
+ /**
+ * @return The MCC, as a string.
+ */
+ public String getMccString() {
+ return this.mMcc;
+ }
+
+ /**
+ * @return The MNC, as a string.
+ */
+ public String getMncString() {
return this.mMnc;
}
@@ -425,8 +453,8 @@
int iconTint = source.readInt();
String number = source.readString();
int dataRoaming = source.readInt();
- int mcc = source.readInt();
- int mnc = source.readInt();
+ String mcc = source.readString();
+ String mnc = source.readString();
String countryIso = source.readString();
Bitmap iconBitmap = Bitmap.CREATOR.createFromParcel(source);
boolean isEmbedded = source.readBoolean();
@@ -455,8 +483,8 @@
dest.writeInt(mIconTint);
dest.writeString(mNumber);
dest.writeInt(mDataRoaming);
- dest.writeInt(mMcc);
- dest.writeInt(mMnc);
+ dest.writeString(mMcc);
+ dest.writeString(mMnc);
dest.writeString(mCountryIso);
mIconBitmap.writeToParcel(dest, flags);
dest.writeBoolean(mIsEmbedded);
diff --git a/telephony/java/android/telephony/SubscriptionManager.java b/telephony/java/android/telephony/SubscriptionManager.java
index ece646c..17e7c49 100644
--- a/telephony/java/android/telephony/SubscriptionManager.java
+++ b/telephony/java/android/telephony/SubscriptionManager.java
@@ -253,6 +253,20 @@
public static final int SIM_PROVISIONED = 0;
/**
+ * TelephonyProvider column name for the MCC associated with a SIM, stored as a string.
+ * <P>Type: TEXT (String)</P>
+ * @hide
+ */
+ public static final String MCC_STRING = "mcc_string";
+
+ /**
+ * TelephonyProvider column name for the MNC associated with a SIM, stored as a string.
+ * <P>Type: TEXT (String)</P>
+ * @hide
+ */
+ public static final String MNC_STRING = "mnc_string";
+
+ /**
* TelephonyProvider column name for the MCC associated with a SIM.
* <P>Type: INTEGER (int)</P>
* @hide
diff --git a/telephony/java/android/telephony/TelephonyManager.java b/telephony/java/android/telephony/TelephonyManager.java
index 6e261dd..9e23c5c 100644
--- a/telephony/java/android/telephony/TelephonyManager.java
+++ b/telephony/java/android/telephony/TelephonyManager.java
@@ -1312,6 +1312,33 @@
}
/**
+ * Returns the Type Allocation Code from the IMEI. Return null if Type Allocation Code is not
+ * available.
+ */
+ public String getTypeAllocationCode() {
+ return getTypeAllocationCode(getSlotIndex());
+ }
+
+ /**
+ * Returns the Type Allocation Code from the IMEI. Return null if Type Allocation Code is not
+ * available.
+ *
+ * @param slotIndex of which Type Allocation Code is returned
+ */
+ public String getTypeAllocationCode(int slotIndex) {
+ ITelephony telephony = getITelephony();
+ if (telephony == null) return null;
+
+ try {
+ return telephony.getTypeAllocationCodeForSlot(slotIndex);
+ } catch (RemoteException ex) {
+ return null;
+ } catch (NullPointerException ex) {
+ return null;
+ }
+ }
+
+ /**
* Returns the MEID (Mobile Equipment Identifier). Return null if MEID is not available.
*
* <p>Requires Permission: {@link android.Manifest.permission#READ_PHONE_STATE READ_PHONE_STATE}
@@ -1347,6 +1374,33 @@
}
/**
+ * Returns the Manufacturer Code from the MEID. Return null if Manufacturer Code is not
+ * available.
+ */
+ public String getManufacturerCode() {
+ return getManufacturerCode(getSlotIndex());
+ }
+
+ /**
+ * Returns the Manufacturer Code from the MEID. Return null if Manufacturer Code is not
+ * available.
+ *
+ * @param slotIndex of which Type Allocation Code is returned
+ */
+ public String getManufacturerCode(int slotIndex) {
+ ITelephony telephony = getITelephony();
+ if (telephony == null) return null;
+
+ try {
+ return telephony.getManufacturerCodeForSlot(slotIndex);
+ } catch (RemoteException ex) {
+ return null;
+ } catch (NullPointerException ex) {
+ return null;
+ }
+ }
+
+ /**
* Returns the Network Access Identifier (NAI). Return null if NAI is not available.
*
* <p>Requires Permission: {@link android.Manifest.permission#READ_PHONE_STATE READ_PHONE_STATE}
diff --git a/telephony/java/android/telephony/ims/ImsExternalCallState.java b/telephony/java/android/telephony/ims/ImsExternalCallState.java
index d03c7e1..e158fa8 100644
--- a/telephony/java/android/telephony/ims/ImsExternalCallState.java
+++ b/telephony/java/android/telephony/ims/ImsExternalCallState.java
@@ -87,6 +87,7 @@
mCallId = in.readInt();
ClassLoader classLoader = ImsExternalCallState.class.getClassLoader();
mAddress = in.readParcelable(classLoader);
+ mLocalAddress = in.readParcelable(classLoader);
mIsPullable = (in.readInt() != 0);
mCallState = in.readInt();
mCallType = in.readInt();
@@ -103,6 +104,7 @@
public void writeToParcel(Parcel out, int flags) {
out.writeInt(mCallId);
out.writeParcelable(mAddress, 0);
+ out.writeParcelable(mLocalAddress, 0);
out.writeInt(mIsPullable ? 1 : 0);
out.writeInt(mCallState);
out.writeInt(mCallType);
@@ -131,6 +133,11 @@
return mAddress;
}
+ /** @hide */
+ public Uri getLocalAddress() {
+ return mLocalAddress;
+ }
+
public boolean isCallPullable() {
return mIsPullable;
}
@@ -151,6 +158,7 @@
public String toString() {
return "ImsExternalCallState { mCallId = " + mCallId +
", mAddress = " + Log.pii(mAddress) +
+ ", mLocalAddress = " + Log.pii(mLocalAddress) +
", mIsPullable = " + mIsPullable +
", mCallState = " + mCallState +
", mCallType = " + mCallType +
diff --git a/telephony/java/com/android/internal/telephony/ITelephony.aidl b/telephony/java/com/android/internal/telephony/ITelephony.aidl
index 84a18b4..d850fbc 100644
--- a/telephony/java/com/android/internal/telephony/ITelephony.aidl
+++ b/telephony/java/com/android/internal/telephony/ITelephony.aidl
@@ -1195,6 +1195,13 @@
String getImeiForSlot(int slotIndex, String callingPackage);
/**
+ * Returns the Type Allocation Code from the IMEI for the given slot.
+ *
+ * @param slotIndex - Which slot to retrieve the Type Allocation Code from.
+ */
+ String getTypeAllocationCodeForSlot(int slotIndex);
+
+ /**
* Returns the MEID for the given slot.
*
* @param slotIndex - device slot.
@@ -1205,6 +1212,13 @@
String getMeidForSlot(int slotIndex, String callingPackage);
/**
+ * Returns the Manufacturer Code from the MEID for the given slot.
+ *
+ * @param slotIndex - Which slot to retrieve the Manufacturer Code from.
+ */
+ String getManufacturerCodeForSlot(int slotIndex);
+
+ /**
* Returns the device software version.
*
* @param slotIndex - device slot.
diff --git a/test-base/Android.bp b/test-base/Android.bp
index a0e3985..d25b477 100644
--- a/test-base/Android.bp
+++ b/test-base/Android.bp
@@ -21,6 +21,7 @@
// Also contains the com.android.internal.util.Predicate[s] classes.
java_library {
name: "android.test.base",
+ installable: true,
srcs: ["src/**/*.java"],
@@ -42,6 +43,7 @@
// Also contains the com.android.internal.util.Predicate[s] classes.
java_library {
name: "legacy-test",
+ installable: true,
sdk_version: "current",
static_libs: ["android.test.base"],
@@ -115,4 +117,5 @@
},
},
sdk_version: "current",
+ compile_dex: true,
}
diff --git a/test-mock/Android.bp b/test-mock/Android.bp
index 51fa86b..8d3faae 100644
--- a/test-mock/Android.bp
+++ b/test-mock/Android.bp
@@ -18,6 +18,7 @@
// ===================================
java_library {
name: "android.test.mock",
+ installable: true,
java_version: "1.8",
srcs: ["src/**/*.java"],
@@ -91,6 +92,7 @@
enabled: false,
},
},
+ compile_dex: true,
}
java_library_static {
@@ -104,4 +106,5 @@
enabled: false,
},
},
+ compile_dex: true,
}
diff --git a/test-runner/Android.bp b/test-runner/Android.bp
index b50ba3b..2caa6c4 100644
--- a/test-runner/Android.bp
+++ b/test-runner/Android.bp
@@ -18,6 +18,7 @@
// =====================================
java_library {
name: "android.test.runner",
+ installable: true,
// Needs to be consistent with the repackaged version of this make target.
java_version: "1.8",
@@ -120,4 +121,5 @@
},
},
sdk_version: "current",
+ compile_dex: true,
}
diff --git a/tests/UsageStatsPerfTests/Android.mk b/tests/UsageStatsPerfTests/Android.mk
new file mode 100644
index 0000000..cd29b51
--- /dev/null
+++ b/tests/UsageStatsPerfTests/Android.mk
@@ -0,0 +1,34 @@
+# Copyright (C) 2018 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.
+
+LOCAL_PATH := $(call my-dir)
+include $(CLEAR_VARS)
+
+LOCAL_MODULE_TAGS := tests
+
+LOCAL_SRC_FILES := \
+ $(call all-java-files-under, src)
+
+LOCAL_STATIC_JAVA_LIBRARIES := \
+ android-support-test \
+ apct-perftests-utils \
+ services.usage
+
+LOCAL_PACKAGE_NAME := UsageStatsPerfTests
+LOCAL_PRIVATE_PLATFORM_APIS := true
+
+# For android.permission.FORCE_STOP_PACKAGES permission
+LOCAL_CERTIFICATE := platform
+
+include $(BUILD_PACKAGE)
diff --git a/tests/UsageStatsPerfTests/AndroidManifest.xml b/tests/UsageStatsPerfTests/AndroidManifest.xml
new file mode 100644
index 0000000..596a79c
--- /dev/null
+++ b/tests/UsageStatsPerfTests/AndroidManifest.xml
@@ -0,0 +1,29 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2018 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.
+-->
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+ package="com.android.frameworks.perftests.usage">
+ <uses-sdk
+ android:minSdkVersion="21" />
+ <uses-permission android:name="android.permission.DUMP" />
+ <uses-permission android:name="android.permission.FORCE_STOP_PACKAGES" />
+
+ <application>
+ <uses-library android:name="android.test.runner" />
+ </application>
+
+ <instrumentation android:name="android.support.test.runner.AndroidJUnitRunner"
+ android:targetPackage="com.android.frameworks.perftests.usage"/>
+</manifest>
diff --git a/tests/UsageStatsPerfTests/AndroidTest.xml b/tests/UsageStatsPerfTests/AndroidTest.xml
new file mode 100644
index 0000000..c9b51dc
--- /dev/null
+++ b/tests/UsageStatsPerfTests/AndroidTest.xml
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2018 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.
+-->
+<configuration description="Runs UsageStats Performance Tests">
+ <target_preparer class="com.android.tradefed.targetprep.TestAppInstallSetup">
+ <option name="test-file-name" value="UsageStatsPerfTests.apk"/>
+ <option name="cleanup-apks" value="true"/>
+ </target_preparer>
+
+ <option name="test-suite-tag" value="apct"/>
+ <option name="test-tag" value="UsageStatsPerfTests"/>
+ <test class="com.android.tradefed.testtype.AndroidJUnitTest">
+ <option name="package" value="com.android.frameworks.perftests.usage"/>
+ <option name="runner" value="android.support.test.runner.AndroidJUnitRunner"/>
+ </test>
+</configuration>
\ No newline at end of file
diff --git a/tests/UsageStatsPerfTests/src/com/android/frameworks/perftests/usage/tests/UsageStatsDatabasePerfTest.java b/tests/UsageStatsPerfTests/src/com/android/frameworks/perftests/usage/tests/UsageStatsDatabasePerfTest.java
new file mode 100644
index 0000000..8467bee
--- /dev/null
+++ b/tests/UsageStatsPerfTests/src/com/android/frameworks/perftests/usage/tests/UsageStatsDatabasePerfTest.java
@@ -0,0 +1,183 @@
+/*
+ * Copyright (C) 2018 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.frameworks.perftests.usage.tests;
+
+import static junit.framework.Assert.assertEquals;
+
+import com.android.server.usage.UsageStatsDatabase;
+import com.android.server.usage.UsageStatsDatabase.StatCombiner;
+import com.android.server.usage.IntervalStats;
+
+import android.app.usage.EventList;
+import android.app.usage.UsageEvents;
+import android.app.usage.UsageStatsManager;
+import android.content.Context;
+import android.os.SystemClock;
+import android.perftests.utils.ManualBenchmarkState;
+import android.perftests.utils.PerfManualStatusReporter;
+import android.support.test.filters.LargeTest;
+import android.support.test.InstrumentationRegistry;
+import android.support.test.runner.AndroidJUnit4;
+
+import org.junit.BeforeClass;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import java.io.File;
+import java.io.IOException;
+import java.util.List;
+
+@RunWith(AndroidJUnit4.class)
+@LargeTest
+public class UsageStatsDatabasePerfTest {
+ protected static Context sContext;
+ private static UsageStatsDatabase sUsageStatsDatabase;
+ private static File mTestDir;
+
+ // Represents how many apps might have used in a day by a user with a few apps
+ final static int FEW_PKGS = 10;
+ // Represent how many apps might have used in a day by a user with many apps
+ final static int MANY_PKGS = 50;
+ // Represents how many usage events per app a device might have with light usage
+ final static int LIGHT_USE = 10;
+ // Represents how many usage events per app a device might have with heavy usage
+ final static int HEAVY_USE = 50;
+
+ private static final StatCombiner<UsageEvents.Event> sUsageStatsCombiner =
+ new StatCombiner<UsageEvents.Event>() {
+ @Override
+ public void combine(IntervalStats stats, boolean mutable,
+ List<UsageEvents.Event> accResult) {
+ final int size = stats.events.size();
+ for (int i = 0; i < size; i++) {
+ accResult.add(stats.events.get(i));
+ }
+ }
+ };
+
+
+ @Rule
+ public PerfManualStatusReporter mPerfManualStatusReporter = new PerfManualStatusReporter();
+
+ @BeforeClass
+ public static void setUpOnce() {
+ sContext = InstrumentationRegistry.getTargetContext();
+ mTestDir = new File(sContext.getFilesDir(), "UsageStatsDatabasePerfTest");
+ sUsageStatsDatabase = new UsageStatsDatabase(mTestDir);
+ sUsageStatsDatabase.init(1);
+ }
+
+ private static void populateIntervalStats(IntervalStats intervalStats, int packageCount,
+ int eventsPerPackage) {
+ if (intervalStats.events == null) {
+ intervalStats.events = new EventList();
+ }
+ for (int pkg = 0; pkg < packageCount; pkg++) {
+ UsageEvents.Event event = new UsageEvents.Event();
+ event.mPackage = "fake.package.name" + pkg;
+ event.mTimeStamp = 1;
+ event.mEventType = UsageEvents.Event.MOVE_TO_FOREGROUND;
+ for (int evt = 0; evt < eventsPerPackage; evt++) {
+ intervalStats.events.insert(event);
+ intervalStats.update(event.mPackage, event.mTimeStamp, event.mEventType);
+ }
+ }
+ }
+
+ private static void clearUsageStatsFiles() {
+ File[] intervalDirs = mTestDir.listFiles();
+ for (File intervalDir : intervalDirs) {
+ if (intervalDir.isDirectory()) {
+ File[] usageFiles = intervalDir.listFiles();
+ for (File f : usageFiles) {
+ f.delete();
+ }
+ }
+ }
+ }
+
+ private void runQueryUsageStatsTest(int packageCount, int eventsPerPackage) throws IOException {
+ final ManualBenchmarkState benchmarkState = mPerfManualStatusReporter.getBenchmarkState();
+ IntervalStats intervalStats = new IntervalStats();
+ populateIntervalStats(intervalStats, packageCount, eventsPerPackage);
+ sUsageStatsDatabase.putUsageStats(0, intervalStats);
+ long elapsedTimeNs = 0;
+ while (benchmarkState.keepRunning(elapsedTimeNs)) {
+ final long startTime = SystemClock.elapsedRealtimeNanos();
+ List<UsageEvents.Event> temp = sUsageStatsDatabase.queryUsageStats(
+ UsageStatsManager.INTERVAL_DAILY, 0, 2, sUsageStatsCombiner);
+ final long endTime = SystemClock.elapsedRealtimeNanos();
+ elapsedTimeNs = endTime - startTime;
+ assertEquals(packageCount * eventsPerPackage, temp.size());
+ }
+ }
+
+ private void runPutUsageStatsTest(int packageCount, int eventsPerPackage) throws IOException {
+ final ManualBenchmarkState benchmarkState = mPerfManualStatusReporter.getBenchmarkState();
+ IntervalStats intervalStats = new IntervalStats();
+ populateIntervalStats(intervalStats, packageCount, eventsPerPackage);
+ long elapsedTimeNs = 0;
+ while (benchmarkState.keepRunning(elapsedTimeNs)) {
+ final long startTime = SystemClock.elapsedRealtimeNanos();
+ sUsageStatsDatabase.putUsageStats(0, intervalStats);
+ final long endTime = SystemClock.elapsedRealtimeNanos();
+ elapsedTimeNs = endTime - startTime;
+ clearUsageStatsFiles();
+ }
+ }
+
+ @Test
+ public void testQueryUsageStats_FewPkgsLightUse() throws IOException {
+ runQueryUsageStatsTest(FEW_PKGS, LIGHT_USE);
+ }
+
+ @Test
+ public void testPutUsageStats_FewPkgsLightUse() throws IOException {
+ runPutUsageStatsTest(FEW_PKGS, LIGHT_USE);
+ }
+
+ @Test
+ public void testQueryUsageStats_FewPkgsHeavyUse() throws IOException {
+ runQueryUsageStatsTest(FEW_PKGS, HEAVY_USE);
+ }
+
+ @Test
+ public void testPutUsageStats_FewPkgsHeavyUse() throws IOException {
+ runPutUsageStatsTest(FEW_PKGS, HEAVY_USE);
+ }
+
+ @Test
+ public void testQueryUsageStats_ManyPkgsLightUse() throws IOException {
+ runQueryUsageStatsTest(MANY_PKGS, LIGHT_USE);
+ }
+
+ @Test
+ public void testPutUsageStats_ManyPkgsLightUse() throws IOException {
+ runPutUsageStatsTest(MANY_PKGS, LIGHT_USE);
+ }
+
+ @Test
+ public void testQueryUsageStats_ManyPkgsHeavyUse() throws IOException {
+ runQueryUsageStatsTest(MANY_PKGS, HEAVY_USE);
+ }
+
+ @Test
+ public void testPutUsageStats_ManyPkgsHeavyUse() throws IOException {
+ runPutUsageStatsTest(MANY_PKGS, HEAVY_USE);
+ }
+}
diff --git a/tests/testables/src/android/testing/TestableContentResolver.java b/tests/testables/src/android/testing/TestableContentResolver.java
index 0850916..a0afef8 100644
--- a/tests/testables/src/android/testing/TestableContentResolver.java
+++ b/tests/testables/src/android/testing/TestableContentResolver.java
@@ -20,6 +20,7 @@
import android.content.IContentProvider;
import android.database.ContentObserver;
import android.net.Uri;
+import android.util.ArrayMap;
import android.util.ArraySet;
import com.google.android.collect.Maps;
@@ -35,7 +36,11 @@
*/
public class TestableContentResolver extends ContentResolver {
- private final Map<String, ContentProvider> mProviders = Maps.newHashMap();
+ public static final int STABLE = 1;
+ public static final int UNSTABLE = 2;
+
+ private final Map<String, ContentProvider> mProviders = new ArrayMap<>();
+ private final Map<String, ContentProvider> mUnstableProviders = new ArrayMap<>();
private final ContentResolver mParent;
private final ArraySet<ContentProvider> mInUse = new ArraySet<>();
private boolean mFallbackToExisting;
@@ -62,7 +67,23 @@
* subclasses, or null.
*/
public void addProvider(String name, ContentProvider provider) {
- mProviders.put(name, provider);
+ addProvider(name, provider, STABLE | UNSTABLE);
+ }
+
+ /**
+ * Adds access to a provider based on its authority
+ *
+ * @param name The authority name associated with the provider.
+ * @param provider An instance of {@link android.content.ContentProvider} or one of its
+ * subclasses, or null.
+ */
+ public void addProvider(String name, ContentProvider provider, int flags) {
+ if ((flags & STABLE) != 0) {
+ mProviders.put(name, provider);
+ }
+ if ((flags & UNSTABLE) != 0) {
+ mUnstableProviders.put(name, provider);
+ }
}
@Override
@@ -98,7 +119,7 @@
@Override
protected IContentProvider acquireUnstableProvider(Context c, String name) {
- final ContentProvider provider = mProviders.get(name);
+ final ContentProvider provider = mUnstableProviders.get(name);
if (provider != null) {
return provider.getIContentProvider();
} else {
@@ -128,7 +149,8 @@
@Override
public void notifyChange(Uri uri, ContentObserver observer, boolean syncToNetwork) {
if (!mFallbackToExisting) return;
- if (!mProviders.containsKey(uri.getAuthority())) {
+ if (!mProviders.containsKey(uri.getAuthority())
+ && !mUnstableProviders.containsKey(uri.getAuthority())) {
super.notifyChange(uri, observer, syncToNetwork);
}
}
diff --git a/tests/testables/tests/src/android/testing/TestableContentResolverTest.java b/tests/testables/tests/src/android/testing/TestableContentResolverTest.java
new file mode 100644
index 0000000..71afda0
--- /dev/null
+++ b/tests/testables/tests/src/android/testing/TestableContentResolverTest.java
@@ -0,0 +1,61 @@
+package android.testing;
+
+import android.content.ContentProvider;
+import android.content.IContentProvider;
+import android.support.test.InstrumentationRegistry;
+import android.support.test.filters.SmallTest;
+
+import org.junit.Assert;
+import org.junit.Before;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mockito;
+
+@SmallTest
+@RunWith(AndroidTestingRunner.class)
+public class TestableContentResolverTest {
+
+ @Rule
+ public TestableContext mContext = new TestableContext(InstrumentationRegistry.getContext());
+ private TestableContentResolver mContentResolver;
+
+ @Before
+ public void setup() {
+ mContentResolver = new TestableContentResolver(mContext);
+ mContentResolver.setFallbackToExisting(false);
+ }
+
+ @Test
+ public void testDefaultContentProvider() {
+ ContentProvider provider = Mockito.mock(ContentProvider.class);
+ IContentProvider iprovider = Mockito.mock(IContentProvider.class);
+ Mockito.when(provider.getIContentProvider()).thenReturn(iprovider);
+ mContentResolver.addProvider("test", provider);
+
+ Assert.assertEquals(iprovider, mContentResolver.acquireProvider(mContext, "test"));
+ Assert.assertEquals(iprovider, mContentResolver.acquireUnstableProvider(mContext, "test"));
+ }
+
+ @Test
+ public void testStableContentProvider() {
+ ContentProvider provider = Mockito.mock(ContentProvider.class);
+ IContentProvider iprovider = Mockito.mock(IContentProvider.class);
+ Mockito.when(provider.getIContentProvider()).thenReturn(iprovider);
+ mContentResolver.addProvider("test", provider, TestableContentResolver.STABLE);
+
+ Assert.assertEquals(iprovider, mContentResolver.acquireProvider(mContext, "test"));
+ Assert.assertNull(mContentResolver.acquireUnstableProvider(mContext, "test"));
+ }
+
+ @Test
+ public void testUnstableContentProvider() {
+ ContentProvider provider = Mockito.mock(ContentProvider.class);
+ IContentProvider iprovider = Mockito.mock(IContentProvider.class);
+ Mockito.when(provider.getIContentProvider()).thenReturn(iprovider);
+ mContentResolver.addProvider("test", provider, TestableContentResolver.UNSTABLE);
+
+ Assert.assertEquals(iprovider, mContentResolver.acquireUnstableProvider(mContext, "test"));
+ Assert.assertNull(mContentResolver.acquireProvider(mContext, "test"));
+ }
+}
diff --git a/wifi/OWNERS b/wifi/OWNERS
index 0efa464..0601047 100644
--- a/wifi/OWNERS
+++ b/wifi/OWNERS
@@ -1,5 +1,6 @@
set noparent
etancohen@google.com
+mplass@google.com
+rpius@google.com
satk@google.com
-silberst@google.com