Merge "Adding more APIs to greylist Test: None" into pi-dev
diff --git a/Android.bp b/Android.bp
index ce93568..9c76e14 100644
--- a/Android.bp
+++ b/Android.bp
@@ -145,7 +145,7 @@
":libcamera_client_framework_aidl",
"core/java/android/hardware/IConsumerIrService.aidl",
"core/java/android/hardware/ISerialManager.aidl",
- "core/java/android/hardware/biometrics/IBiometricDialogReceiver.aidl",
+ "core/java/android/hardware/biometrics/IBiometricPromptReceiver.aidl",
"core/java/android/hardware/display/IDisplayManager.aidl",
"core/java/android/hardware/display/IDisplayManagerCallback.aidl",
"core/java/android/hardware/display/IVirtualDisplayCallback.aidl",
diff --git a/api/current.txt b/api/current.txt
index 7cfcbb4..c351bee 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -6511,6 +6511,7 @@
method public boolean isApplicationHidden(android.content.ComponentName, java.lang.String);
method public boolean isBackupServiceEnabled(android.content.ComponentName);
method public deprecated boolean isCallerApplicationRestrictionsManagingPackage();
+ method public boolean isDeviceIdAttestationSupported();
method public boolean isDeviceOwnerApp(java.lang.String);
method public boolean isEphemeralUser(android.content.ComponentName);
method public boolean isLockTaskPermitted(java.lang.String);
@@ -13657,17 +13658,17 @@
method public static android.graphics.drawable.Drawable decodeDrawable(android.graphics.ImageDecoder.Source, android.graphics.ImageDecoder.OnHeaderDecodedListener) throws java.io.IOException;
method public static android.graphics.drawable.Drawable decodeDrawable(android.graphics.ImageDecoder.Source) throws java.io.IOException;
method public int getAllocator();
- method public boolean getConserveMemory();
method public android.graphics.Rect getCrop();
+ method public int getMemorySizePolicy();
method public android.graphics.ImageDecoder.OnPartialImageListener getOnPartialImageListener();
method public android.graphics.PostProcessor getPostProcessor();
method public boolean isDecodeAsAlphaMaskEnabled();
method public boolean isMutableRequired();
method public boolean isUnpremultipliedRequired();
method public void setAllocator(int);
- method public void setConserveMemory(boolean);
method public void setCrop(android.graphics.Rect);
method public void setDecodeAsAlphaMaskEnabled(boolean);
+ method public void setMemorySizePolicy(int);
method public void setMutableRequired(boolean);
method public void setOnPartialImageListener(android.graphics.ImageDecoder.OnPartialImageListener);
method public void setPostProcessor(android.graphics.PostProcessor);
@@ -13679,6 +13680,8 @@
field public static final int ALLOCATOR_HARDWARE = 3; // 0x3
field public static final int ALLOCATOR_SHARED_MEMORY = 2; // 0x2
field public static final int ALLOCATOR_SOFTWARE = 1; // 0x1
+ field public static final int MEMORY_POLICY_DEFAULT = 1; // 0x1
+ field public static final int MEMORY_POLICY_LOW_RAM = 0; // 0x0
}
public static final class ImageDecoder.DecodeException extends java.io.IOException {
@@ -15755,9 +15758,9 @@
package android.hardware.biometrics {
- public class BiometricDialog {
- method public void authenticate(android.hardware.biometrics.BiometricDialog.CryptoObject, android.os.CancellationSignal, java.util.concurrent.Executor, android.hardware.biometrics.BiometricDialog.AuthenticationCallback);
- method public void authenticate(android.os.CancellationSignal, java.util.concurrent.Executor, android.hardware.biometrics.BiometricDialog.AuthenticationCallback);
+ public class BiometricPrompt {
+ method public void authenticate(android.hardware.biometrics.BiometricPrompt.CryptoObject, android.os.CancellationSignal, java.util.concurrent.Executor, android.hardware.biometrics.BiometricPrompt.AuthenticationCallback);
+ method public void authenticate(android.os.CancellationSignal, java.util.concurrent.Executor, android.hardware.biometrics.BiometricPrompt.AuthenticationCallback);
field public static final int BIOMETRIC_ACQUIRED_GOOD = 0; // 0x0
field public static final int BIOMETRIC_ACQUIRED_IMAGER_DIRTY = 3; // 0x3
field public static final int BIOMETRIC_ACQUIRED_INSUFFICIENT = 2; // 0x2
@@ -15777,31 +15780,31 @@
field public static final int BIOMETRIC_ERROR_VENDOR = 8; // 0x8
}
- public static abstract class BiometricDialog.AuthenticationCallback {
- ctor public BiometricDialog.AuthenticationCallback();
+ public static abstract class BiometricPrompt.AuthenticationCallback {
+ ctor public BiometricPrompt.AuthenticationCallback();
method public void onAuthenticationError(int, java.lang.CharSequence);
method public void onAuthenticationFailed();
method public void onAuthenticationHelp(int, java.lang.CharSequence);
- method public void onAuthenticationSucceeded(android.hardware.biometrics.BiometricDialog.AuthenticationResult);
+ method public void onAuthenticationSucceeded(android.hardware.biometrics.BiometricPrompt.AuthenticationResult);
}
- public static class BiometricDialog.AuthenticationResult {
- method public android.hardware.biometrics.BiometricDialog.CryptoObject getCryptoObject();
+ public static class BiometricPrompt.AuthenticationResult {
+ method public android.hardware.biometrics.BiometricPrompt.CryptoObject getCryptoObject();
}
- public static class BiometricDialog.Builder {
- ctor public BiometricDialog.Builder(android.content.Context);
- method public android.hardware.biometrics.BiometricDialog build();
- method public android.hardware.biometrics.BiometricDialog.Builder setDescription(java.lang.CharSequence);
- method public android.hardware.biometrics.BiometricDialog.Builder setNegativeButton(java.lang.CharSequence, java.util.concurrent.Executor, android.content.DialogInterface.OnClickListener);
- method public android.hardware.biometrics.BiometricDialog.Builder setSubtitle(java.lang.CharSequence);
- method public android.hardware.biometrics.BiometricDialog.Builder setTitle(java.lang.CharSequence);
+ public static class BiometricPrompt.Builder {
+ ctor public BiometricPrompt.Builder(android.content.Context);
+ method public android.hardware.biometrics.BiometricPrompt build();
+ method public android.hardware.biometrics.BiometricPrompt.Builder setDescription(java.lang.CharSequence);
+ method public android.hardware.biometrics.BiometricPrompt.Builder setNegativeButton(java.lang.CharSequence, java.util.concurrent.Executor, android.content.DialogInterface.OnClickListener);
+ method public android.hardware.biometrics.BiometricPrompt.Builder setSubtitle(java.lang.CharSequence);
+ method public android.hardware.biometrics.BiometricPrompt.Builder setTitle(java.lang.CharSequence);
}
- public static final class BiometricDialog.CryptoObject {
- ctor public BiometricDialog.CryptoObject(java.security.Signature);
- ctor public BiometricDialog.CryptoObject(javax.crypto.Cipher);
- ctor public BiometricDialog.CryptoObject(javax.crypto.Mac);
+ public static final class BiometricPrompt.CryptoObject {
+ ctor public BiometricPrompt.CryptoObject(java.security.Signature);
+ ctor public BiometricPrompt.CryptoObject(javax.crypto.Cipher);
+ ctor public BiometricPrompt.CryptoObject(javax.crypto.Mac);
method public javax.crypto.Cipher getCipher();
method public javax.crypto.Mac getMac();
method public java.security.Signature getSignature();
@@ -23165,6 +23168,7 @@
field public static final int AACObjectMain = 1; // 0x1
field public static final int AACObjectSSR = 3; // 0x3
field public static final int AACObjectScalable = 6; // 0x6
+ field public static final int AACObjectXHE = 42; // 0x2a
field public static final int AVCLevel1 = 1; // 0x1
field public static final int AVCLevel11 = 4; // 0x4
field public static final int AVCLevel12 = 8; // 0x8
@@ -33158,6 +33162,7 @@
method public android.os.StrictMode.VmPolicy.Builder detectLeakedClosableObjects();
method public android.os.StrictMode.VmPolicy.Builder detectLeakedRegistrationObjects();
method public android.os.StrictMode.VmPolicy.Builder detectLeakedSqlLiteObjects();
+ method public android.os.StrictMode.VmPolicy.Builder detectNonSdkApiUsage();
method public android.os.StrictMode.VmPolicy.Builder detectUntaggedSockets();
method public android.os.StrictMode.VmPolicy.Builder penaltyDeath();
method public android.os.StrictMode.VmPolicy.Builder penaltyDeathOnCleartextNetwork();
@@ -33165,6 +33170,7 @@
method public android.os.StrictMode.VmPolicy.Builder penaltyDropBox();
method public android.os.StrictMode.VmPolicy.Builder penaltyListener(java.util.concurrent.Executor, android.os.StrictMode.OnVmViolationListener);
method public android.os.StrictMode.VmPolicy.Builder penaltyLog();
+ method public android.os.StrictMode.VmPolicy.Builder permitNonSdkApiUsage();
method public android.os.StrictMode.VmPolicy.Builder setClassInstanceLimit(java.lang.Class, int);
}
@@ -33579,6 +33585,9 @@
public final class NetworkViolation extends android.os.strictmode.Violation {
}
+ public final class NonSdkApiUsedViolation extends android.os.strictmode.Violation {
+ }
+
public final class ResourceMismatchViolation extends android.os.strictmode.Violation {
}
@@ -36677,6 +36686,7 @@
field public static final java.lang.String PARENTAL_CONTROL_ENABLED = "parental_control_enabled";
field public static final java.lang.String PARENTAL_CONTROL_LAST_UPDATE = "parental_control_last_update";
field public static final java.lang.String PARENTAL_CONTROL_REDIRECT_URL = "parental_control_redirect_url";
+ field public static final java.lang.String RTT_CALLING_MODE = "rtt_calling_mode";
field public static final java.lang.String SELECTED_INPUT_METHOD_SUBTYPE = "selected_input_method_subtype";
field public static final java.lang.String SETTINGS_CLASSNAME = "settings_classname";
field public static final java.lang.String SKIP_FIRST_USE_HINTS = "skip_first_use_hints";
@@ -36782,7 +36792,6 @@
field public static final deprecated java.lang.String RADIO_NFC = "nfc";
field public static final deprecated java.lang.String RADIO_WIFI = "wifi";
field public static final java.lang.String RINGTONE = "ringtone";
- field public static final java.lang.String RTT_CALLING_MODE = "rtt_calling_mode";
field public static final java.lang.String SCREEN_BRIGHTNESS = "screen_brightness";
field public static final java.lang.String SCREEN_BRIGHTNESS_MODE = "screen_brightness_mode";
field public static final int SCREEN_BRIGHTNESS_MODE_AUTOMATIC = 1; // 0x1
@@ -38454,23 +38463,10 @@
public abstract class ConfirmationCallback {
ctor public ConfirmationCallback();
- method public void onConfirmedByUser(byte[]);
- method public void onDismissedByApplication();
- method public void onDismissedByUser();
- method public void onError(java.lang.Exception);
- }
-
- public class ConfirmationDialog {
- method public void cancelPrompt();
- method public static boolean isSupported();
- method public void presentPrompt(java.util.concurrent.Executor, android.security.ConfirmationCallback) throws android.security.ConfirmationAlreadyPresentingException, android.security.ConfirmationNotAvailableException;
- }
-
- public static class ConfirmationDialog.Builder {
- ctor public ConfirmationDialog.Builder();
- method public android.security.ConfirmationDialog build(android.content.Context);
- method public android.security.ConfirmationDialog.Builder setExtraData(byte[]);
- method public android.security.ConfirmationDialog.Builder setPromptText(java.lang.CharSequence);
+ method public void onCanceled();
+ method public void onConfirmed(byte[]);
+ method public void onDismissed();
+ method public void onError(java.lang.Throwable);
}
public class ConfirmationNotAvailableException extends java.lang.Exception {
@@ -38478,6 +38474,19 @@
ctor public ConfirmationNotAvailableException(java.lang.String);
}
+ public class ConfirmationPrompt {
+ method public void cancelPrompt();
+ method public static boolean isSupported(android.content.Context);
+ method public void presentPrompt(java.util.concurrent.Executor, android.security.ConfirmationCallback) throws android.security.ConfirmationAlreadyPresentingException, android.security.ConfirmationNotAvailableException;
+ }
+
+ public static final class ConfirmationPrompt.Builder {
+ ctor public ConfirmationPrompt.Builder(android.content.Context);
+ method public android.security.ConfirmationPrompt build();
+ method public android.security.ConfirmationPrompt.Builder setExtraData(byte[]);
+ method public android.security.ConfirmationPrompt.Builder setPromptText(java.lang.CharSequence);
+ }
+
public final class KeyChain {
ctor public KeyChain();
method public static void choosePrivateKeyAlias(android.app.Activity, android.security.KeyChainAliasCallback, java.lang.String[], java.security.Principal[], java.lang.String, int, java.lang.String);
@@ -38753,7 +38762,7 @@
ctor public UserNotAuthenticatedException(java.lang.String, java.lang.Throwable);
}
- public class UserPresenceUnavailableException extends java.security.InvalidAlgorithmParameterException {
+ public class UserPresenceUnavailableException extends java.security.InvalidKeyException {
ctor public UserPresenceUnavailableException();
ctor public UserPresenceUnavailableException(java.lang.String);
ctor public UserPresenceUnavailableException(java.lang.String, java.lang.Throwable);
@@ -50539,7 +50548,7 @@
method public static android.view.textclassifier.TextClassifier.EntityConfig createWithHints(java.util.Collection<java.lang.String>);
method public int describeContents();
method public java.util.Collection<java.lang.String> getHints();
- method public java.util.List<java.lang.String> resolveEntityListModifications(java.util.Collection<java.lang.String>);
+ method public java.util.Collection<java.lang.String> resolveEntityListModifications(java.util.Collection<java.lang.String>);
method public void writeToParcel(android.os.Parcel, int);
field public static final android.os.Parcelable.Creator<android.view.textclassifier.TextClassifier.EntityConfig> CREATOR;
}
diff --git a/api/removed.txt b/api/removed.txt
index af2b25e..1d6a8c2 100644
--- a/api/removed.txt
+++ b/api/removed.txt
@@ -178,10 +178,12 @@
public final class ImageDecoder implements java.lang.AutoCloseable {
method public deprecated boolean getAsAlphaMask();
+ method public deprecated boolean getConserveMemory();
method public deprecated boolean getDecodeAsAlphaMask();
method public deprecated boolean getMutable();
method public deprecated boolean getRequireUnpremultiplied();
method public deprecated android.graphics.ImageDecoder setAsAlphaMask(boolean);
+ method public deprecated void setConserveMemory(boolean);
method public deprecated android.graphics.ImageDecoder setDecodeAsAlphaMask(boolean);
method public deprecated android.graphics.ImageDecoder setMutable(boolean);
method public deprecated android.graphics.ImageDecoder setRequireUnpremultiplied(boolean);
diff --git a/api/system-current.txt b/api/system-current.txt
index c85e2d3..4260e40 100644
--- a/api/system-current.txt
+++ b/api/system-current.txt
@@ -163,6 +163,7 @@
field public static final java.lang.String REVOKE_RUNTIME_PERMISSIONS = "android.permission.REVOKE_RUNTIME_PERMISSIONS";
field public static final java.lang.String SCORE_NETWORKS = "android.permission.SCORE_NETWORKS";
field public static final java.lang.String SEND_RESPOND_VIA_MESSAGE = "android.permission.SEND_RESPOND_VIA_MESSAGE";
+ field public static final java.lang.String SEND_SHOW_SUSPENDED_APP_DETAILS = "android.permission.SEND_SHOW_SUSPENDED_APP_DETAILS";
field public static final java.lang.String SEND_SMS_NO_CONFIRMATION = "android.permission.SEND_SMS_NO_CONFIRMATION";
field public static final java.lang.String SERIAL_PORT = "android.permission.SERIAL_PORT";
field public static final java.lang.String SET_ACTIVITY_WATCHER = "android.permission.SET_ACTIVITY_WATCHER";
@@ -878,6 +879,7 @@
field public static final java.lang.String ACTION_QUERY_PACKAGE_RESTART = "android.intent.action.QUERY_PACKAGE_RESTART";
field public static final java.lang.String ACTION_RESOLVE_INSTANT_APP_PACKAGE = "android.intent.action.RESOLVE_INSTANT_APP_PACKAGE";
field public static final java.lang.String ACTION_REVIEW_PERMISSIONS = "android.intent.action.REVIEW_PERMISSIONS";
+ field public static final java.lang.String ACTION_SHOW_SUSPENDED_APP_DETAILS = "android.intent.action.SHOW_SUSPENDED_APP_DETAILS";
field public static final deprecated java.lang.String ACTION_SIM_STATE_CHANGED = "android.intent.action.SIM_STATE_CHANGED";
field public static final java.lang.String ACTION_SPLIT_CONFIGURATION_CHANGED = "android.intent.action.SPLIT_CONFIGURATION_CHANGED";
field public static final java.lang.String ACTION_UPGRADE_SETUP = "android.intent.action.UPGRADE_SETUP";
@@ -3081,10 +3083,10 @@
}
public static final class IpSecManager.IpSecTunnelInterface implements java.lang.AutoCloseable {
- method public void addAddress(android.net.LinkAddress) throws java.io.IOException;
+ method public void addAddress(java.net.InetAddress, int) throws java.io.IOException;
method public void close();
method public java.lang.String getInterfaceName();
- method public void removeAddress(android.net.LinkAddress) throws java.io.IOException;
+ method public void removeAddress(java.net.InetAddress, int) throws java.io.IOException;
}
public final class IpSecTransform implements java.lang.AutoCloseable {
@@ -4759,8 +4761,8 @@
method public final android.view.textclassifier.TextClassifier getLocalTextClassifier();
method public final android.os.IBinder onBind(android.content.Intent);
method public abstract void onClassifyText(android.view.textclassifier.TextClassificationSessionId, android.view.textclassifier.TextClassification.Request, android.os.CancellationSignal, android.service.textclassifier.TextClassifierService.Callback<android.view.textclassifier.TextClassification>);
- method public abstract void onCreateTextClassificationSession(android.view.textclassifier.TextClassificationContext, android.view.textclassifier.TextClassificationSessionId);
- method public abstract void onDestroyTextClassificationSession(android.view.textclassifier.TextClassificationSessionId);
+ method public void onCreateTextClassificationSession(android.view.textclassifier.TextClassificationContext, android.view.textclassifier.TextClassificationSessionId);
+ method public void onDestroyTextClassificationSession(android.view.textclassifier.TextClassificationSessionId);
method public abstract void onGenerateLinks(android.view.textclassifier.TextClassificationSessionId, android.view.textclassifier.TextLinks.Request, android.os.CancellationSignal, android.service.textclassifier.TextClassifierService.Callback<android.view.textclassifier.TextLinks>);
method public void onSelectionEvent(android.view.textclassifier.TextClassificationSessionId, android.view.textclassifier.SelectionEvent);
method public abstract void onSuggestSelection(android.view.textclassifier.TextClassificationSessionId, android.view.textclassifier.TextSelection.Request, android.os.CancellationSignal, android.service.textclassifier.TextClassifierService.Callback<android.view.textclassifier.TextSelection>);
@@ -5106,6 +5108,7 @@
}
public abstract class NetworkService extends android.app.Service {
+ ctor public NetworkService();
method protected abstract android.telephony.NetworkService.NetworkServiceProvider createNetworkServiceProvider(int);
field public static final java.lang.String NETWORK_SERVICE_EXTRA_SLOT_ID = "android.telephony.extra.SLOT_ID";
field public static final java.lang.String NETWORK_SERVICE_INTERFACE = "android.telephony.NetworkService";
@@ -5387,6 +5390,7 @@
}
public abstract class DataService extends android.app.Service {
+ ctor public DataService();
method public abstract android.telephony.data.DataService.DataServiceProvider createDataServiceProvider(int);
field public static final java.lang.String DATA_SERVICE_EXTRA_SLOT_ID = "android.telephony.data.extra.SLOT_ID";
field public static final java.lang.String DATA_SERVICE_INTERFACE = "android.telephony.data.DataService";
diff --git a/api/test-current.txt b/api/test-current.txt
index 9f5fa0c..4878690 100644
--- a/api/test-current.txt
+++ b/api/test-current.txt
@@ -467,6 +467,14 @@
}
+package android.media.audiofx {
+
+ public class AudioEffect {
+ field public static final java.util.UUID EFFECT_TYPE_NULL;
+ }
+
+}
+
package android.net {
public final class IpSecManager {
@@ -527,6 +535,7 @@
field public static final int DETECT_VM_CURSOR_LEAKS = 256; // 0x100
field public static final int DETECT_VM_FILE_URI_EXPOSURE = 8192; // 0x2000
field public static final int DETECT_VM_INSTANCE_LEAKS = 2048; // 0x800
+ field public static final int DETECT_VM_NON_SDK_API_USAGE = 1073741824; // 0x40000000
field public static final int DETECT_VM_REGISTRATION_LEAKS = 4096; // 0x1000
field public static final int DETECT_VM_UNTAGGED_SOCKET = -2147483648; // 0x80000000
}
diff --git a/cmds/incidentd/src/PrivacyBuffer.cpp b/cmds/incidentd/src/PrivacyBuffer.cpp
index 6cd2fe1..d753e5e 100644
--- a/cmds/incidentd/src/PrivacyBuffer.cpp
+++ b/cmds/incidentd/src/PrivacyBuffer.cpp
@@ -34,7 +34,7 @@
void PrivacyBuffer::writeFieldOrSkip(uint32_t fieldTag, bool skip) {
uint8_t wireType = read_wire_type(fieldTag);
size_t bytesToWrite = 0;
- uint32_t varint = 0;
+ uint64_t varint = 0;
switch (wireType) {
case WIRE_TYPE_VARINT:
diff --git a/cmds/incidentd/src/Section.h b/cmds/incidentd/src/Section.h
index 34a3613..20ecdb1 100644
--- a/cmds/incidentd/src/Section.h
+++ b/cmds/incidentd/src/Section.h
@@ -31,7 +31,7 @@
namespace os {
namespace incidentd {
-const int64_t REMOTE_CALL_TIMEOUT_MS = 10 * 1000; // 10 seconds
+const int64_t REMOTE_CALL_TIMEOUT_MS = 30 * 1000; // 30 seconds
/**
* Base class for sections
diff --git a/cmds/statsd/Android.mk b/cmds/statsd/Android.mk
index 7723615..8e46714 100644
--- a/cmds/statsd/Android.mk
+++ b/cmds/statsd/Android.mk
@@ -209,7 +209,9 @@
tests/e2e/DimensionInCondition_e2e_combination_OR_cond_test.cpp \
tests/e2e/DimensionInCondition_e2e_simple_cond_test.cpp \
tests/e2e/Anomaly_count_e2e_test.cpp \
- tests/e2e/Anomaly_duration_sum_e2e_test.cpp
+ tests/e2e/Anomaly_duration_sum_e2e_test.cpp \
+ tests/e2e/ConfigTtl_e2e_test.cpp \
+ tests/e2e/PartialBucket_e2e_test.cpp
LOCAL_STATIC_LIBRARIES := \
$(statsd_common_static_libraries) \
diff --git a/cmds/statsd/benchmark/metric_util.cpp b/cmds/statsd/benchmark/metric_util.cpp
index fae186a..7d6c47b 100644
--- a/cmds/statsd/benchmark/metric_util.cpp
+++ b/cmds/statsd/benchmark/metric_util.cpp
@@ -366,7 +366,7 @@
sp<AlarmMonitor> periodicAlarmMonitor;
sp<StatsLogProcessor> processor = new StatsLogProcessor(
uidMap, anomalyAlarmMonitor, periodicAlarmMonitor, timeBaseSec, [](const ConfigKey&){});
- processor->OnConfigUpdated(0, key, config);
+ processor->OnConfigUpdated(timeBaseSec * NS_PER_SEC, key, config);
return processor;
}
diff --git a/cmds/statsd/src/StatsLogProcessor.cpp b/cmds/statsd/src/StatsLogProcessor.cpp
index f00cdb3..90ce735 100644
--- a/cmds/statsd/src/StatsLogProcessor.cpp
+++ b/cmds/statsd/src/StatsLogProcessor.cpp
@@ -65,6 +65,7 @@
const int FIELD_ID_LAST_REPORT_WALL_CLOCK_NANOS = 5;
const int FIELD_ID_CURRENT_REPORT_WALL_CLOCK_NANOS = 6;
+#define NS_PER_HOUR 3600 * NS_PER_SEC
#define STATS_DATA_DIR "/data/misc/stats-data"
@@ -85,7 +86,7 @@
}
void StatsLogProcessor::onAnomalyAlarmFired(
- const uint64_t& timestampNs,
+ const int64_t& timestampNs,
unordered_set<sp<const InternalAlarm>, SpHash<InternalAlarm>> alarmSet) {
std::lock_guard<std::mutex> lock(mMetricsMutex);
for (const auto& itr : mMetricsManagers) {
@@ -93,7 +94,7 @@
}
}
void StatsLogProcessor::onPeriodicAlarmFired(
- const uint64_t& timestampNs,
+ const int64_t& timestampNs,
unordered_set<sp<const InternalAlarm>, SpHash<InternalAlarm>> alarmSet) {
std::lock_guard<std::mutex> lock(mMetricsMutex);
@@ -156,10 +157,17 @@
void StatsLogProcessor::OnLogEvent(LogEvent* event) {
std::lock_guard<std::mutex> lock(mMetricsMutex);
- if (event->GetElapsedTimestampNs() < mLastLogTimestamp) {
+ const int64_t currentTimestampNs = event->GetElapsedTimestampNs();
+
+ if (currentTimestampNs < mLastLogTimestamp) {
+ StatsdStats::getInstance().noteLogEventSkipped(
+ event->GetTagId(), event->GetElapsedTimestampNs());
return;
}
- mLastLogTimestamp = event->GetElapsedTimestampNs();
+
+ resetIfConfigTtlExpiredLocked(currentTimestampNs);
+
+ mLastLogTimestamp = currentTimestampNs;
StatsdStats::getInstance().noteAtomLogged(
event->GetTagId(), event->GetElapsedTimestampNs() / NS_PER_SEC);
@@ -173,12 +181,13 @@
return;
}
- uint64_t curTimeSec = getElapsedRealtimeSec();
+ int64_t curTimeSec = getElapsedRealtimeSec();
if (curTimeSec - mLastPullerCacheClearTimeSec > StatsdStats::kPullerCacheClearIntervalSec) {
mStatsPullerManager.ClearPullerCacheIfNecessary(curTimeSec * NS_PER_SEC);
mLastPullerCacheClearTimeSec = curTimeSec;
}
+
if (event->GetTagId() != android::util::ISOLATED_UID_CHANGED) {
// Map the isolated uid to host uid if necessary.
mapIsolatedUidToHostUidIfNecessaryLocked(event);
@@ -194,11 +203,19 @@
void StatsLogProcessor::OnConfigUpdated(const int64_t timestampNs, const ConfigKey& key,
const StatsdConfig& config) {
std::lock_guard<std::mutex> lock(mMetricsMutex);
+ OnConfigUpdatedLocked(timestampNs, key, config);
+}
+
+void StatsLogProcessor::OnConfigUpdatedLocked(
+ const int64_t timestampNs, const ConfigKey& key, const StatsdConfig& config) {
VLOG("Updated configuration for key %s", key.ToString().c_str());
sp<MetricsManager> newMetricsManager =
new MetricsManager(key, config, mTimeBaseSec, (timestampNs - 1) / NS_PER_SEC + 1, mUidMap,
mAnomalyAlarmMonitor, mPeriodicAlarmMonitor);
-
+ auto it = mMetricsManagers.find(key);
+ if (it != mMetricsManagers.end()) {
+ WriteDataToDiskLocked(it->first);
+ }
if (newMetricsManager->isConfigValid()) {
mUidMap->OnConfigUpdated(key);
if (newMetricsManager->shouldAddUidMapListener()) {
@@ -206,6 +223,7 @@
// not safe to create wp or sp from this pointer inside its constructor.
mUidMap->addListener(newMetricsManager.get());
}
+ newMetricsManager->refreshTtl(timestampNs);
mMetricsManagers[key] = newMetricsManager;
VLOG("StatsdConfig valid");
} else {
@@ -235,20 +253,11 @@
/*
* onDumpReport dumps serialized ConfigMetricsReportList into outData.
*/
-void StatsLogProcessor::onDumpReport(const ConfigKey& key, const uint64_t dumpTimeStampNs,
+void StatsLogProcessor::onDumpReport(const ConfigKey& key, const int64_t dumpTimeStampNs,
+ const bool include_current_partial_bucket,
vector<uint8_t>* outData) {
std::lock_guard<std::mutex> lock(mMetricsMutex);
- auto it = mMetricsManagers.find(key);
- if (it == mMetricsManagers.end()) {
- ALOGW("Config source %s does not exist", key.ToString().c_str());
- return;
- }
-
- // This allows another broadcast to be sent within the rate-limit period if we get close to
- // filling the buffer again soon.
- mLastBroadcastTimes.erase(key);
-
ProtoOutputStream proto;
// Start of ConfigKey.
@@ -258,18 +267,26 @@
proto.end(configKeyToken);
// End of ConfigKey.
- // Start of ConfigMetricsReport (reports).
- uint64_t reportsToken =
- proto.start(FIELD_TYPE_MESSAGE | FIELD_COUNT_REPEATED | FIELD_ID_REPORTS);
- onConfigMetricsReportLocked(key, dumpTimeStampNs, &proto);
- proto.end(reportsToken);
- // End of ConfigMetricsReport (reports).
-
-
// Then, check stats-data directory to see there's any file containing
// ConfigMetricsReport from previous shutdowns to concatenate to reports.
StorageManager::appendConfigMetricsReport(key, &proto);
+ auto it = mMetricsManagers.find(key);
+ if (it != mMetricsManagers.end()) {
+ // This allows another broadcast to be sent within the rate-limit period if we get close to
+ // filling the buffer again soon.
+ mLastBroadcastTimes.erase(key);
+
+ // Start of ConfigMetricsReport (reports).
+ uint64_t reportsToken =
+ proto.start(FIELD_TYPE_MESSAGE | FIELD_COUNT_REPEATED | FIELD_ID_REPORTS);
+ onConfigMetricsReportLocked(key, dumpTimeStampNs, include_current_partial_bucket, &proto);
+ proto.end(reportsToken);
+ // End of ConfigMetricsReport (reports).
+ } else {
+ ALOGW("Config source %s does not exist", key.ToString().c_str());
+ }
+
if (outData != nullptr) {
outData->clear();
outData->resize(proto.size());
@@ -283,28 +300,32 @@
}
}
- StatsdStats::getInstance().noteMetricsReportSent(key);
+ StatsdStats::getInstance().noteMetricsReportSent(key, proto.size());
}
/*
* onConfigMetricsReportLocked dumps serialized ConfigMetricsReport into outData.
*/
void StatsLogProcessor::onConfigMetricsReportLocked(const ConfigKey& key,
- const uint64_t dumpTimeStampNs,
+ const int64_t dumpTimeStampNs,
+ const bool include_current_partial_bucket,
ProtoOutputStream* proto) {
// We already checked whether key exists in mMetricsManagers in
// WriteDataToDisk.
auto it = mMetricsManagers.find(key);
+ if (it == mMetricsManagers.end()) {
+ return;
+ }
int64_t lastReportTimeNs = it->second->getLastReportTimeNs();
int64_t lastReportWallClockNs = it->second->getLastReportWallClockNs();
// First, fill in ConfigMetricsReport using current data on memory, which
// starts from filling in StatsLogReport's.
- it->second->onDumpReport(dumpTimeStampNs, proto);
+ it->second->onDumpReport(dumpTimeStampNs, include_current_partial_bucket, proto);
// Fill in UidMap.
uint64_t uidMapToken = proto->start(FIELD_TYPE_MESSAGE | FIELD_ID_UID_MAP);
- mUidMap->appendUidMap(key, proto);
+ mUidMap->appendUidMap(dumpTimeStampNs, key, proto);
proto->end(uidMapToken);
// Fill in the timestamps.
@@ -316,14 +337,36 @@
(long long)lastReportWallClockNs);
proto->write(FIELD_TYPE_INT64 | FIELD_ID_CURRENT_REPORT_WALL_CLOCK_NANOS,
(long long)getWallClockNs());
+}
+void StatsLogProcessor::resetIfConfigTtlExpiredLocked(const int64_t timestampNs) {
+ std::vector<ConfigKey> configKeysTtlExpired;
+ for (auto it = mMetricsManagers.begin(); it != mMetricsManagers.end(); it++) {
+ if (it->second != nullptr && !it->second->isInTtl(timestampNs)) {
+ configKeysTtlExpired.push_back(it->first);
+ }
+ }
+ for (const auto& key : configKeysTtlExpired) {
+ StatsdConfig config;
+ if (StorageManager::readConfigFromDisk(key, &config)) {
+ OnConfigUpdatedLocked(timestampNs, key, config);
+ StatsdStats::getInstance().noteConfigReset(key);
+ } else {
+ ALOGE("Failed to read backup config from disk for : %s", key.ToString().c_str());
+ auto it = mMetricsManagers.find(key);
+ if (it != mMetricsManagers.end()) {
+ it->second->refreshTtl(timestampNs);
+ }
+ }
+ }
}
void StatsLogProcessor::OnConfigRemoved(const ConfigKey& key) {
std::lock_guard<std::mutex> lock(mMetricsMutex);
auto it = mMetricsManagers.find(key);
if (it != mMetricsManagers.end()) {
+ WriteDataToDiskLocked(key);
mMetricsManagers.erase(it);
mUidMap->OnConfigRemoved(key);
}
@@ -337,7 +380,7 @@
}
void StatsLogProcessor::flushIfNecessaryLocked(
- uint64_t timestampNs, const ConfigKey& key, MetricsManager& metricsManager) {
+ int64_t timestampNs, const ConfigKey& key, MetricsManager& metricsManager) {
auto lastCheckTime = mLastByteSizeTimes.find(key);
if (lastCheckTime != mLastByteSizeTimes.end()) {
if (timestampNs - lastCheckTime->second < StatsdStats::kMinByteSizeCheckPeriodNs) {
@@ -369,22 +412,30 @@
}
}
+void StatsLogProcessor::WriteDataToDiskLocked(const ConfigKey& key) {
+ ProtoOutputStream proto;
+ onConfigMetricsReportLocked(key, getElapsedRealtimeNs(),
+ true /* include_current_partial_bucket*/, &proto);
+ string file_name = StringPrintf("%s/%ld_%d_%lld", STATS_DATA_DIR,
+ (long)getWallClockSec(), key.GetUid(), (long long)key.GetId());
+ android::base::unique_fd fd(open(file_name.c_str(),
+ O_WRONLY | O_CREAT | O_CLOEXEC, S_IRUSR | S_IWUSR));
+ if (fd == -1) {
+ ALOGE("Attempt to write %s but failed", file_name.c_str());
+ return;
+ }
+ proto.flush(fd.get());
+}
+
+void StatsLogProcessor::WriteDataToDiskLocked() {
+ for (auto& pair : mMetricsManagers) {
+ WriteDataToDiskLocked(pair.first);
+ }
+}
+
void StatsLogProcessor::WriteDataToDisk() {
std::lock_guard<std::mutex> lock(mMetricsMutex);
- for (auto& pair : mMetricsManagers) {
- const ConfigKey& key = pair.first;
- ProtoOutputStream proto;
- onConfigMetricsReportLocked(key, getElapsedRealtimeNs(), &proto);
- string file_name = StringPrintf("%s/%ld_%d_%lld", STATS_DATA_DIR,
- (long)getWallClockSec(), key.GetUid(), (long long)key.GetId());
- android::base::unique_fd fd(open(file_name.c_str(),
- O_WRONLY | O_CREAT | O_CLOEXEC, S_IRUSR | S_IWUSR));
- if (fd == -1) {
- VLOG("Attempt to write %s but failed", file_name.c_str());
- return;
- }
- proto.flush(fd.get());
- }
+ WriteDataToDiskLocked();
}
} // namespace statsd
diff --git a/cmds/statsd/src/StatsLogProcessor.h b/cmds/statsd/src/StatsLogProcessor.h
index 1c4698f..1e82b1e 100644
--- a/cmds/statsd/src/StatsLogProcessor.h
+++ b/cmds/statsd/src/StatsLogProcessor.h
@@ -48,16 +48,17 @@
size_t GetMetricsSize(const ConfigKey& key) const;
- void onDumpReport(const ConfigKey& key, const uint64_t dumpTimeNs, vector<uint8_t>* outData);
+ void onDumpReport(const ConfigKey& key, const int64_t dumpTimeNs,
+ const bool include_current_partial_bucket, vector<uint8_t>* outData);
/* Tells MetricsManager that the alarms in alarmSet have fired. Modifies anomaly alarmSet. */
void onAnomalyAlarmFired(
- const uint64_t& timestampNs,
+ const int64_t& timestampNs,
unordered_set<sp<const InternalAlarm>, SpHash<InternalAlarm>> alarmSet);
/* Tells MetricsManager that the alarms in alarmSet have fired. Modifies periodic alarmSet. */
void onPeriodicAlarmFired(
- const uint64_t& timestampNs,
+ const int64_t& timestampNs,
unordered_set<sp<const InternalAlarm>, SpHash<InternalAlarm>> alarmSet);
/* Flushes data to disk. Data on memory will be gone after written to disk. */
@@ -69,6 +70,7 @@
void dumpStates(FILE* out, bool verbose);
+
private:
// For testing only.
inline sp<AlarmMonitor> getAnomalyAlarmMonitor() const {
@@ -96,12 +98,21 @@
sp<AlarmMonitor> mPeriodicAlarmMonitor;
- void onConfigMetricsReportLocked(const ConfigKey& key, const uint64_t dumpTimeStampNs,
+ void resetIfConfigTtlExpiredLocked(const int64_t timestampNs);
+
+ void OnConfigUpdatedLocked(
+ const int64_t currentTimestampNs, const ConfigKey& key, const StatsdConfig& config);
+
+ void WriteDataToDiskLocked();
+ void WriteDataToDiskLocked(const ConfigKey& key);
+
+ void onConfigMetricsReportLocked(const ConfigKey& key, const int64_t dumpTimeStampNs,
+ const bool include_current_partial_bucket,
util::ProtoOutputStream* proto);
/* Check if we should send a broadcast if approaching memory limits and if we're over, we
* actually delete the data. */
- void flushIfNecessaryLocked(uint64_t timestampNs, const ConfigKey& key,
+ void flushIfNecessaryLocked(int64_t timestampNs, const ConfigKey& key,
MetricsManager& metricsManager);
// Maps the isolated uid in the log event to host uid if the log event contains uid fields.
@@ -152,7 +163,9 @@
FRIEND_TEST(AnomalyDetectionE2eTest, TestDurationMetric_SUM_single_bucket);
FRIEND_TEST(AnomalyDetectionE2eTest, TestDurationMetric_SUM_multiple_buckets);
FRIEND_TEST(AnomalyDetectionE2eTest, TestDurationMetric_SUM_long_refractory_period);
+
FRIEND_TEST(AlarmE2eTest, TestMultipleAlarms);
+ FRIEND_TEST(ConfigTtlE2eTest, TestCountMetric);
};
} // namespace statsd
diff --git a/cmds/statsd/src/StatsService.cpp b/cmds/statsd/src/StatsService.cpp
index 7b0d5d9..f16109c 100644
--- a/cmds/statsd/src/StatsService.cpp
+++ b/cmds/statsd/src/StatsService.cpp
@@ -501,7 +501,7 @@
if (good) {
vector<uint8_t> data;
mProcessor->onDumpReport(ConfigKey(uid, StrToInt64(name)), getElapsedRealtimeNs(),
- &data);
+ false /* include_current_bucket*/, &data);
// TODO: print the returned StatsLogReport to file instead of printing to logcat.
if (proto) {
for (size_t i = 0; i < data.size(); i ++) {
@@ -640,7 +640,7 @@
"Only system uid can call informAllUidData");
}
- mUidMap->updateMap(uid, version, app);
+ mUidMap->updateMap(getElapsedRealtimeNs(), uid, version, app);
VLOG("StatsService::informAllUidData succeeded");
return Status::ok();
@@ -653,7 +653,7 @@
return Status::fromExceptionCode(Status::EX_SECURITY,
"Only system uid can call informOnePackage");
}
- mUidMap->updateApp(app, uid, version);
+ mUidMap->updateApp(getElapsedRealtimeNs(), app, uid, version);
return Status::ok();
}
@@ -664,7 +664,7 @@
return Status::fromExceptionCode(Status::EX_SECURITY,
"Only system uid can call informOnePackageRemoved");
}
- mUidMap->removeApp(app, uid);
+ mUidMap->removeApp(getElapsedRealtimeNs(), app, uid);
mConfigManager->RemoveConfigs(uid);
return Status::ok();
}
@@ -677,7 +677,7 @@
"Only system uid can call informAnomalyAlarmFired");
}
- uint64_t currentTimeSec = getElapsedRealtimeSec();
+ int64_t currentTimeSec = getElapsedRealtimeSec();
std::unordered_set<sp<const InternalAlarm>, SpHash<InternalAlarm>> alarmSet =
mAnomalyAlarmMonitor->popSoonerThan(static_cast<uint32_t>(currentTimeSec));
if (alarmSet.size() > 0) {
@@ -698,7 +698,7 @@
"Only system uid can call informAlarmForSubscriberTriggeringFired");
}
- uint64_t currentTimeSec = getElapsedRealtimeSec();
+ int64_t currentTimeSec = getElapsedRealtimeSec();
std::unordered_set<sp<const InternalAlarm>, SpHash<InternalAlarm>> alarmSet =
mPeriodicAlarmMonitor->popSoonerThan(static_cast<uint32_t>(currentTimeSec));
if (alarmSet.size() > 0) {
@@ -800,7 +800,8 @@
VLOG("StatsService::getData with Pid %i, Uid %i", ipc->getCallingPid(), ipc->getCallingUid());
if (checkCallingPermission(String16(kPermissionDump))) {
ConfigKey configKey(ipc->getCallingUid(), key);
- mProcessor->onDumpReport(configKey, getElapsedRealtimeNs(), output);
+ mProcessor->onDumpReport(configKey, getElapsedRealtimeNs(),
+ false /* include_current_bucket*/, output);
return Status::ok();
} else {
return Status::fromExceptionCode(binder::Status::EX_SECURITY);
diff --git a/cmds/statsd/src/StatsService.h b/cmds/statsd/src/StatsService.h
index 8d2fd33..a4552e1 100644
--- a/cmds/statsd/src/StatsService.h
+++ b/cmds/statsd/src/StatsService.h
@@ -262,6 +262,10 @@
FRIEND_TEST(StatsServiceTest, TestAddConfig_simple);
FRIEND_TEST(StatsServiceTest, TestAddConfig_empty);
FRIEND_TEST(StatsServiceTest, TestAddConfig_invalid);
+ FRIEND_TEST(PartialBucketE2eTest, TestCountMetricNoSplitOnNewApp);
+ FRIEND_TEST(PartialBucketE2eTest, TestCountMetricSplitOnUpgrade);
+ FRIEND_TEST(PartialBucketE2eTest, TestCountMetricSplitOnRemoval);
+ FRIEND_TEST(PartialBucketE2eTest, TestCountMetricWithoutSplit);
};
} // namespace statsd
diff --git a/cmds/statsd/src/anomaly/AlarmTracker.cpp b/cmds/statsd/src/anomaly/AlarmTracker.cpp
index 70e6e84..c8e406f 100644
--- a/cmds/statsd/src/anomaly/AlarmTracker.cpp
+++ b/cmds/statsd/src/anomaly/AlarmTracker.cpp
@@ -30,8 +30,8 @@
namespace os {
namespace statsd {
-AlarmTracker::AlarmTracker(const uint64_t startMillis,
- const uint64_t currentMillis,
+AlarmTracker::AlarmTracker(const int64_t startMillis,
+ const int64_t currentMillis,
const Alarm& alarm, const ConfigKey& configKey,
const sp<AlarmMonitor>& alarmMonitor)
: mAlarmConfig(alarm),
@@ -70,7 +70,7 @@
}
void AlarmTracker::informAlarmsFired(
- const uint64_t& timestampNs,
+ const int64_t& timestampNs,
unordered_set<sp<const InternalAlarm>, SpHash<InternalAlarm>>& firedAlarms) {
if (firedAlarms.empty() || mInternalAlarm == nullptr ||
firedAlarms.find(mInternalAlarm) == firedAlarms.end()) {
diff --git a/cmds/statsd/src/anomaly/AlarmTracker.h b/cmds/statsd/src/anomaly/AlarmTracker.h
index 962a014..2fb3e3b 100644
--- a/cmds/statsd/src/anomaly/AlarmTracker.h
+++ b/cmds/statsd/src/anomaly/AlarmTracker.h
@@ -34,8 +34,8 @@
class AlarmTracker : public virtual RefBase {
public:
- AlarmTracker(const uint64_t startMillis,
- const uint64_t currentMillis,
+ AlarmTracker(const int64_t startMillis,
+ const int64_t currentMillis,
const Alarm& alarm, const ConfigKey& configKey,
const sp<AlarmMonitor>& subscriberAlarmMonitor);
@@ -45,12 +45,12 @@
void addSubscription(const Subscription& subscription);
- void informAlarmsFired(const uint64_t& timestampNs,
+ void informAlarmsFired(const int64_t& timestampNs,
unordered_set<sp<const InternalAlarm>, SpHash<InternalAlarm>>& firedAlarms);
protected:
// For test only. Returns the alarm timestamp in seconds. Otherwise returns 0.
- inline uint32_t getAlarmTimestampSec() const {
+ inline int32_t getAlarmTimestampSec() const {
return mInternalAlarm == nullptr ? 0 : mInternalAlarm->timestampSec;
}
diff --git a/cmds/statsd/src/anomaly/AnomalyTracker.cpp b/cmds/statsd/src/anomaly/AnomalyTracker.cpp
index f0960e3..f32efee 100644
--- a/cmds/statsd/src/anomaly/AnomalyTracker.cpp
+++ b/cmds/statsd/src/anomaly/AnomalyTracker.cpp
@@ -207,7 +207,7 @@
getSumOverPastBuckets(key) + currentBucketValue > mAlert.trigger_if_sum_gt();
}
-void AnomalyTracker::declareAnomaly(const uint64_t& timestampNs, const MetricDimensionKey& key) {
+void AnomalyTracker::declareAnomaly(const int64_t& timestampNs, const MetricDimensionKey& key) {
// TODO: Why receive timestamp? RefractoryPeriod should always be based on real time right now.
if (isInRefractoryPeriod(timestampNs, key)) {
VLOG("Skipping anomaly declaration since within refractory period");
@@ -235,7 +235,7 @@
mConfigKey.GetId(), mAlert.id());
}
-void AnomalyTracker::detectAndDeclareAnomaly(const uint64_t& timestampNs,
+void AnomalyTracker::detectAndDeclareAnomaly(const int64_t& timestampNs,
const int64_t& currBucketNum,
const MetricDimensionKey& key,
const int64_t& currentBucketValue) {
@@ -244,11 +244,11 @@
}
}
-bool AnomalyTracker::isInRefractoryPeriod(const uint64_t& timestampNs,
+bool AnomalyTracker::isInRefractoryPeriod(const int64_t& timestampNs,
const MetricDimensionKey& key) const {
const auto& it = mRefractoryPeriodEndsSec.find(key);
if (it != mRefractoryPeriodEndsSec.end()) {
- return timestampNs < it->second * NS_PER_SEC;
+ return timestampNs < (it->second * (int64_t)NS_PER_SEC);
}
return false;
}
diff --git a/cmds/statsd/src/anomaly/AnomalyTracker.h b/cmds/statsd/src/anomaly/AnomalyTracker.h
index 15671a6..927e2df 100644
--- a/cmds/statsd/src/anomaly/AnomalyTracker.h
+++ b/cmds/statsd/src/anomaly/AnomalyTracker.h
@@ -67,13 +67,13 @@
const int64_t& currentBucketValue);
// Informs incidentd about the detected alert.
- void declareAnomaly(const uint64_t& timestampNs, const MetricDimensionKey& key);
+ void declareAnomaly(const int64_t& timestampNs, const MetricDimensionKey& key);
// Detects if, based on past buckets plus the new currentBucketValue (which generally
// represents the partially-filled current bucket), an anomaly has happened, and if so,
// declares an anomaly and informs relevant subscribers.
// Also advances to currBucketNum-1.
- void detectAndDeclareAnomaly(const uint64_t& timestampNs, const int64_t& currBucketNum,
+ void detectAndDeclareAnomaly(const int64_t& timestampNs, const int64_t& currBucketNum,
const MetricDimensionKey& key, const int64_t& currentBucketValue);
// Init the AlarmMonitor which is shared across anomaly trackers.
@@ -107,7 +107,7 @@
// Declares an anomaly for each alarm in firedAlarms that belongs to this AnomalyTracker,
// and removes it from firedAlarms. Does NOT remove the alarm from the AlarmMonitor.
- virtual void informAlarmsFired(const uint64_t& timestampNs,
+ virtual void informAlarmsFired(const int64_t& timestampNs,
unordered_set<sp<const InternalAlarm>, SpHash<InternalAlarm>>& firedAlarms) {
return; // The base AnomalyTracker class doesn't have alarms.
}
@@ -166,7 +166,7 @@
void subtractValueFromSum(const MetricDimensionKey& key, const int64_t& bucketValue);
// Returns true if in the refractory period, else false.
- bool isInRefractoryPeriod(const uint64_t& timestampNs, const MetricDimensionKey& key) const;
+ bool isInRefractoryPeriod(const int64_t& timestampNs, const MetricDimensionKey& key) const;
// Calculates the corresponding bucket index within the circular array.
// Requires bucketNum >= 0.
diff --git a/cmds/statsd/src/anomaly/DurationAnomalyTracker.cpp b/cmds/statsd/src/anomaly/DurationAnomalyTracker.cpp
index cdc4251..3acfd17 100644
--- a/cmds/statsd/src/anomaly/DurationAnomalyTracker.cpp
+++ b/cmds/statsd/src/anomaly/DurationAnomalyTracker.cpp
@@ -36,7 +36,7 @@
}
void DurationAnomalyTracker::startAlarm(const MetricDimensionKey& dimensionKey,
- const uint64_t& timestampNs) {
+ const int64_t& timestampNs) {
// Alarms are stored in secs. Must round up, since if it fires early, it is ignored completely.
uint32_t timestampSec = static_cast<uint32_t>((timestampNs -1) / NS_PER_SEC) + 1; // round up
if (isInRefractoryPeriod(timestampNs, dimensionKey)) {
@@ -57,14 +57,14 @@
}
void DurationAnomalyTracker::stopAlarm(const MetricDimensionKey& dimensionKey,
- const uint64_t& timestampNs) {
+ const int64_t& timestampNs) {
const auto itr = mAlarms.find(dimensionKey);
if (itr == mAlarms.end()) {
return;
}
// If the alarm is set in the past but hasn't fired yet (due to lag), catch it now.
- if (itr->second != nullptr && timestampNs >= NS_PER_SEC * itr->second->timestampSec) {
+ if (itr->second != nullptr && timestampNs >= (int64_t)NS_PER_SEC * itr->second->timestampSec) {
declareAnomaly(timestampNs, dimensionKey);
}
if (mAlarmMonitor != nullptr) {
@@ -82,7 +82,7 @@
mAlarms.clear();
}
-void DurationAnomalyTracker::informAlarmsFired(const uint64_t& timestampNs,
+void DurationAnomalyTracker::informAlarmsFired(const int64_t& timestampNs,
unordered_set<sp<const InternalAlarm>, SpHash<InternalAlarm>>& firedAlarms) {
if (firedAlarms.empty() || mAlarms.empty()) return;
diff --git a/cmds/statsd/src/anomaly/DurationAnomalyTracker.h b/cmds/statsd/src/anomaly/DurationAnomalyTracker.h
index 53155d9..686d8f9 100644
--- a/cmds/statsd/src/anomaly/DurationAnomalyTracker.h
+++ b/cmds/statsd/src/anomaly/DurationAnomalyTracker.h
@@ -34,12 +34,12 @@
// Sets an alarm for the given timestamp.
// Replaces previous alarm if one already exists.
- void startAlarm(const MetricDimensionKey& dimensionKey, const uint64_t& eventTime);
+ void startAlarm(const MetricDimensionKey& dimensionKey, const int64_t& eventTime);
// Stops the alarm.
// If it should have already fired, but hasn't yet (e.g. because the AlarmManager is delayed),
// declare the anomaly now.
- void stopAlarm(const MetricDimensionKey& dimensionKey, const uint64_t& timestampNs);
+ void stopAlarm(const MetricDimensionKey& dimensionKey, const int64_t& timestampNs);
// Stop all the alarms owned by this tracker. Does not declare any anomalies.
void cancelAllAlarms();
@@ -48,7 +48,7 @@
// and removes it from firedAlarms. The AlarmMonitor is not informed.
// Note that this will generally be called from a different thread from the other functions;
// the caller is responsible for thread safety.
- void informAlarmsFired(const uint64_t& timestampNs,
+ void informAlarmsFired(const int64_t& timestampNs,
unordered_set<sp<const InternalAlarm>, SpHash<InternalAlarm>>& firedAlarms) override;
protected:
diff --git a/cmds/statsd/src/config/ConfigManager.cpp b/cmds/statsd/src/config/ConfigManager.cpp
index f9aaad4..16b7e79 100644
--- a/cmds/statsd/src/config/ConfigManager.cpp
+++ b/cmds/statsd/src/config/ConfigManager.cpp
@@ -23,6 +23,7 @@
#include "guardrail/StatsdStats.h"
#include "stats_log_util.h"
#include "stats_util.h"
+#include "stats_log_util.h"
#include <android-base/file.h>
#include <dirent.h>
@@ -112,7 +113,7 @@
const int64_t timestampNs = getElapsedRealtimeNs();
// Tell everyone
- for (sp<ConfigListener> listener:broadcastList) {
+ for (sp<ConfigListener> listener : broadcastList) {
listener->OnConfigUpdated(timestampNs, key, config);
}
}
diff --git a/cmds/statsd/src/guardrail/StatsdStats.cpp b/cmds/statsd/src/guardrail/StatsdStats.cpp
index 77773fe..b589d0d 100644
--- a/cmds/statsd/src/guardrail/StatsdStats.cpp
+++ b/cmds/statsd/src/guardrail/StatsdStats.cpp
@@ -49,20 +49,25 @@
const int FIELD_ID_ANOMALY_ALARM_STATS = 9;
// const int FIELD_ID_PULLED_ATOM_STATS = 10; // The proto is written in stats_log_util.cpp
const int FIELD_ID_LOGGER_ERROR_STATS = 11;
-const int FIELD_ID_SUBSCRIBER_ALARM_STATS = 12;
+const int FIELD_ID_PERIODIC_ALARM_STATS = 12;
+const int FIELD_ID_SKIPPED_LOG_EVENT_STATS = 13;
const int FIELD_ID_ATOM_STATS_TAG = 1;
const int FIELD_ID_ATOM_STATS_COUNT = 2;
const int FIELD_ID_ANOMALY_ALARMS_REGISTERED = 1;
-const int FIELD_ID_SUBSCRIBER_ALARMS_REGISTERED = 1;
+const int FIELD_ID_PERIODIC_ALARMS_REGISTERED = 1;
const int FIELD_ID_LOGGER_STATS_TIME = 1;
const int FIELD_ID_LOGGER_STATS_ERROR_CODE = 2;
+const int FIELD_ID_SKIPPED_LOG_EVENT_STATS_TAG = 1;
+const int FIELD_ID_SKIPPED_LOG_EVENT_STATS_TIMESTAMP = 2;
+
const int FIELD_ID_CONFIG_STATS_UID = 1;
const int FIELD_ID_CONFIG_STATS_ID = 2;
const int FIELD_ID_CONFIG_STATS_CREATION = 3;
+const int FIELD_ID_CONFIG_STATS_RESET = 19;
const int FIELD_ID_CONFIG_STATS_DELETION = 4;
const int FIELD_ID_CONFIG_STATS_METRIC_COUNT = 5;
const int FIELD_ID_CONFIG_STATS_CONDITION_COUNT = 6;
@@ -71,7 +76,8 @@
const int FIELD_ID_CONFIG_STATS_VALID = 9;
const int FIELD_ID_CONFIG_STATS_BROADCAST = 10;
const int FIELD_ID_CONFIG_STATS_DATA_DROP = 11;
-const int FIELD_ID_CONFIG_STATS_DUMP_REPORT = 12;
+const int FIELD_ID_CONFIG_STATS_DUMP_REPORT_TIME = 12;
+const int FIELD_ID_CONFIG_STATS_DUMP_REPORT_BYTES = 20;
const int FIELD_ID_CONFIG_STATS_MATCHER_STATS = 13;
const int FIELD_ID_CONFIG_STATS_CONDITION_STATS = 14;
const int FIELD_ID_CONFIG_STATS_METRIC_STATS = 15;
@@ -90,11 +96,10 @@
const int FIELD_ID_ALERT_STATS_ID = 1;
const int FIELD_ID_ALERT_STATS_COUNT = 2;
-const int FIELD_ID_UID_MAP_SNAPSHOTS = 1;
-const int FIELD_ID_UID_MAP_CHANGES = 2;
-const int FIELD_ID_UID_MAP_BYTES_USED = 3;
-const int FIELD_ID_UID_MAP_DROPPED_SNAPSHOTS = 4;
-const int FIELD_ID_UID_MAP_DROPPED_CHANGES = 5;
+const int FIELD_ID_UID_MAP_CHANGES = 1;
+const int FIELD_ID_UID_MAP_BYTES_USED = 2;
+const int FIELD_ID_UID_MAP_DROPPED_CHANGES = 3;
+const int FIELD_ID_UID_MAP_DELETED_APPS = 4;
const std::map<int, std::pair<size_t, size_t>> StatsdStats::kAtomDimensionKeySizeLimitMap = {
{android::util::CPU_TIME_PER_UID_FREQ, {6000, 10000}},
@@ -165,6 +170,18 @@
noteConfigRemovedInternalLocked(key);
}
+void StatsdStats::noteConfigResetInternalLocked(const ConfigKey& key) {
+ auto it = mConfigStats.find(key);
+ if (it != mConfigStats.end()) {
+ it->second->reset_time_sec = getWallClockSec();
+ }
+}
+
+void StatsdStats::noteConfigReset(const ConfigKey& key) {
+ lock_guard<std::mutex> lock(mLock);
+ noteConfigResetInternalLocked(key);
+}
+
void StatsdStats::noteBroadcastSent(const ConfigKey& key) {
noteBroadcastSent(key, getWallClockSec());
}
@@ -199,32 +216,32 @@
it->second->data_drop_time_sec.push_back(timeSec);
}
-void StatsdStats::noteMetricsReportSent(const ConfigKey& key) {
- noteMetricsReportSent(key, getWallClockSec());
+void StatsdStats::noteMetricsReportSent(const ConfigKey& key, const size_t num_bytes) {
+ noteMetricsReportSent(key, num_bytes, getWallClockSec());
}
-void StatsdStats::noteMetricsReportSent(const ConfigKey& key, int32_t timeSec) {
+void StatsdStats::noteMetricsReportSent(const ConfigKey& key, const size_t num_bytes,
+ int32_t timeSec) {
lock_guard<std::mutex> lock(mLock);
auto it = mConfigStats.find(key);
if (it == mConfigStats.end()) {
ALOGE("Config key %s not found!", key.ToString().c_str());
return;
}
- if (it->second->dump_report_time_sec.size() == kMaxTimestampCount) {
- it->second->dump_report_time_sec.pop_front();
+ if (it->second->dump_report_stats.size() == kMaxTimestampCount) {
+ it->second->dump_report_stats.pop_front();
}
- it->second->dump_report_time_sec.push_back(timeSec);
+ it->second->dump_report_stats.push_back(std::make_pair(timeSec, num_bytes));
}
-void StatsdStats::noteUidMapDropped(int snapshots, int deltas) {
+void StatsdStats::noteUidMapDropped(int deltas) {
lock_guard<std::mutex> lock(mLock);
- mUidMapStats.dropped_snapshots += mUidMapStats.dropped_snapshots + snapshots;
mUidMapStats.dropped_changes += mUidMapStats.dropped_changes + deltas;
}
-void StatsdStats::setUidMapSnapshots(int snapshots) {
+void StatsdStats::noteUidMapAppDeletionDropped() {
lock_guard<std::mutex> lock(mLock);
- mUidMapStats.snapshots = snapshots;
+ mUidMapStats.deleted_apps++;
}
void StatsdStats::setUidMapChanges(int changes) {
@@ -333,6 +350,15 @@
mPushedAtomStats[atomId]++;
}
+void StatsdStats::noteLogEventSkipped(int tag, int64_t timestamp) {
+ lock_guard<std::mutex> lock(mLock);
+ // grows strictly one at a time. so it won't > kMaxSkippedLogEvents
+ if (mSkippedLogEvents.size() == kMaxSkippedLogEvents) {
+ mSkippedLogEvents.pop_front();
+ }
+ mSkippedLogEvents.push_back(std::make_pair(tag, timestamp));
+}
+
void StatsdStats::noteLoggerError(int error) {
lock_guard<std::mutex> lock(mLock);
// grows strictly one at a time. so it won't > kMaxLoggerErrors
@@ -355,10 +381,11 @@
mAnomalyAlarmRegisteredStats = 0;
mPeriodicAlarmRegisteredStats = 0;
mLoggerErrors.clear();
+ mSkippedLogEvents.clear();
for (auto& config : mConfigStats) {
config.second->broadcast_sent_time_sec.clear();
config.second->data_drop_time_sec.clear();
- config.second->dump_report_time_sec.clear();
+ config.second->dump_report_stats.clear();
config.second->annotations.clear();
config.second->matcher_stats.clear();
config.second->condition_stats.clear();
@@ -378,10 +405,11 @@
fprintf(out, "%lu Config in icebox: \n", (unsigned long)mIceBox.size());
for (const auto& configStats : mIceBox) {
fprintf(out,
- "Config {%d_%lld}: creation=%d, deletion=%d, #metric=%d, #condition=%d, "
+ "Config {%d_%lld}: creation=%d, deletion=%d, reset=%d, #metric=%d, #condition=%d, "
"#matcher=%d, #alert=%d, valid=%d\n",
configStats->uid, (long long)configStats->id, configStats->creation_time_sec,
- configStats->deletion_time_sec, configStats->metric_count,
+ configStats->deletion_time_sec, configStats->reset_time_sec,
+ configStats->metric_count,
configStats->condition_count, configStats->matcher_count, configStats->alert_count,
configStats->is_valid);
@@ -416,8 +444,8 @@
fprintf(out, "\tdata drop time: %d\n", dataDropTime);
}
- for (const auto& dumpTime : configStats->dump_report_time_sec) {
- fprintf(out, "\tdump report time: %d\n", dumpTime);
+ for (const auto& dump : configStats->dump_report_stats) {
+ fprintf(out, "\tdump report time: %d bytes: %lld\n", dump.first, (long long)dump.second);
}
for (const auto& stats : pair.second->matcher_stats) {
@@ -464,11 +492,9 @@
fprintf(out, "Subscriber alarm registrations: %d\n", mPeriodicAlarmRegisteredStats);
}
- fprintf(out,
- "UID map stats: bytes=%d, snapshots=%d, changes=%d, snapshots lost=%d, changes "
- "lost=%d\n",
- mUidMapStats.bytes_used, mUidMapStats.snapshots, mUidMapStats.changes,
- mUidMapStats.dropped_snapshots, mUidMapStats.dropped_changes);
+ fprintf(out, "UID map stats: bytes=%d, changes=%d, deleted=%d, changes lost=%d\n",
+ mUidMapStats.bytes_used, mUidMapStats.changes, mUidMapStats.deleted_apps,
+ mUidMapStats.dropped_changes);
for (const auto& error : mLoggerErrors) {
time_t error_time = error.first;
@@ -477,6 +503,9 @@
strftime(buffer, sizeof(buffer), "%Y-%m-%d %I:%M%p\n", error_tm);
fprintf(out, "Logger error %d at %s\n", error.second, buffer);
}
+ for (const auto& skipped : mSkippedLogEvents) {
+ fprintf(out, "Log event (%d) skipped at %lld\n", skipped.first, (long long)skipped.second);
+ }
}
void addConfigStatsToProto(const ConfigStats& configStats, ProtoOutputStream* proto) {
@@ -485,6 +514,9 @@
proto->write(FIELD_TYPE_INT32 | FIELD_ID_CONFIG_STATS_UID, configStats.uid);
proto->write(FIELD_TYPE_INT64 | FIELD_ID_CONFIG_STATS_ID, (long long)configStats.id);
proto->write(FIELD_TYPE_INT32 | FIELD_ID_CONFIG_STATS_CREATION, configStats.creation_time_sec);
+ if (configStats.reset_time_sec != 0) {
+ proto->write(FIELD_TYPE_INT32 | FIELD_ID_CONFIG_STATS_RESET, configStats.reset_time_sec);
+ }
if (configStats.deletion_time_sec != 0) {
proto->write(FIELD_TYPE_INT32 | FIELD_ID_CONFIG_STATS_DELETION,
configStats.deletion_time_sec);
@@ -506,9 +538,16 @@
drop);
}
- for (const auto& dump : configStats.dump_report_time_sec) {
- proto->write(FIELD_TYPE_INT32 | FIELD_ID_CONFIG_STATS_DUMP_REPORT | FIELD_COUNT_REPEATED,
- dump);
+ for (const auto& dump : configStats.dump_report_stats) {
+ proto->write(FIELD_TYPE_INT32 | FIELD_ID_CONFIG_STATS_DUMP_REPORT_TIME |
+ FIELD_COUNT_REPEATED,
+ dump.first);
+ }
+
+ for (const auto& dump : configStats.dump_report_stats) {
+ proto->write(FIELD_TYPE_INT64 | FIELD_ID_CONFIG_STATS_DUMP_REPORT_BYTES |
+ FIELD_COUNT_REPEATED,
+ (long long)dump.second);
}
for (const auto& annotation : configStats.annotations) {
@@ -600,19 +639,17 @@
}
if (mPeriodicAlarmRegisteredStats > 0) {
- uint64_t token = proto.start(FIELD_TYPE_MESSAGE | FIELD_ID_SUBSCRIBER_ALARM_STATS);
- proto.write(FIELD_TYPE_INT32 | FIELD_ID_SUBSCRIBER_ALARMS_REGISTERED,
+ uint64_t token = proto.start(FIELD_TYPE_MESSAGE | FIELD_ID_PERIODIC_ALARM_STATS);
+ proto.write(FIELD_TYPE_INT32 | FIELD_ID_PERIODIC_ALARMS_REGISTERED,
mPeriodicAlarmRegisteredStats);
proto.end(token);
}
uint64_t uidMapToken = proto.start(FIELD_TYPE_MESSAGE | FIELD_ID_UIDMAP_STATS);
- proto.write(FIELD_TYPE_INT32 | FIELD_ID_UID_MAP_SNAPSHOTS, mUidMapStats.snapshots);
proto.write(FIELD_TYPE_INT32 | FIELD_ID_UID_MAP_CHANGES, mUidMapStats.changes);
proto.write(FIELD_TYPE_INT32 | FIELD_ID_UID_MAP_BYTES_USED, mUidMapStats.bytes_used);
- proto.write(FIELD_TYPE_INT32 | FIELD_ID_UID_MAP_DROPPED_SNAPSHOTS,
- mUidMapStats.dropped_snapshots);
proto.write(FIELD_TYPE_INT32 | FIELD_ID_UID_MAP_DROPPED_CHANGES, mUidMapStats.dropped_changes);
+ proto.write(FIELD_TYPE_INT32 | FIELD_ID_UID_MAP_DELETED_APPS, mUidMapStats.deleted_apps);
proto.end(uidMapToken);
for (const auto& error : mLoggerErrors) {
@@ -623,6 +660,15 @@
proto.end(token);
}
+ for (const auto& skipped : mSkippedLogEvents) {
+ uint64_t token = proto.start(FIELD_TYPE_MESSAGE | FIELD_ID_SKIPPED_LOG_EVENT_STATS |
+ FIELD_COUNT_REPEATED);
+ proto.write(FIELD_TYPE_INT32 | FIELD_ID_SKIPPED_LOG_EVENT_STATS_TAG, skipped.first);
+ proto.write(FIELD_TYPE_INT64 | FIELD_ID_SKIPPED_LOG_EVENT_STATS_TIMESTAMP,
+ (long long)skipped.second);
+ proto.end(token);
+ }
+
output->clear();
size_t bufferSize = proto.size();
output->resize(bufferSize);
diff --git a/cmds/statsd/src/guardrail/StatsdStats.h b/cmds/statsd/src/guardrail/StatsdStats.h
index a1b0ee2..123a703 100644
--- a/cmds/statsd/src/guardrail/StatsdStats.h
+++ b/cmds/statsd/src/guardrail/StatsdStats.h
@@ -34,6 +34,7 @@
int64_t id;
int32_t creation_time_sec;
int32_t deletion_time_sec = 0;
+ int32_t reset_time_sec = 0;
int32_t metric_count;
int32_t condition_count;
int32_t matcher_count;
@@ -42,7 +43,7 @@
std::list<int32_t> broadcast_sent_time_sec;
std::list<int32_t> data_drop_time_sec;
- std::list<int32_t> dump_report_time_sec;
+ std::list<std::pair<int32_t, int64_t>> dump_report_stats;
// Stores how many times a matcher have been matched. The map size is capped by kMaxConfigCount.
std::map<const int64_t, int> matcher_stats;
@@ -72,11 +73,10 @@
};
struct UidMapStats {
- int32_t snapshots;
int32_t changes;
int32_t bytes_used;
- int32_t dropped_snapshots;
int32_t dropped_changes;
+ int32_t deleted_apps = 0;
};
// Keeps track of stats of statsd.
@@ -104,6 +104,8 @@
const static int kMaxLoggerErrors = 10;
+ const static int kMaxSkippedLogEvents = 200;
+
const static int kMaxTimestampCount = 20;
const static int kMaxLogSourceCount = 50;
@@ -120,11 +122,14 @@
// is critical for understanding the metrics.
const static size_t kMaxBytesUsedUidMap = 50 * 1024;
+ // The number of deleted apps that are stored in the uid map.
+ const static int kMaxDeletedAppsInUidMap = 100;
+
/* Minimum period between two broadcasts in nanoseconds. */
- static const unsigned long long kMinBroadcastPeriodNs = 60 * NS_PER_SEC;
+ static const int64_t kMinBroadcastPeriodNs = 60 * NS_PER_SEC;
/* Min period between two checks of byte size per config key in nanoseconds. */
- static const unsigned long long kMinByteSizeCheckPeriodNs = 10 * NS_PER_SEC;
+ static const int64_t kMinByteSizeCheckPeriodNs = 10 * NS_PER_SEC;
// Maximum age (30 days) that files on disk can exist in seconds.
static const int kMaxAgeSecond = 60 * 60 * 24 * 30;
@@ -152,6 +157,10 @@
* Report a config has been removed.
*/
void noteConfigRemoved(const ConfigKey& key);
+ /**
+ * Report a config has been reset when ttl expires.
+ */
+ void noteConfigReset(const ConfigKey& key);
/**
* Report a broadcast has been sent to a config owner to collect the data.
@@ -168,7 +177,7 @@
*
* The report may be requested via StatsManager API, or through adb cmd.
*/
- void noteMetricsReportSent(const ConfigKey& key);
+ void noteMetricsReportSent(const ConfigKey& key, const size_t num_bytes);
/**
* Report the size of output tuple of a condition.
@@ -239,14 +248,18 @@
void noteRegisteredPeriodicAlarmChanged();
/**
- * Records the number of snapshot and delta entries that are being dropped from the uid map.
+ * Records the number of delta entries that are being dropped from the uid map.
*/
- void noteUidMapDropped(int snapshots, int deltas);
+ void noteUidMapDropped(int deltas);
/**
- * Updates the number of snapshots currently stored in the uid map.
+ * Records that an app was deleted (from statsd's map).
*/
- void setUidMapSnapshots(int snapshots);
+ void noteUidMapAppDeletionDropped();
+
+ /**
+ * Updates the number of changes currently stored in the uid map.
+ */
void setUidMapChanges(int changes);
void setCurrentUidMapMemory(int bytes);
@@ -265,6 +278,11 @@
void noteLoggerError(int error);
/**
+ * Records statsd skipped an event.
+ */
+ void noteLogEventSkipped(int tag, int64_t timestamp);
+
+ /**
* Reset the historical stats. Including all stats in icebox, and the tracked stats about
* metrics, matchers, and atoms. The active configs will be kept and StatsdStats will continue
* to collect stats after reset() has been called.
@@ -319,6 +337,9 @@
// Logd errors. Size capped by kMaxLoggerErrors.
std::list<const std::pair<int, int>> mLoggerErrors;
+ // Skipped log events.
+ std::list<const std::pair<int, int64_t>> mSkippedLogEvents;
+
// Stores the number of times statsd modified the anomaly alarm registered with
// StatsCompanionService.
int mAnomalyAlarmRegisteredStats = 0;
@@ -326,6 +347,7 @@
// Stores the number of times statsd registers the periodic alarm changes
int mPeriodicAlarmRegisteredStats = 0;
+ void noteConfigResetInternalLocked(const ConfigKey& key);
void noteConfigRemovedInternalLocked(const ConfigKey& key);
@@ -333,7 +355,7 @@
void noteDataDropped(const ConfigKey& key, int32_t timeSec);
- void noteMetricsReportSent(const ConfigKey& key, int32_t timeSec);
+ void noteMetricsReportSent(const ConfigKey& key, const size_t num_bytes, int32_t timeSec);
void noteBroadcastSent(const ConfigKey& key, int32_t timeSec);
diff --git a/cmds/statsd/src/metrics/CountMetricProducer.cpp b/cmds/statsd/src/metrics/CountMetricProducer.cpp
index afa5140..c77e07b 100644
--- a/cmds/statsd/src/metrics/CountMetricProducer.cpp
+++ b/cmds/statsd/src/metrics/CountMetricProducer.cpp
@@ -59,7 +59,7 @@
CountMetricProducer::CountMetricProducer(const ConfigKey& key, const CountMetric& metric,
const int conditionIndex,
const sp<ConditionWizard>& wizard,
- const uint64_t startTimeNs)
+ const int64_t startTimeNs)
: MetricProducer(metric.id(), key, startTimeNs, conditionIndex, wizard) {
// TODO: evaluate initial conditions. and set mConditionMet.
if (metric.has_bucket()) {
@@ -118,13 +118,18 @@
}
void CountMetricProducer::onSlicedConditionMayChangeLocked(bool overallCondition,
- const uint64_t eventTime) {
+ const int64_t eventTime) {
VLOG("Metric %lld onSlicedConditionMayChange", (long long)mMetricId);
}
-void CountMetricProducer::onDumpReportLocked(const uint64_t dumpTimeNs,
+void CountMetricProducer::onDumpReportLocked(const int64_t dumpTimeNs,
+ const bool include_current_partial_bucket,
ProtoOutputStream* protoOutput) {
- flushIfNeededLocked(dumpTimeNs);
+ if (include_current_partial_bucket) {
+ flushLocked(dumpTimeNs);
+ } else {
+ flushIfNeededLocked(dumpTimeNs);
+ }
if (mPastBuckets.empty()) {
return;
}
@@ -173,13 +178,13 @@
mPastBuckets.clear();
}
-void CountMetricProducer::dropDataLocked(const uint64_t dropTimeNs) {
+void CountMetricProducer::dropDataLocked(const int64_t dropTimeNs) {
flushIfNeededLocked(dropTimeNs);
mPastBuckets.clear();
}
void CountMetricProducer::onConditionChangedLocked(const bool conditionMet,
- const uint64_t eventTime) {
+ const int64_t eventTime) {
VLOG("Metric %lld onConditionChanged", (long long)mMetricId);
mCondition = conditionMet;
}
@@ -208,7 +213,7 @@
const size_t matcherIndex, const MetricDimensionKey& eventKey,
const ConditionKey& conditionKey, bool condition,
const LogEvent& event) {
- uint64_t eventTimeNs = event.GetElapsedTimestampNs();
+ int64_t eventTimeNs = event.GetElapsedTimestampNs();
flushIfNeededLocked(eventTimeNs);
if (condition == false) {
@@ -244,23 +249,23 @@
// When a new matched event comes in, we check if event falls into the current
// bucket. If not, flush the old counter to past buckets and initialize the new bucket.
-void CountMetricProducer::flushIfNeededLocked(const uint64_t& eventTimeNs) {
- uint64_t currentBucketEndTimeNs = getCurrentBucketEndTimeNs();
+void CountMetricProducer::flushIfNeededLocked(const int64_t& eventTimeNs) {
+ int64_t currentBucketEndTimeNs = getCurrentBucketEndTimeNs();
if (eventTimeNs < currentBucketEndTimeNs) {
return;
}
flushCurrentBucketLocked(eventTimeNs);
// Setup the bucket start time and number.
- uint64_t numBucketsForward = 1 + (eventTimeNs - currentBucketEndTimeNs) / mBucketSizeNs;
+ int64_t numBucketsForward = 1 + (eventTimeNs - currentBucketEndTimeNs) / mBucketSizeNs;
mCurrentBucketStartTimeNs = currentBucketEndTimeNs + (numBucketsForward - 1) * mBucketSizeNs;
mCurrentBucketNum += numBucketsForward;
VLOG("metric %lld: new bucket start time: %lld", (long long)mMetricId,
(long long)mCurrentBucketStartTimeNs);
}
-void CountMetricProducer::flushCurrentBucketLocked(const uint64_t& eventTimeNs) {
- uint64_t fullBucketEndTimeNs = getCurrentBucketEndTimeNs();
+void CountMetricProducer::flushCurrentBucketLocked(const int64_t& eventTimeNs) {
+ int64_t fullBucketEndTimeNs = getCurrentBucketEndTimeNs();
CountBucket info;
info.mBucketStartNs = mCurrentBucketStartTimeNs;
if (eventTimeNs < fullBucketEndTimeNs) {
diff --git a/cmds/statsd/src/metrics/CountMetricProducer.h b/cmds/statsd/src/metrics/CountMetricProducer.h
index fd9f0e0..cafc882 100644
--- a/cmds/statsd/src/metrics/CountMetricProducer.h
+++ b/cmds/statsd/src/metrics/CountMetricProducer.h
@@ -43,7 +43,7 @@
// TODO: Pass in the start time from MetricsManager, it should be consistent for all metrics.
CountMetricProducer(const ConfigKey& key, const CountMetric& countMetric,
const int conditionIndex, const sp<ConditionWizard>& wizard,
- const uint64_t startTimeNs);
+ const int64_t startTimeNs);
virtual ~CountMetricProducer();
@@ -54,26 +54,28 @@
const LogEvent& event) override;
private:
- void onDumpReportLocked(const uint64_t dumpTimeNs,
+
+ void onDumpReportLocked(const int64_t dumpTimeNs,
+ const bool include_current_partial_bucket,
android::util::ProtoOutputStream* protoOutput) override;
// Internal interface to handle condition change.
- void onConditionChangedLocked(const bool conditionMet, const uint64_t eventTime) override;
+ void onConditionChangedLocked(const bool conditionMet, const int64_t eventTime) override;
// Internal interface to handle sliced condition change.
- void onSlicedConditionMayChangeLocked(bool overallCondition, const uint64_t eventTime) override;
+ void onSlicedConditionMayChangeLocked(bool overallCondition, const int64_t eventTime) override;
// Internal function to calculate the current used bytes.
size_t byteSizeLocked() const override;
void dumpStatesLocked(FILE* out, bool verbose) const override;
- void dropDataLocked(const uint64_t dropTimeNs) override;
+ void dropDataLocked(const int64_t dropTimeNs) override;
// Util function to flush the old packet.
- void flushIfNeededLocked(const uint64_t& newEventTime) override;
+ void flushIfNeededLocked(const int64_t& newEventTime) override;
- void flushCurrentBucketLocked(const uint64_t& eventTimeNs) override;
+ void flushCurrentBucketLocked(const int64_t& eventTimeNs) override;
// TODO: Add a lock to mPastBuckets.
std::unordered_map<MetricDimensionKey, std::vector<CountBucket>> mPastBuckets;
diff --git a/cmds/statsd/src/metrics/DurationMetricProducer.cpp b/cmds/statsd/src/metrics/DurationMetricProducer.cpp
index f02f307..3125fa7 100644
--- a/cmds/statsd/src/metrics/DurationMetricProducer.cpp
+++ b/cmds/statsd/src/metrics/DurationMetricProducer.cpp
@@ -61,7 +61,7 @@
const bool nesting,
const sp<ConditionWizard>& wizard,
const FieldMatcher& internalDimensions,
- const uint64_t startTimeNs)
+ const int64_t startTimeNs)
: MetricProducer(metric.id(), key, startTimeNs, conditionIndex, wizard),
mAggregationType(metric.aggregation_type()),
mStartIndex(startIndex),
@@ -170,7 +170,7 @@
// 2. No condition in dimension
// 3. The links covers all dimension fields in the sliced child condition predicate.
void DurationMetricProducer::onSlicedConditionMayChangeLocked_opt1(bool condition,
- const uint64_t eventTime) {
+ const int64_t eventTime) {
if (mMetric2ConditionLinks.size() != 1 ||
!mHasLinksToAllConditionDimensionsInTracker ||
!mDimensionsInCondition.empty()) {
@@ -243,7 +243,7 @@
// 1. If combination condition, logical operation is AND, only one sliced child predicate.
// 2. Has dimensions_in_condition and it equals to the output dimensions of the sliced predicate.
void DurationMetricProducer::onSlicedConditionMayChangeLocked_opt2(bool condition,
- const uint64_t eventTime) {
+ const int64_t eventTime) {
if (mMetric2ConditionLinks.size() > 1 || !mSameConditionDimensionsInTracker) {
return;
}
@@ -328,7 +328,7 @@
}
void DurationMetricProducer::onSlicedConditionMayChangeLocked(bool overallCondition,
- const uint64_t eventTime) {
+ const int64_t eventTime) {
VLOG("Metric %lld onSlicedConditionMayChange", (long long)mMetricId);
flushIfNeededLocked(eventTime);
@@ -420,7 +420,7 @@
}
void DurationMetricProducer::onConditionChangedLocked(const bool conditionMet,
- const uint64_t eventTime) {
+ const int64_t eventTime) {
VLOG("Metric %lld onConditionChanged", (long long)mMetricId);
mCondition = conditionMet;
flushIfNeededLocked(eventTime);
@@ -433,14 +433,19 @@
}
}
-void DurationMetricProducer::dropDataLocked(const uint64_t dropTimeNs) {
+void DurationMetricProducer::dropDataLocked(const int64_t dropTimeNs) {
flushIfNeededLocked(dropTimeNs);
mPastBuckets.clear();
}
-void DurationMetricProducer::onDumpReportLocked(const uint64_t dumpTimeNs,
+void DurationMetricProducer::onDumpReportLocked(const int64_t dumpTimeNs,
+ const bool include_current_partial_bucket,
ProtoOutputStream* protoOutput) {
- flushIfNeededLocked(dumpTimeNs);
+ if (include_current_partial_bucket) {
+ flushLocked(dumpTimeNs);
+ } else {
+ flushIfNeededLocked(dumpTimeNs);
+ }
if (mPastBuckets.empty()) {
VLOG(" Duration metric, empty return");
return;
@@ -492,8 +497,8 @@
mPastBuckets.clear();
}
-void DurationMetricProducer::flushIfNeededLocked(const uint64_t& eventTimeNs) {
- uint64_t currentBucketEndTimeNs = getCurrentBucketEndTimeNs();
+void DurationMetricProducer::flushIfNeededLocked(const int64_t& eventTimeNs) {
+ int64_t currentBucketEndTimeNs = getCurrentBucketEndTimeNs();
if (currentBucketEndTimeNs > eventTimeNs) {
return;
@@ -522,7 +527,7 @@
mCurrentBucketNum += numBucketsForward;
}
-void DurationMetricProducer::flushCurrentBucketLocked(const uint64_t& eventTimeNs) {
+void DurationMetricProducer::flushCurrentBucketLocked(const int64_t& eventTimeNs) {
for (auto whatIt = mCurrentSlicedDurationTrackerMap.begin();
whatIt != mCurrentSlicedDurationTrackerMap.end();) {
for (auto it = whatIt->second.begin(); it != whatIt->second.end();) {
@@ -644,7 +649,7 @@
void DurationMetricProducer::onMatchedLogEventLocked(const size_t matcherIndex,
const LogEvent& event) {
- uint64_t eventTimeNs = event.GetElapsedTimestampNs();
+ int64_t eventTimeNs = event.GetElapsedTimestampNs();
if (eventTimeNs < mStartTimeNs) {
return;
}
diff --git a/cmds/statsd/src/metrics/DurationMetricProducer.h b/cmds/statsd/src/metrics/DurationMetricProducer.h
index 75f2391..80fbdde 100644
--- a/cmds/statsd/src/metrics/DurationMetricProducer.h
+++ b/cmds/statsd/src/metrics/DurationMetricProducer.h
@@ -42,7 +42,7 @@
const int conditionIndex, const size_t startIndex,
const size_t stopIndex, const size_t stopAllIndex, const bool nesting,
const sp<ConditionWizard>& wizard,
- const FieldMatcher& internalDimensions, const uint64_t startTimeNs);
+ const FieldMatcher& internalDimensions, const int64_t startTimeNs);
virtual ~DurationMetricProducer();
@@ -61,29 +61,30 @@
void handleStartEvent(const MetricDimensionKey& eventKey, const ConditionKey& conditionKeys,
bool condition, const LogEvent& event);
- void onDumpReportLocked(const uint64_t dumpTimeNs,
+ void onDumpReportLocked(const int64_t dumpTimeNs,
+ const bool include_current_partial_bucket,
android::util::ProtoOutputStream* protoOutput) override;
// Internal interface to handle condition change.
- void onConditionChangedLocked(const bool conditionMet, const uint64_t eventTime) override;
+ void onConditionChangedLocked(const bool conditionMet, const int64_t eventTime) override;
// Internal interface to handle sliced condition change.
- void onSlicedConditionMayChangeLocked(bool overallCondition, const uint64_t eventTime) override;
+ void onSlicedConditionMayChangeLocked(bool overallCondition, const int64_t eventTime) override;
- void onSlicedConditionMayChangeLocked_opt1(bool overallCondition, const uint64_t eventTime);
- void onSlicedConditionMayChangeLocked_opt2(bool overallCondition, const uint64_t eventTime);
+ void onSlicedConditionMayChangeLocked_opt1(bool overallCondition, const int64_t eventTime);
+ void onSlicedConditionMayChangeLocked_opt2(bool overallCondition, const int64_t eventTime);
// Internal function to calculate the current used bytes.
size_t byteSizeLocked() const override;
void dumpStatesLocked(FILE* out, bool verbose) const override;
- void dropDataLocked(const uint64_t dropTimeNs) override;
+ void dropDataLocked(const int64_t dropTimeNs) override;
// Util function to flush the old packet.
- void flushIfNeededLocked(const uint64_t& eventTime);
+ void flushIfNeededLocked(const int64_t& eventTime);
- void flushCurrentBucketLocked(const uint64_t& eventTimeNs) override;
+ void flushCurrentBucketLocked(const int64_t& eventTimeNs) override;
const DurationMetric_AggregationType mAggregationType;
diff --git a/cmds/statsd/src/metrics/EventMetricProducer.cpp b/cmds/statsd/src/metrics/EventMetricProducer.cpp
index 42a5a3a..33ab9aa 100644
--- a/cmds/statsd/src/metrics/EventMetricProducer.cpp
+++ b/cmds/statsd/src/metrics/EventMetricProducer.cpp
@@ -54,7 +54,7 @@
EventMetricProducer::EventMetricProducer(const ConfigKey& key, const EventMetric& metric,
const int conditionIndex,
const sp<ConditionWizard>& wizard,
- const uint64_t startTimeNs)
+ const int64_t startTimeNs)
: MetricProducer(metric.id(), key, startTimeNs, conditionIndex, wizard) {
if (metric.links().size() > 0) {
for (const auto& link : metric.links()) {
@@ -75,12 +75,12 @@
VLOG("~EventMetricProducer() called");
}
-void EventMetricProducer::dropDataLocked(const uint64_t dropTimeNs) {
+void EventMetricProducer::dropDataLocked(const int64_t dropTimeNs) {
mProto->clear();
}
void EventMetricProducer::onSlicedConditionMayChangeLocked(bool overallCondition,
- const uint64_t eventTime) {
+ const int64_t eventTime) {
}
std::unique_ptr<std::vector<uint8_t>> serializeProtoLocked(ProtoOutputStream& protoOutput) {
@@ -100,7 +100,8 @@
return buffer;
}
-void EventMetricProducer::onDumpReportLocked(const uint64_t dumpTimeNs,
+void EventMetricProducer::onDumpReportLocked(const int64_t dumpTimeNs,
+ const bool include_current_partial_bucket,
ProtoOutputStream* protoOutput) {
if (mProto->size() <= 0) {
return;
@@ -119,7 +120,7 @@
}
void EventMetricProducer::onConditionChangedLocked(const bool conditionMet,
- const uint64_t eventTime) {
+ const int64_t eventTime) {
VLOG("Metric %lld onConditionChanged", (long long)mMetricId);
mCondition = conditionMet;
}
diff --git a/cmds/statsd/src/metrics/EventMetricProducer.h b/cmds/statsd/src/metrics/EventMetricProducer.h
index 93c6c9a..5c29174 100644
--- a/cmds/statsd/src/metrics/EventMetricProducer.h
+++ b/cmds/statsd/src/metrics/EventMetricProducer.h
@@ -36,7 +36,7 @@
// TODO: Pass in the start time from MetricsManager, it should be consistent for all metrics.
EventMetricProducer(const ConfigKey& key, const EventMetric& eventMetric,
const int conditionIndex, const sp<ConditionWizard>& wizard,
- const uint64_t startTimeNs);
+ const int64_t startTimeNs);
virtual ~EventMetricProducer();
@@ -46,16 +46,17 @@
const ConditionKey& conditionKey, bool condition,
const LogEvent& event) override;
- void onDumpReportLocked(const uint64_t dumpTimeNs,
+ void onDumpReportLocked(const int64_t dumpTimeNs,
+ const bool include_current_partial_bucket,
android::util::ProtoOutputStream* protoOutput) override;
// Internal interface to handle condition change.
- void onConditionChangedLocked(const bool conditionMet, const uint64_t eventTime) override;
+ void onConditionChangedLocked(const bool conditionMet, const int64_t eventTime) override;
// Internal interface to handle sliced condition change.
- void onSlicedConditionMayChangeLocked(bool overallCondition, const uint64_t eventTime) override;
+ void onSlicedConditionMayChangeLocked(bool overallCondition, const int64_t eventTime) override;
- void dropDataLocked(const uint64_t dropTimeNs) override;
+ void dropDataLocked(const int64_t dropTimeNs) override;
// Internal function to calculate the current used bytes.
size_t byteSizeLocked() const override;
diff --git a/cmds/statsd/src/metrics/GaugeMetricProducer.cpp b/cmds/statsd/src/metrics/GaugeMetricProducer.cpp
index b13c3e7..3c77aae 100644
--- a/cmds/statsd/src/metrics/GaugeMetricProducer.cpp
+++ b/cmds/statsd/src/metrics/GaugeMetricProducer.cpp
@@ -61,7 +61,7 @@
GaugeMetricProducer::GaugeMetricProducer(const ConfigKey& key, const GaugeMetric& metric,
const int conditionIndex,
const sp<ConditionWizard>& wizard, const int pullTagId,
- const uint64_t startTimeNs,
+ const int64_t startTimeNs,
shared_ptr<StatsPullerManager> statsPullerManager)
: MetricProducer(metric.id(), key, startTimeNs, conditionIndex, wizard),
mStatsPullerManager(statsPullerManager),
@@ -155,9 +155,15 @@
}
}
-void GaugeMetricProducer::onDumpReportLocked(const uint64_t dumpTimeNs,
+void GaugeMetricProducer::onDumpReportLocked(const int64_t dumpTimeNs,
+ const bool include_current_partial_bucket,
ProtoOutputStream* protoOutput) {
VLOG("Gauge metric %lld report now...", (long long)mMetricId);
+ if (include_current_partial_bucket) {
+ flushLocked(dumpTimeNs);
+ } else {
+ flushIfNeededLocked(dumpTimeNs);
+ }
flushIfNeededLocked(dumpTimeNs);
if (mPastBuckets.empty()) {
@@ -267,7 +273,7 @@
}
void GaugeMetricProducer::onConditionChangedLocked(const bool conditionMet,
- const uint64_t eventTime) {
+ const int64_t eventTime) {
VLOG("GaugeMetric %lld onConditionChanged", (long long)mMetricId);
flushIfNeededLocked(eventTime);
mCondition = conditionMet;
@@ -278,7 +284,7 @@
}
void GaugeMetricProducer::onSlicedConditionMayChangeLocked(bool overallCondition,
- const uint64_t eventTime) {
+ const int64_t eventTime) {
VLOG("GaugeMetric %lld onSlicedConditionMayChange overall condition %d", (long long)mMetricId,
overallCondition);
flushIfNeededLocked(eventTime);
@@ -336,7 +342,7 @@
if (condition == false) {
return;
}
- uint64_t eventTimeNs = event.GetElapsedTimestampNs();
+ int64_t eventTimeNs = event.GetElapsedTimestampNs();
mTagId = event.GetTagId();
if (eventTimeNs < mCurrentBucketStartTimeNs) {
VLOG("Gauge Skip event due to late arrival: %lld vs %lld", (long long)eventTimeNs,
@@ -391,7 +397,7 @@
}
}
-void GaugeMetricProducer::dropDataLocked(const uint64_t dropTimeNs) {
+void GaugeMetricProducer::dropDataLocked(const int64_t dropTimeNs) {
flushIfNeededLocked(dropTimeNs);
mPastBuckets.clear();
}
@@ -401,8 +407,8 @@
// bucket.
// if data is pushed, onMatchedLogEvent will only be called through onConditionChanged() inside
// the GaugeMetricProducer while holding the lock.
-void GaugeMetricProducer::flushIfNeededLocked(const uint64_t& eventTimeNs) {
- uint64_t currentBucketEndTimeNs = getCurrentBucketEndTimeNs();
+void GaugeMetricProducer::flushIfNeededLocked(const int64_t& eventTimeNs) {
+ int64_t currentBucketEndTimeNs = getCurrentBucketEndTimeNs();
if (eventTimeNs < currentBucketEndTimeNs) {
VLOG("Gauge eventTime is %lld, less than next bucket start time %lld",
@@ -420,8 +426,8 @@
(long long)mCurrentBucketStartTimeNs);
}
-void GaugeMetricProducer::flushCurrentBucketLocked(const uint64_t& eventTimeNs) {
- uint64_t fullBucketEndTimeNs = getCurrentBucketEndTimeNs();
+void GaugeMetricProducer::flushCurrentBucketLocked(const int64_t& eventTimeNs) {
+ int64_t fullBucketEndTimeNs = getCurrentBucketEndTimeNs();
GaugeBucket info;
info.mBucketStartNs = mCurrentBucketStartTimeNs;
diff --git a/cmds/statsd/src/metrics/GaugeMetricProducer.h b/cmds/statsd/src/metrics/GaugeMetricProducer.h
index 9605b13..04b7df9 100644
--- a/cmds/statsd/src/metrics/GaugeMetricProducer.h
+++ b/cmds/statsd/src/metrics/GaugeMetricProducer.h
@@ -65,7 +65,7 @@
void onDataPulled(const std::vector<std::shared_ptr<LogEvent>>& data) override;
// GaugeMetric needs to immediately trigger another pull when we create the partial bucket.
- void notifyAppUpgrade(const uint64_t& eventTimeNs, const string& apk, const int uid,
+ void notifyAppUpgrade(const int64_t& eventTimeNs, const string& apk, const int uid,
const int64_t version) override {
std::lock_guard<std::mutex> lock(mMutex);
@@ -87,32 +87,33 @@
const LogEvent& event) override;
private:
- void onDumpReportLocked(const uint64_t dumpTimeNs,
+ void onDumpReportLocked(const int64_t dumpTimeNs,
+ const bool include_current_partial_bucket,
android::util::ProtoOutputStream* protoOutput) override;
// for testing
GaugeMetricProducer(const ConfigKey& key, const GaugeMetric& gaugeMetric,
const int conditionIndex, const sp<ConditionWizard>& wizard,
- const int pullTagId, const uint64_t startTimeNs,
+ const int pullTagId, const int64_t startTimeNs,
std::shared_ptr<StatsPullerManager> statsPullerManager);
// Internal interface to handle condition change.
- void onConditionChangedLocked(const bool conditionMet, const uint64_t eventTime) override;
+ void onConditionChangedLocked(const bool conditionMet, const int64_t eventTime) override;
// Internal interface to handle sliced condition change.
- void onSlicedConditionMayChangeLocked(bool overallCondition, const uint64_t eventTime) override;
+ void onSlicedConditionMayChangeLocked(bool overallCondition, const int64_t eventTime) override;
// Internal function to calculate the current used bytes.
size_t byteSizeLocked() const override;
void dumpStatesLocked(FILE* out, bool verbose) const override;
- void dropDataLocked(const uint64_t dropTimeNs) override;
+ void dropDataLocked(const int64_t dropTimeNs) override;
// Util function to flush the old packet.
- void flushIfNeededLocked(const uint64_t& eventTime) override;
+ void flushIfNeededLocked(const int64_t& eventTime) override;
- void flushCurrentBucketLocked(const uint64_t& eventTimeNs) override;
+ void flushCurrentBucketLocked(const int64_t& eventTimeNs) override;
void pullLocked();
diff --git a/cmds/statsd/src/metrics/MetricProducer.cpp b/cmds/statsd/src/metrics/MetricProducer.cpp
index bf529c8..bcf0e62 100644
--- a/cmds/statsd/src/metrics/MetricProducer.cpp
+++ b/cmds/statsd/src/metrics/MetricProducer.cpp
@@ -25,7 +25,7 @@
using std::map;
void MetricProducer::onMatchedLogEventLocked(const size_t matcherIndex, const LogEvent& event) {
- uint64_t eventTimeNs = event.GetElapsedTimestampNs();
+ int64_t eventTimeNs = event.GetElapsedTimestampNs();
// this is old event, maybe statsd restarted?
if (eventTimeNs < mStartTimeNs) {
return;
diff --git a/cmds/statsd/src/metrics/MetricProducer.h b/cmds/statsd/src/metrics/MetricProducer.h
index 0b3d677..f931e57 100644
--- a/cmds/statsd/src/metrics/MetricProducer.h
+++ b/cmds/statsd/src/metrics/MetricProducer.h
@@ -64,7 +64,7 @@
* the flush again when the end timestamp is forced to be now, and then after flushing, update
* the start timestamp to be now.
*/
- void notifyAppUpgrade(const uint64_t& eventTimeNs, const string& apk, const int uid,
+ void notifyAppUpgrade(const int64_t& eventTimeNs, const string& apk, const int uid,
const int64_t version) override {
std::lock_guard<std::mutex> lock(mMutex);
@@ -79,12 +79,14 @@
// is a partial bucket and can merge it with the previous bucket.
};
- void notifyAppRemoved(const uint64_t& eventTimeNs, const string& apk, const int uid) override{
- // TODO: Implement me.
+ void notifyAppRemoved(const int64_t& eventTimeNs, const string& apk, const int uid) override{
+ // Force buckets to split on removal also.
+ notifyAppUpgrade(eventTimeNs, apk, uid, 0);
};
- void onUidMapReceived(const uint64_t& eventTimeNs) override{
- // TODO: Implement me.
+ void onUidMapReceived(const int64_t& eventTimeNs) override{
+ // Purposefully don't flush partial buckets on a new snapshot.
+ // This occurs if a new user is added/removed or statsd crashes.
};
// Consume the parsed stats log entry that already matched the "what" of the metric.
@@ -93,12 +95,12 @@
onMatchedLogEventLocked(matcherIndex, event);
}
- void onConditionChanged(const bool condition, const uint64_t eventTime) {
+ void onConditionChanged(const bool condition, const int64_t eventTime) {
std::lock_guard<std::mutex> lock(mMutex);
onConditionChangedLocked(condition, eventTime);
}
- void onSlicedConditionMayChange(bool overallCondition, const uint64_t eventTime) {
+ void onSlicedConditionMayChange(bool overallCondition, const int64_t eventTime) {
std::lock_guard<std::mutex> lock(mMutex);
onSlicedConditionMayChangeLocked(overallCondition, eventTime);
}
@@ -110,9 +112,11 @@
// Output the metrics data to [protoOutput]. All metrics reports end with the same timestamp.
// This method clears all the past buckets.
- void onDumpReport(const uint64_t dumpTimeNs, android::util::ProtoOutputStream* protoOutput) {
+ void onDumpReport(const int64_t dumpTimeNs,
+ const bool include_current_partial_bucket,
+ android::util::ProtoOutputStream* protoOutput) {
std::lock_guard<std::mutex> lock(mMutex);
- return onDumpReportLocked(dumpTimeNs, protoOutput);
+ return onDumpReportLocked(dumpTimeNs, include_current_partial_bucket, protoOutput);
}
void dumpStates(FILE* out, bool verbose) const {
@@ -156,24 +160,34 @@
// We still need to keep future data valid and anomaly tracking work, which means we will
// have to flush old data, informing anomaly trackers then safely drop old data.
// We still keep current bucket data for future metrics' validity.
- void dropData(const uint64_t dropTimeNs) {
+ void dropData(const int64_t dropTimeNs) {
std::lock_guard<std::mutex> lock(mMutex);
dropDataLocked(dropTimeNs);
}
protected:
- virtual void onConditionChangedLocked(const bool condition, const uint64_t eventTime) = 0;
+ virtual void onConditionChangedLocked(const bool condition, const int64_t eventTime) = 0;
virtual void onSlicedConditionMayChangeLocked(bool overallCondition,
- const uint64_t eventTime) = 0;
- virtual void onDumpReportLocked(const uint64_t dumpTimeNs,
+ const int64_t eventTime) = 0;
+ virtual void onDumpReportLocked(const int64_t dumpTimeNs,
+ const bool include_current_partial_bucket,
android::util::ProtoOutputStream* protoOutput) = 0;
virtual size_t byteSizeLocked() const = 0;
virtual void dumpStatesLocked(FILE* out, bool verbose) const = 0;
/**
- * Flushes the current bucket if the eventTime is after the current bucket's end time.
+ * Flushes the current bucket if the eventTime is after the current bucket's end time. This will
+ also flush the current partial bucket in memory.
*/
- virtual void flushIfNeededLocked(const uint64_t& eventTime){};
+ virtual void flushIfNeededLocked(const int64_t& eventTime){};
+
+ /**
+ * Flushes all the data including the current partial bucket.
+ */
+ virtual void flushLocked(const int64_t& eventTime) {
+ flushIfNeededLocked(eventTime);
+ flushCurrentBucketLocked(eventTime);
+ };
/**
* For metrics that aggregate (ie, every metric producer except for EventMetricProducer),
@@ -185,15 +199,15 @@
* flushIfNeededLocked or the app upgrade handler; the caller MUST update the bucket timestamp
* and bucket number as needed.
*/
- virtual void flushCurrentBucketLocked(const uint64_t& eventTimeNs){};
+ virtual void flushCurrentBucketLocked(const int64_t& eventTimeNs){};
// Convenience to compute the current bucket's end time, which is always aligned with the
// start time of the metric.
- uint64_t getCurrentBucketEndTimeNs() const {
+ int64_t getCurrentBucketEndTimeNs() const {
return mStartTimeNs + (mCurrentBucketNum + 1) * mBucketSizeNs;
}
- virtual void dropDataLocked(const uint64_t dropTimeNs) = 0;
+ virtual void dropDataLocked(const int64_t dropTimeNs) = 0;
const int64_t mMetricId;
@@ -201,15 +215,15 @@
// The time when this metric producer was first created. The end time for the current bucket
// can be computed from this based on mCurrentBucketNum.
- uint64_t mStartTimeNs;
+ int64_t mStartTimeNs;
// Start time may not be aligned with the start of statsd if there is an app upgrade in the
// middle of a bucket.
- uint64_t mCurrentBucketStartTimeNs;
+ int64_t mCurrentBucketStartTimeNs;
// Used by anomaly detector to track which bucket we are in. This is not sent with the produced
// report.
- uint64_t mCurrentBucketNum;
+ int64_t mCurrentBucketNum;
int64_t mBucketSizeNs;
diff --git a/cmds/statsd/src/metrics/MetricsManager.cpp b/cmds/statsd/src/metrics/MetricsManager.cpp
index 772f017..b7f1bd5 100644
--- a/cmds/statsd/src/metrics/MetricsManager.cpp
+++ b/cmds/statsd/src/metrics/MetricsManager.cpp
@@ -59,8 +59,13 @@
const sp<AlarmMonitor>& anomalyAlarmMonitor,
const sp<AlarmMonitor>& periodicAlarmMonitor)
: mConfigKey(key), mUidMap(uidMap),
+ mTtlNs(config.has_ttl_in_seconds() ? config.ttl_in_seconds() * NS_PER_SEC : -1),
+ mTtlEndNs(-1),
mLastReportTimeNs(timeBaseSec * NS_PER_SEC),
mLastReportWallClockNs(getWallClockNs()) {
+ // Init the ttl end timestamp.
+ refreshTtl(timeBaseSec * NS_PER_SEC);
+
mConfigValid =
initStatsdConfig(key, config, *uidMap, anomalyAlarmMonitor, periodicAlarmMonitor,
timeBaseSec, currentTimeSec, mTagIds, mAllAtomMatchers,
@@ -136,7 +141,7 @@
return mConfigValid;
}
-void MetricsManager::notifyAppUpgrade(const uint64_t& eventTimeNs, const string& apk, const int uid,
+void MetricsManager::notifyAppUpgrade(const int64_t& eventTimeNs, const string& apk, const int uid,
const int64_t version) {
// check if we care this package
if (std::find(mAllowedPkg.begin(), mAllowedPkg.end(), apk) == mAllowedPkg.end()) {
@@ -147,7 +152,7 @@
initLogSourceWhiteList();
}
-void MetricsManager::notifyAppRemoved(const uint64_t& eventTimeNs, const string& apk,
+void MetricsManager::notifyAppRemoved(const int64_t& eventTimeNs, const string& apk,
const int uid) {
// check if we care this package
if (std::find(mAllowedPkg.begin(), mAllowedPkg.end(), apk) == mAllowedPkg.end()) {
@@ -158,7 +163,7 @@
initLogSourceWhiteList();
}
-void MetricsManager::onUidMapReceived(const uint64_t& eventTimeNs) {
+void MetricsManager::onUidMapReceived(const int64_t& eventTimeNs) {
if (mAllowedPkg.size() == 0) {
return;
}
@@ -179,20 +184,22 @@
}
}
-void MetricsManager::dropData(const uint64_t dropTimeNs) {
+void MetricsManager::dropData(const int64_t dropTimeNs) {
for (const auto& producer : mAllMetricProducers) {
producer->dropData(dropTimeNs);
}
}
-void MetricsManager::onDumpReport(const uint64_t dumpTimeStampNs, ProtoOutputStream* protoOutput) {
+void MetricsManager::onDumpReport(const int64_t dumpTimeStampNs,
+ const bool include_current_partial_bucket,
+ ProtoOutputStream* protoOutput) {
VLOG("=========================Metric Reports Start==========================");
// one StatsLogReport per MetricProduer
for (const auto& producer : mAllMetricProducers) {
if (mNoReportMetricIds.find(producer->getMetricId()) == mNoReportMetricIds.end()) {
uint64_t token =
protoOutput->start(FIELD_TYPE_MESSAGE | FIELD_COUNT_REPEATED | FIELD_ID_METRICS);
- producer->onDumpReport(dumpTimeStampNs, protoOutput);
+ producer->onDumpReport(dumpTimeStampNs, include_current_partial_bucket, protoOutput);
protoOutput->end(token);
}
}
@@ -288,7 +295,7 @@
}
int tagId = event.GetTagId();
- uint64_t eventTime = event.GetElapsedTimestampNs();
+ int64_t eventTime = event.GetElapsedTimestampNs();
if (mTagIds.find(tagId) == mTagIds.end()) {
// not interesting...
return;
@@ -367,7 +374,7 @@
}
void MetricsManager::onAnomalyAlarmFired(
- const uint64_t& timestampNs,
+ const int64_t& timestampNs,
unordered_set<sp<const InternalAlarm>, SpHash<InternalAlarm>>& alarmSet) {
for (const auto& itr : mAllAnomalyTrackers) {
itr->informAlarmsFired(timestampNs, alarmSet);
@@ -375,7 +382,7 @@
}
void MetricsManager::onPeriodicAlarmFired(
- const uint64_t& timestampNs,
+ const int64_t& timestampNs,
unordered_set<sp<const InternalAlarm>, SpHash<InternalAlarm>>& alarmSet) {
for (const auto& itr : mAllPeriodicAlarmTrackers) {
itr->informAlarmsFired(timestampNs, alarmSet);
diff --git a/cmds/statsd/src/metrics/MetricsManager.h b/cmds/statsd/src/metrics/MetricsManager.h
index be4644c..6aa260a 100644
--- a/cmds/statsd/src/metrics/MetricsManager.h
+++ b/cmds/statsd/src/metrics/MetricsManager.h
@@ -49,19 +49,19 @@
void onLogEvent(const LogEvent& event);
void onAnomalyAlarmFired(
- const uint64_t& timestampNs,
+ const int64_t& timestampNs,
unordered_set<sp<const InternalAlarm>, SpHash<InternalAlarm>>& alarmSet);
void onPeriodicAlarmFired(
- const uint64_t& timestampNs,
+ const int64_t& timestampNs,
unordered_set<sp<const InternalAlarm>, SpHash<InternalAlarm>>& alarmSet);
- void notifyAppUpgrade(const uint64_t& eventTimeNs, const string& apk, const int uid,
+ void notifyAppUpgrade(const int64_t& eventTimeNs, const string& apk, const int uid,
const int64_t version) override;
- void notifyAppRemoved(const uint64_t& eventTimeNs, const string& apk, const int uid) override;
+ void notifyAppRemoved(const int64_t& eventTimeNs, const string& apk, const int uid) override;
- void onUidMapReceived(const uint64_t& eventTimeNs) override;
+ void onUidMapReceived(const int64_t& eventTimeNs) override;
bool shouldAddUidMapListener() const {
return !mAllowedPkg.empty();
@@ -69,6 +69,16 @@
void dumpStates(FILE* out, bool verbose);
+ inline bool isInTtl(const int64_t timestampNs) const {
+ return mTtlNs <= 0 || timestampNs < mTtlEndNs;
+ };
+
+ void refreshTtl(const int64_t currentTimestampNs) {
+ if (mTtlNs > 0) {
+ mTtlEndNs = currentTimestampNs + mTtlNs;
+ }
+ };
+
// Returns the elapsed realtime when this metric manager last reported metrics.
inline int64_t getLastReportTimeNs() const {
return mLastReportTimeNs;
@@ -78,22 +88,29 @@
return mLastReportWallClockNs;
};
- virtual void dropData(const uint64_t dropTimeNs);
+ virtual void dropData(const int64_t dropTimeNs);
- // Config source owner can call onDumpReport() to get all the metrics collected.
- virtual void onDumpReport(const uint64_t dumpTimeNs,
+ virtual void onDumpReport(const int64_t dumpTimeNs,
+ const bool include_current_partial_bucket,
android::util::ProtoOutputStream* protoOutput);
// Computes the total byte size of all metrics managed by a single config source.
// Does not change the state.
virtual size_t byteSize();
+
private:
+ // For test only.
+ inline int64_t getTtlEndNs() const { return mTtlEndNs; }
+
const ConfigKey mConfigKey;
sp<UidMap> mUidMap;
bool mConfigValid = false;
+ const int64_t mTtlNs;
+ int64_t mTtlEndNs;
+
int64_t mLastReportTimeNs;
int64_t mLastReportWallClockNs;
@@ -189,6 +206,7 @@
FRIEND_TEST(AnomalyDetectionE2eTest, TestDurationMetric_SUM_long_refractory_period);
FRIEND_TEST(AlarmE2eTest, TestMultipleAlarms);
+ FRIEND_TEST(ConfigTtlE2eTest, TestCountMetric);
};
} // namespace statsd
diff --git a/cmds/statsd/src/metrics/ValueMetricProducer.cpp b/cmds/statsd/src/metrics/ValueMetricProducer.cpp
index d0f510d..51fac8c 100644
--- a/cmds/statsd/src/metrics/ValueMetricProducer.cpp
+++ b/cmds/statsd/src/metrics/ValueMetricProducer.cpp
@@ -63,7 +63,7 @@
ValueMetricProducer::ValueMetricProducer(const ConfigKey& key, const ValueMetric& metric,
const int conditionIndex,
const sp<ConditionWizard>& wizard, const int pullTagId,
- const uint64_t startTimeNs,
+ const int64_t startTimeNs,
shared_ptr<StatsPullerManager> statsPullerManager)
: MetricProducer(metric.id(), key, startTimeNs, conditionIndex, wizard),
mValueField(metric.value_field()),
@@ -124,7 +124,7 @@
ValueMetricProducer::ValueMetricProducer(const ConfigKey& key, const ValueMetric& metric,
const int conditionIndex,
const sp<ConditionWizard>& wizard, const int pullTagId,
- const uint64_t startTimeNs)
+ const int64_t startTimeNs)
: ValueMetricProducer(key, metric, conditionIndex, wizard, pullTagId, startTimeNs,
make_shared<StatsPullerManager>()) {
}
@@ -137,19 +137,24 @@
}
void ValueMetricProducer::onSlicedConditionMayChangeLocked(bool overallCondition,
- const uint64_t eventTime) {
+ const int64_t eventTime) {
VLOG("Metric %lld onSlicedConditionMayChange", (long long)mMetricId);
}
-void ValueMetricProducer::dropDataLocked(const uint64_t dropTimeNs) {
+void ValueMetricProducer::dropDataLocked(const int64_t dropTimeNs) {
flushIfNeededLocked(dropTimeNs);
mPastBuckets.clear();
}
-void ValueMetricProducer::onDumpReportLocked(const uint64_t dumpTimeNs,
+void ValueMetricProducer::onDumpReportLocked(const int64_t dumpTimeNs,
+ const bool include_current_partial_bucket,
ProtoOutputStream* protoOutput) {
VLOG("metric %lld dump report now...", (long long)mMetricId);
- flushIfNeededLocked(dumpTimeNs);
+ if (include_current_partial_bucket) {
+ flushLocked(dumpTimeNs);
+ } else {
+ flushIfNeededLocked(dumpTimeNs);
+ }
if (mPastBuckets.empty()) {
return;
}
@@ -197,7 +202,7 @@
}
void ValueMetricProducer::onConditionChangedLocked(const bool condition,
- const uint64_t eventTimeNs) {
+ const int64_t eventTimeNs) {
mCondition = condition;
if (eventTimeNs < mCurrentBucketStartTimeNs) {
@@ -231,8 +236,8 @@
}
// For scheduled pulled data, the effective event time is snap to the nearest
// bucket boundary to make bucket finalize.
- uint64_t realEventTime = allData.at(0)->GetElapsedTimestampNs();
- uint64_t eventTime = mStartTimeNs +
+ int64_t realEventTime = allData.at(0)->GetElapsedTimestampNs();
+ int64_t eventTime = mStartTimeNs +
((realEventTime - mStartTimeNs) / mBucketSizeNs) * mBucketSizeNs;
mCondition = false;
@@ -290,7 +295,7 @@
const size_t matcherIndex, const MetricDimensionKey& eventKey,
const ConditionKey& conditionKey, bool condition,
const LogEvent& event) {
- uint64_t eventTimeNs = event.GetElapsedTimestampNs();
+ int64_t eventTimeNs = event.GetElapsedTimestampNs();
if (eventTimeNs < mCurrentBucketStartTimeNs) {
VLOG("Skip event due to late arrival: %lld vs %lld", (long long)eventTimeNs,
(long long)mCurrentBucketStartTimeNs);
@@ -349,8 +354,8 @@
}
}
-void ValueMetricProducer::flushIfNeededLocked(const uint64_t& eventTimeNs) {
- uint64_t currentBucketEndTimeNs = getCurrentBucketEndTimeNs();
+void ValueMetricProducer::flushIfNeededLocked(const int64_t& eventTimeNs) {
+ int64_t currentBucketEndTimeNs = getCurrentBucketEndTimeNs();
if (currentBucketEndTimeNs > eventTimeNs) {
VLOG("eventTime is %lld, less than next bucket start time %lld", (long long)eventTimeNs,
@@ -371,10 +376,10 @@
(long long)mCurrentBucketStartTimeNs);
}
-void ValueMetricProducer::flushCurrentBucketLocked(const uint64_t& eventTimeNs) {
+void ValueMetricProducer::flushCurrentBucketLocked(const int64_t& eventTimeNs) {
VLOG("finalizing bucket for %ld, dumping %d slices", (long)mCurrentBucketStartTimeNs,
(int)mCurrentSlicedBucket.size());
- uint64_t fullBucketEndTimeNs = getCurrentBucketEndTimeNs();
+ int64_t fullBucketEndTimeNs = getCurrentBucketEndTimeNs();
ValueBucket info;
info.mBucketStartNs = mCurrentBucketStartTimeNs;
diff --git a/cmds/statsd/src/metrics/ValueMetricProducer.h b/cmds/statsd/src/metrics/ValueMetricProducer.h
index 45d9531..b5f6429 100644
--- a/cmds/statsd/src/metrics/ValueMetricProducer.h
+++ b/cmds/statsd/src/metrics/ValueMetricProducer.h
@@ -40,14 +40,14 @@
public:
ValueMetricProducer(const ConfigKey& key, const ValueMetric& valueMetric,
const int conditionIndex, const sp<ConditionWizard>& wizard,
- const int pullTagId, const uint64_t startTimeNs);
+ const int pullTagId, const int64_t startTimeNs);
virtual ~ValueMetricProducer();
void onDataPulled(const std::vector<std::shared_ptr<LogEvent>>& data) override;
// ValueMetric needs special logic if it's a pulled atom.
- void notifyAppUpgrade(const uint64_t& eventTimeNs, const string& apk, const int uid,
+ void notifyAppUpgrade(const int64_t& eventTimeNs, const string& apk, const int uid,
const int64_t version) override {
std::lock_guard<std::mutex> lock(mMutex);
@@ -86,14 +86,15 @@
const LogEvent& event) override;
private:
- void onDumpReportLocked(const uint64_t dumpTimeNs,
+ void onDumpReportLocked(const int64_t dumpTimeNs,
+ const bool include_current_partial_bucket,
android::util::ProtoOutputStream* protoOutput) override;
// Internal interface to handle condition change.
- void onConditionChangedLocked(const bool conditionMet, const uint64_t eventTime) override;
+ void onConditionChangedLocked(const bool conditionMet, const int64_t eventTime) override;
// Internal interface to handle sliced condition change.
- void onSlicedConditionMayChangeLocked(bool overallCondition, const uint64_t eventTime) override;
+ void onSlicedConditionMayChangeLocked(bool overallCondition, const int64_t eventTime) override;
// Internal function to calculate the current used bytes.
size_t byteSizeLocked() const override;
@@ -101,11 +102,11 @@
void dumpStatesLocked(FILE* out, bool verbose) const override;
// Util function to flush the old packet.
- void flushIfNeededLocked(const uint64_t& eventTime) override;
+ void flushIfNeededLocked(const int64_t& eventTime) override;
- void flushCurrentBucketLocked(const uint64_t& eventTimeNs) override;
+ void flushCurrentBucketLocked(const int64_t& eventTimeNs) override;
- void dropDataLocked(const uint64_t dropTimeNs) override;
+ void dropDataLocked(const int64_t dropTimeNs) override;
const FieldMatcher mValueField;
@@ -114,7 +115,7 @@
// for testing
ValueMetricProducer(const ConfigKey& key, const ValueMetric& valueMetric,
const int conditionIndex, const sp<ConditionWizard>& wizard,
- const int pullTagId, const uint64_t startTimeNs,
+ const int pullTagId, const int64_t startTimeNs,
std::shared_ptr<StatsPullerManager> statsPullerManager);
// tagId for pulled data. -1 if this is not pulled
diff --git a/cmds/statsd/src/metrics/duration_helper/DurationTracker.h b/cmds/statsd/src/metrics/duration_helper/DurationTracker.h
index 4132703..149b318 100644
--- a/cmds/statsd/src/metrics/duration_helper/DurationTracker.h
+++ b/cmds/statsd/src/metrics/duration_helper/DurationTracker.h
@@ -52,9 +52,9 @@
};
struct DurationBucket {
- uint64_t mBucketStartNs;
- uint64_t mBucketEndNs;
- uint64_t mDuration;
+ int64_t mBucketStartNs;
+ int64_t mBucketEndNs;
+ int64_t mDuration;
};
class DurationTracker {
@@ -62,8 +62,8 @@
DurationTracker(const ConfigKey& key, const int64_t& id, const MetricDimensionKey& eventKey,
sp<ConditionWizard> wizard, int conditionIndex,
const std::vector<Matcher>& dimensionInCondition, bool nesting,
- uint64_t currentBucketStartNs, uint64_t currentBucketNum, uint64_t startTimeNs,
- uint64_t bucketSizeNs, bool conditionSliced, bool fullLink,
+ int64_t currentBucketStartNs, int64_t currentBucketNum, int64_t startTimeNs,
+ int64_t bucketSizeNs, bool conditionSliced, bool fullLink,
const std::vector<sp<DurationAnomalyTracker>>& anomalyTrackers)
: mConfigKey(key),
mTrackerId(id),
@@ -84,27 +84,27 @@
virtual ~DurationTracker(){};
- virtual unique_ptr<DurationTracker> clone(const uint64_t eventTime) = 0;
+ virtual unique_ptr<DurationTracker> clone(const int64_t eventTime) = 0;
virtual void noteStart(const HashableDimensionKey& key, bool condition,
- const uint64_t eventTime, const ConditionKey& conditionKey) = 0;
- virtual void noteStop(const HashableDimensionKey& key, const uint64_t eventTime,
+ const int64_t eventTime, const ConditionKey& conditionKey) = 0;
+ virtual void noteStop(const HashableDimensionKey& key, const int64_t eventTime,
const bool stopAll) = 0;
- virtual void noteStopAll(const uint64_t eventTime) = 0;
+ virtual void noteStopAll(const int64_t eventTime) = 0;
- virtual void onSlicedConditionMayChange(bool overallCondition, const uint64_t timestamp) = 0;
- virtual void onConditionChanged(bool condition, const uint64_t timestamp) = 0;
+ virtual void onSlicedConditionMayChange(bool overallCondition, const int64_t timestamp) = 0;
+ virtual void onConditionChanged(bool condition, const int64_t timestamp) = 0;
// Flush stale buckets if needed, and return true if the tracker has no on-going duration
// events, so that the owner can safely remove the tracker.
virtual bool flushIfNeeded(
- uint64_t timestampNs,
+ int64_t timestampNs,
std::unordered_map<MetricDimensionKey, std::vector<DurationBucket>>* output) = 0;
// Should only be called during an app upgrade or from this tracker's flushIfNeeded. If from
// an app upgrade, we assume that we're trying to form a partial bucket.
virtual bool flushCurrentBucket(
- const uint64_t& eventTimeNs,
+ const int64_t& eventTimeNs,
std::unordered_map<MetricDimensionKey, std::vector<DurationBucket>>* output) = 0;
// Predict the anomaly timestamp given the current status.
@@ -118,15 +118,15 @@
}
protected:
- uint64_t getCurrentBucketEndTimeNs() const {
+ int64_t getCurrentBucketEndTimeNs() const {
return mStartTimeNs + (mCurrentBucketNum + 1) * mBucketSizeNs;
}
// Starts the anomaly alarm.
- void startAnomalyAlarm(const uint64_t eventTime) {
+ void startAnomalyAlarm(const int64_t eventTime) {
for (auto& anomalyTracker : mAnomalyTrackers) {
if (anomalyTracker != nullptr) {
- const uint64_t alarmTimestampNs =
+ const int64_t alarmTimestampNs =
predictAnomalyTimestampNs(*anomalyTracker, eventTime);
if (alarmTimestampNs > 0) {
anomalyTracker->startAlarm(mEventKey, alarmTimestampNs);
@@ -136,7 +136,7 @@
}
// Stops the anomaly alarm. If it should have already fired, declare the anomaly now.
- void stopAnomalyAlarm(const uint64_t timestamp) {
+ void stopAnomalyAlarm(const int64_t timestamp) {
for (auto& anomalyTracker : mAnomalyTrackers) {
if (anomalyTracker != nullptr) {
anomalyTracker->stopAlarm(mEventKey, timestamp);
@@ -152,7 +152,7 @@
}
}
- void detectAndDeclareAnomaly(const uint64_t& timestamp, const int64_t& currBucketNum,
+ void detectAndDeclareAnomaly(const int64_t& timestamp, const int64_t& currBucketNum,
const int64_t& currentBucketValue) {
for (auto& anomalyTracker : mAnomalyTrackers) {
if (anomalyTracker != nullptr) {
@@ -164,7 +164,7 @@
// Convenience to compute the current bucket's end time, which is always aligned with the
// start time of the metric.
- uint64_t getCurrentBucketEndTimeNs() {
+ int64_t getCurrentBucketEndTimeNs() {
return mStartTimeNs + (mCurrentBucketNum + 1) * mBucketSizeNs;
}
@@ -185,15 +185,15 @@
const bool mNested;
- uint64_t mCurrentBucketStartTimeNs;
+ int64_t mCurrentBucketStartTimeNs;
int64_t mDuration; // current recorded duration result (for partial bucket)
int64_t mDurationFullBucket; // Sum of past partial buckets in current full bucket.
- uint64_t mCurrentBucketNum;
+ int64_t mCurrentBucketNum;
- const uint64_t mStartTimeNs;
+ const int64_t mStartTimeNs;
const bool mConditionSliced;
diff --git a/cmds/statsd/src/metrics/duration_helper/MaxDurationTracker.cpp b/cmds/statsd/src/metrics/duration_helper/MaxDurationTracker.cpp
index 5c1e9c0..6868b8c 100644
--- a/cmds/statsd/src/metrics/duration_helper/MaxDurationTracker.cpp
+++ b/cmds/statsd/src/metrics/duration_helper/MaxDurationTracker.cpp
@@ -28,8 +28,8 @@
const MetricDimensionKey& eventKey,
sp<ConditionWizard> wizard, int conditionIndex,
const vector<Matcher>& dimensionInCondition, bool nesting,
- uint64_t currentBucketStartNs, uint64_t currentBucketNum,
- uint64_t startTimeNs, uint64_t bucketSizeNs,
+ int64_t currentBucketStartNs, int64_t currentBucketNum,
+ int64_t startTimeNs, int64_t bucketSizeNs,
bool conditionSliced, bool fullLink,
const vector<sp<DurationAnomalyTracker>>& anomalyTrackers)
: DurationTracker(key, id, eventKey, wizard, conditionIndex, dimensionInCondition, nesting,
@@ -41,7 +41,7 @@
}
}
-unique_ptr<DurationTracker> MaxDurationTracker::clone(const uint64_t eventTime) {
+unique_ptr<DurationTracker> MaxDurationTracker::clone(const int64_t eventTime) {
auto clonedTracker = make_unique<MaxDurationTracker>(*this);
for (auto it = clonedTracker->mInfos.begin(); it != clonedTracker->mInfos.end();) {
if (it->second.state != kStopped) {
@@ -80,7 +80,7 @@
}
void MaxDurationTracker::noteStart(const HashableDimensionKey& key, bool condition,
- const uint64_t eventTime, const ConditionKey& conditionKey) {
+ const int64_t eventTime, const ConditionKey& conditionKey) {
// this will construct a new DurationInfo if this key didn't exist.
if (hitGuardRail(key)) {
return;
@@ -114,7 +114,7 @@
}
-void MaxDurationTracker::noteStop(const HashableDimensionKey& key, const uint64_t eventTime,
+void MaxDurationTracker::noteStop(const HashableDimensionKey& key, const int64_t eventTime,
bool forceStop) {
VLOG("MaxDuration: key %s stop", key.toString().c_str());
if (mInfos.find(key) == mInfos.end()) {
@@ -175,7 +175,7 @@
return false;
}
-void MaxDurationTracker::noteStopAll(const uint64_t eventTime) {
+void MaxDurationTracker::noteStopAll(const int64_t eventTime) {
std::set<HashableDimensionKey> keys;
for (const auto& pair : mInfos) {
keys.insert(pair.first);
@@ -186,14 +186,14 @@
}
bool MaxDurationTracker::flushCurrentBucket(
- const uint64_t& eventTimeNs,
+ const int64_t& eventTimeNs,
std::unordered_map<MetricDimensionKey, std::vector<DurationBucket>>* output) {
VLOG("MaxDurationTracker flushing.....");
// adjust the bucket start time
int numBucketsForward = 0;
- uint64_t fullBucketEnd = getCurrentBucketEndTimeNs();
- uint64_t currentBucketEndTimeNs;
+ int64_t fullBucketEnd = getCurrentBucketEndTimeNs();
+ int64_t currentBucketEndTimeNs;
if (eventTimeNs >= fullBucketEnd) {
numBucketsForward = 1 + (eventTimeNs - fullBucketEnd) / mBucketSizeNs;
currentBucketEndTimeNs = fullBucketEnd;
@@ -238,7 +238,7 @@
}
bool MaxDurationTracker::flushIfNeeded(
- uint64_t eventTimeNs, unordered_map<MetricDimensionKey, vector<DurationBucket>>* output) {
+ int64_t eventTimeNs, unordered_map<MetricDimensionKey, vector<DurationBucket>>* output) {
if (eventTimeNs < getCurrentBucketEndTimeNs()) {
return false;
}
@@ -246,7 +246,7 @@
}
void MaxDurationTracker::onSlicedConditionMayChange(bool overallCondition,
- const uint64_t timestamp) {
+ const int64_t timestamp) {
// Now for each of the on-going event, check if the condition has changed for them.
for (auto& pair : mInfos) {
if (pair.second.state == kStopped) {
@@ -268,14 +268,14 @@
}
}
-void MaxDurationTracker::onConditionChanged(bool condition, const uint64_t timestamp) {
+void MaxDurationTracker::onConditionChanged(bool condition, const int64_t timestamp) {
for (auto& pair : mInfos) {
noteConditionChanged(pair.first, condition, timestamp);
}
}
void MaxDurationTracker::noteConditionChanged(const HashableDimensionKey& key, bool conditionMet,
- const uint64_t timestamp) {
+ const int64_t timestamp) {
auto it = mInfos.find(key);
if (it == mInfos.end()) {
return;
diff --git a/cmds/statsd/src/metrics/duration_helper/MaxDurationTracker.h b/cmds/statsd/src/metrics/duration_helper/MaxDurationTracker.h
index 884e8ac..8e8f2cd 100644
--- a/cmds/statsd/src/metrics/duration_helper/MaxDurationTracker.h
+++ b/cmds/statsd/src/metrics/duration_helper/MaxDurationTracker.h
@@ -31,30 +31,30 @@
MaxDurationTracker(const ConfigKey& key, const int64_t& id, const MetricDimensionKey& eventKey,
sp<ConditionWizard> wizard, int conditionIndex,
const std::vector<Matcher>& dimensionInCondition, bool nesting,
- uint64_t currentBucketStartNs, uint64_t currentBucketNum,
- uint64_t startTimeNs, uint64_t bucketSizeNs, bool conditionSliced,
+ int64_t currentBucketStartNs, int64_t currentBucketNum,
+ int64_t startTimeNs, int64_t bucketSizeNs, bool conditionSliced,
bool fullLink,
const std::vector<sp<DurationAnomalyTracker>>& anomalyTrackers);
MaxDurationTracker(const MaxDurationTracker& tracker) = default;
- unique_ptr<DurationTracker> clone(const uint64_t eventTime) override;
+ unique_ptr<DurationTracker> clone(const int64_t eventTime) override;
- void noteStart(const HashableDimensionKey& key, bool condition, const uint64_t eventTime,
+ void noteStart(const HashableDimensionKey& key, bool condition, const int64_t eventTime,
const ConditionKey& conditionKey) override;
- void noteStop(const HashableDimensionKey& key, const uint64_t eventTime,
+ void noteStop(const HashableDimensionKey& key, const int64_t eventTime,
const bool stopAll) override;
- void noteStopAll(const uint64_t eventTime) override;
+ void noteStopAll(const int64_t eventTime) override;
bool flushIfNeeded(
- uint64_t timestampNs,
+ int64_t timestampNs,
std::unordered_map<MetricDimensionKey, std::vector<DurationBucket>>* output) override;
bool flushCurrentBucket(
- const uint64_t& eventTimeNs,
+ const int64_t& eventTimeNs,
std::unordered_map<MetricDimensionKey, std::vector<DurationBucket>>*) override;
- void onSlicedConditionMayChange(bool overallCondition, const uint64_t timestamp) override;
- void onConditionChanged(bool condition, const uint64_t timestamp) override;
+ void onSlicedConditionMayChange(bool overallCondition, const int64_t timestamp) override;
+ void onConditionChanged(bool condition, const int64_t timestamp) override;
int64_t predictAnomalyTimestampNs(const DurationAnomalyTracker& anomalyTracker,
const int64_t currentTimestamp) const override;
@@ -67,7 +67,7 @@
std::unordered_map<HashableDimensionKey, DurationInfo> mInfos;
void noteConditionChanged(const HashableDimensionKey& key, bool conditionMet,
- const uint64_t timestamp);
+ const int64_t timestamp);
// return true if we should not allow newKey to be tracked because we are above the threshold
bool hitGuardRail(const HashableDimensionKey& newKey);
diff --git a/cmds/statsd/src/metrics/duration_helper/OringDurationTracker.cpp b/cmds/statsd/src/metrics/duration_helper/OringDurationTracker.cpp
index 50db9a0..b833dfc 100644
--- a/cmds/statsd/src/metrics/duration_helper/OringDurationTracker.cpp
+++ b/cmds/statsd/src/metrics/duration_helper/OringDurationTracker.cpp
@@ -27,8 +27,8 @@
OringDurationTracker::OringDurationTracker(
const ConfigKey& key, const int64_t& id, const MetricDimensionKey& eventKey,
sp<ConditionWizard> wizard, int conditionIndex, const vector<Matcher>& dimensionInCondition,
- bool nesting, uint64_t currentBucketStartNs, uint64_t currentBucketNum,
- uint64_t startTimeNs, uint64_t bucketSizeNs, bool conditionSliced, bool fullLink,
+ bool nesting, int64_t currentBucketStartNs, int64_t currentBucketNum,
+ int64_t startTimeNs, int64_t bucketSizeNs, bool conditionSliced, bool fullLink,
const vector<sp<DurationAnomalyTracker>>& anomalyTrackers)
: DurationTracker(key, id, eventKey, wizard, conditionIndex, dimensionInCondition, nesting,
currentBucketStartNs, currentBucketNum, startTimeNs, bucketSizeNs,
@@ -42,7 +42,7 @@
}
}
-unique_ptr<DurationTracker> OringDurationTracker::clone(const uint64_t eventTime) {
+unique_ptr<DurationTracker> OringDurationTracker::clone(const int64_t eventTime) {
auto clonedTracker = make_unique<OringDurationTracker>(*this);
clonedTracker->mLastStartTime = eventTime;
clonedTracker->mDuration = 0;
@@ -69,7 +69,7 @@
}
void OringDurationTracker::noteStart(const HashableDimensionKey& key, bool condition,
- const uint64_t eventTime, const ConditionKey& conditionKey) {
+ const int64_t eventTime, const ConditionKey& conditionKey) {
if (hitGuardRail(key)) {
return;
}
@@ -90,7 +90,7 @@
VLOG("Oring: %s start, condition %d", key.toString().c_str(), condition);
}
-void OringDurationTracker::noteStop(const HashableDimensionKey& key, const uint64_t timestamp,
+void OringDurationTracker::noteStop(const HashableDimensionKey& key, const int64_t timestamp,
const bool stopAll) {
VLOG("Oring: %s stop", key.toString().c_str());
auto it = mStarted.find(key);
@@ -121,7 +121,7 @@
}
}
-void OringDurationTracker::noteStopAll(const uint64_t timestamp) {
+void OringDurationTracker::noteStopAll(const int64_t timestamp) {
if (!mStarted.empty()) {
mDuration += (timestamp - mLastStartTime);
VLOG("Oring Stop all: record duration %lld %lld ", (long long)timestamp - mLastStartTime,
@@ -136,7 +136,7 @@
}
bool OringDurationTracker::flushCurrentBucket(
- const uint64_t& eventTimeNs,
+ const int64_t& eventTimeNs,
std::unordered_map<MetricDimensionKey, std::vector<DurationBucket>>* output) {
VLOG("OringDurationTracker Flushing.............");
@@ -144,8 +144,8 @@
// MetricProducer#notifyAppUpgrade.
int numBucketsForward = 0;
- uint64_t fullBucketEnd = getCurrentBucketEndTimeNs();
- uint64_t currentBucketEndTimeNs;
+ int64_t fullBucketEnd = getCurrentBucketEndTimeNs();
+ int64_t currentBucketEndTimeNs;
if (eventTimeNs >= fullBucketEnd) {
numBucketsForward = 1 + (eventTimeNs - fullBucketEnd) / mBucketSizeNs;
@@ -207,7 +207,7 @@
}
bool OringDurationTracker::flushIfNeeded(
- uint64_t eventTimeNs, unordered_map<MetricDimensionKey, vector<DurationBucket>>* output) {
+ int64_t eventTimeNs, unordered_map<MetricDimensionKey, vector<DurationBucket>>* output) {
if (eventTimeNs < getCurrentBucketEndTimeNs()) {
return false;
}
@@ -215,7 +215,7 @@
}
void OringDurationTracker::onSlicedConditionMayChange(bool overallCondition,
- const uint64_t timestamp) {
+ const int64_t timestamp) {
vector<pair<HashableDimensionKey, int>> startedToPaused;
vector<pair<HashableDimensionKey, int>> pausedToStarted;
if (!mStarted.empty()) {
@@ -297,7 +297,7 @@
}
}
-void OringDurationTracker::onConditionChanged(bool condition, const uint64_t timestamp) {
+void OringDurationTracker::onConditionChanged(bool condition, const int64_t timestamp) {
if (condition) {
if (!mPaused.empty()) {
VLOG("Condition true, all started");
diff --git a/cmds/statsd/src/metrics/duration_helper/OringDurationTracker.h b/cmds/statsd/src/metrics/duration_helper/OringDurationTracker.h
index 987e28e..8e73256 100644
--- a/cmds/statsd/src/metrics/duration_helper/OringDurationTracker.h
+++ b/cmds/statsd/src/metrics/duration_helper/OringDurationTracker.h
@@ -30,29 +30,29 @@
OringDurationTracker(const ConfigKey& key, const int64_t& id,
const MetricDimensionKey& eventKey, sp<ConditionWizard> wizard,
int conditionIndex, const std::vector<Matcher>& dimensionInCondition,
- bool nesting, uint64_t currentBucketStartNs, uint64_t currentBucketNum,
- uint64_t startTimeNs, uint64_t bucketSizeNs, bool conditionSliced,
+ bool nesting, int64_t currentBucketStartNs, int64_t currentBucketNum,
+ int64_t startTimeNs, int64_t bucketSizeNs, bool conditionSliced,
bool fullLink,
const std::vector<sp<DurationAnomalyTracker>>& anomalyTrackers);
OringDurationTracker(const OringDurationTracker& tracker) = default;
- unique_ptr<DurationTracker> clone(const uint64_t eventTime) override;
+ unique_ptr<DurationTracker> clone(const int64_t eventTime) override;
- void noteStart(const HashableDimensionKey& key, bool condition, const uint64_t eventTime,
+ void noteStart(const HashableDimensionKey& key, bool condition, const int64_t eventTime,
const ConditionKey& conditionKey) override;
- void noteStop(const HashableDimensionKey& key, const uint64_t eventTime,
+ void noteStop(const HashableDimensionKey& key, const int64_t eventTime,
const bool stopAll) override;
- void noteStopAll(const uint64_t eventTime) override;
+ void noteStopAll(const int64_t eventTime) override;
- void onSlicedConditionMayChange(bool overallCondition, const uint64_t timestamp) override;
- void onConditionChanged(bool condition, const uint64_t timestamp) override;
+ void onSlicedConditionMayChange(bool overallCondition, const int64_t timestamp) override;
+ void onConditionChanged(bool condition, const int64_t timestamp) override;
bool flushCurrentBucket(
- const uint64_t& eventTimeNs,
+ const int64_t& eventTimeNs,
std::unordered_map<MetricDimensionKey, std::vector<DurationBucket>>* output) override;
bool flushIfNeeded(
- uint64_t timestampNs,
+ int64_t timestampNs,
std::unordered_map<MetricDimensionKey, std::vector<DurationBucket>>* output) override;
int64_t predictAnomalyTimestampNs(const DurationAnomalyTracker& anomalyTracker,
diff --git a/cmds/statsd/src/metrics/metrics_manager_util.cpp b/cmds/statsd/src/metrics/metrics_manager_util.cpp
index b7c5795..566d34e 100644
--- a/cmds/statsd/src/metrics/metrics_manager_util.cpp
+++ b/cmds/statsd/src/metrics/metrics_manager_util.cpp
@@ -263,15 +263,14 @@
}
bool initMetrics(const ConfigKey& key, const StatsdConfig& config, const long timeBaseSec,
- const unordered_map<int64_t, int>& logTrackerMap,
+ UidMap& uidMap, const unordered_map<int64_t, int>& logTrackerMap,
const unordered_map<int64_t, int>& conditionTrackerMap,
const vector<sp<LogMatchingTracker>>& allAtomMatchers,
vector<sp<ConditionTracker>>& allConditionTrackers,
vector<sp<MetricProducer>>& allMetricProducers,
unordered_map<int, std::vector<int>>& conditionToMetricMap,
unordered_map<int, std::vector<int>>& trackerToMetricMap,
- unordered_map<int64_t, int>& metricMap,
- std::set<int64_t> &noReportMetricIds) {
+ unordered_map<int64_t, int>& metricMap, std::set<int64_t>& noReportMetricIds) {
sp<ConditionWizard> wizard = new ConditionWizard(allConditionTrackers);
const int allMetricsCount = config.count_metric_size() + config.duration_metric_size() +
config.event_metric_size() + config.value_metric_size();
@@ -538,6 +537,9 @@
}
noReportMetricIds.insert(no_report_metric);
}
+ for (auto it : allMetricProducers) {
+ uidMap.addListener(it);
+ }
return true;
}
@@ -642,12 +644,10 @@
return true;
}
-bool initStatsdConfig(const ConfigKey& key, const StatsdConfig& config,
- const UidMap& uidMap,
+bool initStatsdConfig(const ConfigKey& key, const StatsdConfig& config, UidMap& uidMap,
const sp<AlarmMonitor>& anomalyAlarmMonitor,
- const sp<AlarmMonitor>& periodicAlarmMonitor,
- const long timeBaseSec, const long currentTimeSec,
- set<int>& allTagIds,
+ const sp<AlarmMonitor>& periodicAlarmMonitor, const long timeBaseSec,
+ const long currentTimeSec, set<int>& allTagIds,
vector<sp<LogMatchingTracker>>& allAtomMatchers,
vector<sp<ConditionTracker>>& allConditionTrackers,
vector<sp<MetricProducer>>& allMetricProducers,
@@ -656,7 +656,7 @@
unordered_map<int, std::vector<int>>& conditionToMetricMap,
unordered_map<int, std::vector<int>>& trackerToMetricMap,
unordered_map<int, std::vector<int>>& trackerToConditionMap,
- std::set<int64_t> &noReportMetricIds) {
+ std::set<int64_t>& noReportMetricIds) {
unordered_map<int64_t, int> logTrackerMap;
unordered_map<int64_t, int> conditionTrackerMap;
unordered_map<int64_t, int> metricProducerMap;
@@ -673,9 +673,10 @@
return false;
}
- if (!initMetrics(key, config, timeBaseSec, logTrackerMap, conditionTrackerMap, allAtomMatchers,
- allConditionTrackers, allMetricProducers, conditionToMetricMap,
- trackerToMetricMap, metricProducerMap, noReportMetricIds)) {
+ if (!initMetrics(key, config, timeBaseSec, uidMap, logTrackerMap, conditionTrackerMap,
+ allAtomMatchers, allConditionTrackers, allMetricProducers,
+ conditionToMetricMap, trackerToMetricMap, metricProducerMap,
+ noReportMetricIds)) {
ALOGE("initMetricProducers failed");
return false;
}
diff --git a/cmds/statsd/src/metrics/metrics_manager_util.h b/cmds/statsd/src/metrics/metrics_manager_util.h
index 3754ae0..0ebdcf9 100644
--- a/cmds/statsd/src/metrics/metrics_manager_util.h
+++ b/cmds/statsd/src/metrics/metrics_manager_util.h
@@ -81,7 +81,7 @@
// the list of MetricProducer index
// [trackerToMetricMap]: contains the mapping from log tracker to MetricProducer index.
bool initMetrics(
- const ConfigKey& key, const StatsdConfig& config, const long timeBaseSec,
+ const ConfigKey& key, const StatsdConfig& config, const long timeBaseSec, UidMap& uidMap,
const std::unordered_map<int64_t, int>& logTrackerMap,
const std::unordered_map<int64_t, int>& conditionTrackerMap,
const std::unordered_map<int, std::vector<MetricConditionLink>>& eventConditionLinks,
@@ -90,16 +90,14 @@
std::vector<sp<MetricProducer>>& allMetricProducers,
std::unordered_map<int, std::vector<int>>& conditionToMetricMap,
std::unordered_map<int, std::vector<int>>& trackerToMetricMap,
- std::set<int64_t> &noReportMetricIds);
+ std::set<int64_t>& noReportMetricIds);
// Initialize MetricsManager from StatsdConfig.
// Parameters are the members of MetricsManager. See MetricsManager for declaration.
-bool initStatsdConfig(const ConfigKey& key, const StatsdConfig& config,
- const UidMap& uidMap,
+bool initStatsdConfig(const ConfigKey& key, const StatsdConfig& config, UidMap& uidMap,
const sp<AlarmMonitor>& anomalyAlarmMonitor,
- const sp<AlarmMonitor>& periodicAlarmMonitor,
- const long timeBaseSec, const long currentTimeSec,
- std::set<int>& allTagIds,
+ const sp<AlarmMonitor>& periodicAlarmMonitor, const long timeBaseSec,
+ const long currentTimeSec, std::set<int>& allTagIds,
std::vector<sp<LogMatchingTracker>>& allAtomMatchers,
std::vector<sp<ConditionTracker>>& allConditionTrackers,
std::vector<sp<MetricProducer>>& allMetricProducers,
@@ -108,7 +106,7 @@
std::unordered_map<int, std::vector<int>>& conditionToMetricMap,
std::unordered_map<int, std::vector<int>>& trackerToMetricMap,
std::unordered_map<int, std::vector<int>>& trackerToConditionMap,
- std::set<int64_t> &noReportMetricIds);
+ std::set<int64_t>& noReportMetricIds);
bool isStateTracker(const SimplePredicate& simplePredicate, std::vector<Matcher>* primaryKeys);
diff --git a/cmds/statsd/src/packages/PackageInfoListener.h b/cmds/statsd/src/packages/PackageInfoListener.h
index 03cb364..fcdbe69 100644
--- a/cmds/statsd/src/packages/PackageInfoListener.h
+++ b/cmds/statsd/src/packages/PackageInfoListener.h
@@ -28,15 +28,15 @@
public:
// Uid map will notify this listener that the app with apk name and uid has been upgraded to
// the specified version.
- virtual void notifyAppUpgrade(const uint64_t& eventTimeNs, const std::string& apk,
+ virtual void notifyAppUpgrade(const int64_t& eventTimeNs, const std::string& apk,
const int uid, const int64_t version) = 0;
// Notify interested listeners that the given apk and uid combination no longer exits.
- virtual void notifyAppRemoved(const uint64_t& eventTimeNs, const std::string& apk,
+ virtual void notifyAppRemoved(const int64_t& eventTimeNs, const std::string& apk,
const int uid) = 0;
// Notify the listener that the UidMap snapshot is available.
- virtual void onUidMapReceived(const uint64_t& eventTimeNs) = 0;
+ virtual void onUidMapReceived(const int64_t& eventTimeNs) = 0;
};
} // namespace statsd
diff --git a/cmds/statsd/src/packages/UidMap.cpp b/cmds/statsd/src/packages/UidMap.cpp
index 8c8152d..b3425a4 100644
--- a/cmds/statsd/src/packages/UidMap.cpp
+++ b/cmds/statsd/src/packages/UidMap.cpp
@@ -45,6 +45,7 @@
const int FIELD_ID_SNAPSHOT_PACKAGE_NAME = 1;
const int FIELD_ID_SNAPSHOT_PACKAGE_VERSION = 2;
const int FIELD_ID_SNAPSHOT_PACKAGE_UID = 3;
+const int FIELD_ID_SNAPSHOT_PACKAGE_DELETED = 4;
const int FIELD_ID_SNAPSHOT_TIMESTAMP = 1;
const int FIELD_ID_SNAPSHOT_PACKAGE_INFO = 2;
const int FIELD_ID_SNAPSHOTS = 1;
@@ -53,7 +54,8 @@
const int FIELD_ID_CHANGE_TIMESTAMP = 2;
const int FIELD_ID_CHANGE_PACKAGE = 3;
const int FIELD_ID_CHANGE_UID = 4;
-const int FIELD_ID_CHANGE_VERSION = 5;
+const int FIELD_ID_CHANGE_NEW_VERSION = 5;
+const int FIELD_ID_CHANGE_PREV_VERSION = 6;
UidMap::UidMap() : mBytesUsed(0) {}
@@ -62,13 +64,8 @@
bool UidMap::hasApp(int uid, const string& packageName) const {
lock_guard<mutex> lock(mMutex);
- auto range = mMap.equal_range(uid);
- for (auto it = range.first; it != range.second; ++it) {
- if (it->second.packageName == packageName) {
- return true;
- }
- }
- return false;
+ auto it = mMap.find(std::make_pair(uid, packageName));
+ return it != mMap.end() && !it->second.deleted;
}
string UidMap::normalizeAppName(const string& appName) const {
@@ -84,10 +81,10 @@
std::set<string> UidMap::getAppNamesFromUidLocked(const int32_t& uid, bool returnNormalized) const {
std::set<string> names;
- auto range = mMap.equal_range(uid);
- for (auto it = range.first; it != range.second; ++it) {
- names.insert(returnNormalized ?
- normalizeAppName(it->second.packageName) : it->second.packageName);
+ for (const auto& kv : mMap) {
+ if (kv.first.first == uid && !kv.second.deleted) {
+ names.insert(returnNormalized ? normalizeAppName(kv.first.second) : kv.first.second);
+ }
}
return names;
}
@@ -95,18 +92,11 @@
int64_t UidMap::getAppVersion(int uid, const string& packageName) const {
lock_guard<mutex> lock(mMutex);
- auto range = mMap.equal_range(uid);
- for (auto it = range.first; it != range.second; ++it) {
- if (it->second.packageName == packageName) {
- return it->second.versionCode;
- }
+ auto it = mMap.find(std::make_pair(uid, packageName));
+ if (it == mMap.end() || it->second.deleted) {
+ return 0;
}
- return 0;
-}
-
-void UidMap::updateMap(const vector<int32_t>& uid, const vector<int64_t>& versionCode,
- const vector<String16>& packageName) {
- updateMap(getElapsedRealtimeNs(), uid, versionCode, packageName);
+ return it->second.versionCode;
}
void UidMap::updateMap(const int64_t& timestamp, const vector<int32_t>& uid,
@@ -115,20 +105,31 @@
{
lock_guard<mutex> lock(mMutex); // Exclusively lock for updates.
- mMap.clear();
- vector<const SnapshotPackageInfo> infos;
- for (size_t j = 0; j < uid.size(); j++) {
- string package = string(String8(packageName[j]).string());
- mMap.insert(make_pair(uid[j], AppData(package, versionCode[j])));
- infos.emplace_back(package, versionCode[j], uid[j]);
+ std::unordered_map<std::pair<int, string>, AppData, PairHash> deletedApps;
+
+ // Copy all the deleted apps.
+ for (const auto& kv : mMap) {
+ if (kv.second.deleted) {
+ deletedApps[kv.first] = kv.second;
+ }
}
- mSnapshots.emplace_back(timestamp, infos);
+ mMap.clear();
+ for (size_t j = 0; j < uid.size(); j++) {
+ string package = string(String8(packageName[j]).string());
+ mMap[std::make_pair(uid[j], package)] = AppData(versionCode[j]);
+ }
- mBytesUsed += mSnapshots.back().bytes;
+ for (const auto& kv : deletedApps) {
+ auto mMapIt = mMap.find(kv.first);
+ if (mMapIt != mMap.end()) {
+ // Insert this deleted app back into the current map.
+ mMap[kv.first] = kv.second;
+ }
+ }
+
ensureBytesUsedBelowLimit();
StatsdStats::getInstance().setCurrentUidMapMemory(mBytesUsed);
- StatsdStats::getInstance().setUidMapSnapshots(mSnapshots.size());
getListenerListCopyLocked(&broadcastList);
}
// To avoid invoking callback while holding the internal lock. we get a copy of the listener
@@ -144,38 +145,34 @@
}
}
-void UidMap::updateApp(const String16& app_16, const int32_t& uid, const int64_t& versionCode) {
- updateApp(getElapsedRealtimeNs(), app_16, uid, versionCode);
-}
-
void UidMap::updateApp(const int64_t& timestamp, const String16& app_16, const int32_t& uid,
const int64_t& versionCode) {
vector<wp<PackageInfoListener>> broadcastList;
string appName = string(String8(app_16).string());
{
lock_guard<mutex> lock(mMutex);
-
- mChanges.emplace_back(false, timestamp, appName, uid, versionCode);
+ int32_t prevVersion = 0;
+ bool found = false;
+ auto it = mMap.find(std::make_pair(uid, appName));
+ if (it != mMap.end()) {
+ found = true;
+ prevVersion = it->second.versionCode;
+ it->second.versionCode = versionCode;
+ it->second.deleted = false;
+ }
+ if (!found) {
+ // Otherwise, we need to add an app at this uid.
+ mMap[std::make_pair(uid, appName)] = AppData(versionCode);
+ } else {
+ // Only notify the listeners if this is an app upgrade. If this app is being installed
+ // for the first time, then we don't notify the listeners.
+ getListenerListCopyLocked(&broadcastList);
+ }
+ mChanges.emplace_back(false, timestamp, appName, uid, versionCode, prevVersion);
mBytesUsed += kBytesChangeRecord;
ensureBytesUsedBelowLimit();
StatsdStats::getInstance().setCurrentUidMapMemory(mBytesUsed);
StatsdStats::getInstance().setUidMapChanges(mChanges.size());
-
- auto range = mMap.equal_range(int(uid));
- bool found = false;
- for (auto it = range.first; it != range.second; ++it) {
- // If we find the exact same app name and uid, update the app version directly.
- if (it->second.packageName == appName) {
- it->second.versionCode = versionCode;
- found = true;
- break;
- }
- }
- if (!found) {
- // Otherwise, we need to add an app at this uid.
- mMap.insert(make_pair(uid, AppData(appName, versionCode)));
- }
- getListenerListCopyLocked(&broadcastList);
}
for (auto weakPtr : broadcastList) {
@@ -195,22 +192,14 @@
}
while (mBytesUsed > limit) {
ALOGI("Bytes used %zu is above limit %zu, need to delete something", mBytesUsed, limit);
- if (mSnapshots.size() > 0) {
- mBytesUsed -= mSnapshots.front().bytes;
- mSnapshots.pop_front();
- StatsdStats::getInstance().noteUidMapDropped(1, 0);
- } else if (mChanges.size() > 0) {
+ if (mChanges.size() > 0) {
mBytesUsed -= kBytesChangeRecord;
mChanges.pop_front();
- StatsdStats::getInstance().noteUidMapDropped(0, 1);
+ StatsdStats::getInstance().noteUidMapDropped(1);
}
}
}
-void UidMap::removeApp(const String16& app_16, const int32_t& uid) {
- removeApp(getElapsedRealtimeNs(), app_16, uid);
-}
-
void UidMap::getListenerListCopyLocked(vector<wp<PackageInfoListener>>* output) {
for (auto weakIt = mSubscribers.begin(); weakIt != mSubscribers.end();) {
auto strongPtr = weakIt->promote();
@@ -230,19 +219,26 @@
{
lock_guard<mutex> lock(mMutex);
- mChanges.emplace_back(true, timestamp, app, uid, 0);
+ int32_t prevVersion = 0;
+ auto key = std::make_pair(uid, app);
+ auto it = mMap.find(key);
+ if (it != mMap.end() && !it->second.deleted) {
+ prevVersion = it->second.versionCode;
+ it->second.deleted = true;
+ mDeletedApps.push_back(key);
+ }
+ if (mDeletedApps.size() > StatsdStats::kMaxDeletedAppsInUidMap) {
+ // Delete the oldest one.
+ auto oldest = mDeletedApps.front();
+ mDeletedApps.pop_front();
+ mMap.erase(oldest);
+ StatsdStats::getInstance().noteUidMapAppDeletionDropped();
+ }
+ mChanges.emplace_back(true, timestamp, app, uid, 0, prevVersion);
mBytesUsed += kBytesChangeRecord;
ensureBytesUsedBelowLimit();
StatsdStats::getInstance().setCurrentUidMapMemory(mBytesUsed);
StatsdStats::getInstance().setUidMapChanges(mChanges.size());
-
- auto range = mMap.equal_range(int(uid));
- for (auto it = range.first; it != range.second; ++it) {
- if (it->second.packageName == app) {
- mMap.erase(it);
- break;
- }
- }
getListenerListCopyLocked(&broadcastList);
}
@@ -290,22 +286,20 @@
}
void UidMap::clearOutput() {
- mSnapshots.clear();
mChanges.clear();
// Also update the guardrail trackers.
StatsdStats::getInstance().setUidMapChanges(0);
- StatsdStats::getInstance().setUidMapSnapshots(1);
mBytesUsed = 0;
StatsdStats::getInstance().setCurrentUidMapMemory(mBytesUsed);
}
int64_t UidMap::getMinimumTimestampNs() {
int64_t m = 0;
- for (auto it : mLastUpdatePerConfigKey) {
+ for (const auto& kv : mLastUpdatePerConfigKey) {
if (m == 0) {
- m = it.second;
- } else if (it.second < m) {
- m = it.second;
+ m = kv.second;
+ } else if (kv.second < m) {
+ m = kv.second;
}
}
return m;
@@ -315,10 +309,6 @@
return mBytesUsed;
}
-void UidMap::appendUidMap(const ConfigKey& key, ProtoOutputStream* proto) {
- appendUidMap(getElapsedRealtimeNs(), key, proto);
-}
-
void UidMap::appendUidMap(const int64_t& timestamp, const ConfigKey& key,
ProtoOutputStream* proto) {
lock_guard<mutex> lock(mMutex); // Lock for updates
@@ -332,34 +322,27 @@
(long long)record.timestampNs);
proto->write(FIELD_TYPE_STRING | FIELD_ID_CHANGE_PACKAGE, record.package);
proto->write(FIELD_TYPE_INT32 | FIELD_ID_CHANGE_UID, (int)record.uid);
- proto->write(FIELD_TYPE_INT32 | FIELD_ID_CHANGE_VERSION, (int)record.version);
+ proto->write(FIELD_TYPE_INT32 | FIELD_ID_CHANGE_NEW_VERSION, (int)record.version);
+ proto->write(FIELD_TYPE_INT32 | FIELD_ID_CHANGE_PREV_VERSION, (int)record.prevVersion);
proto->end(changesToken);
}
}
- bool atLeastOneSnapshot = false;
- unsigned int count = 0;
- for (const SnapshotRecord& record : mSnapshots) {
- // Ensure that we include at least the latest snapshot.
- if ((count == mSnapshots.size() - 1 && !atLeastOneSnapshot) ||
- record.timestampNs > mLastUpdatePerConfigKey[key]) {
- uint64_t snapshotsToken =
- proto->start(FIELD_TYPE_MESSAGE | FIELD_COUNT_REPEATED | FIELD_ID_SNAPSHOTS);
- atLeastOneSnapshot = true;
- count++;
- proto->write(FIELD_TYPE_INT64 | FIELD_ID_SNAPSHOT_TIMESTAMP,
- (long long)record.timestampNs);
- for (const SnapshotPackageInfo& info : record.infos) {
- uint64_t token = proto->start(FIELD_TYPE_MESSAGE | FIELD_COUNT_REPEATED |
- FIELD_ID_SNAPSHOT_PACKAGE_INFO);
- proto->write(FIELD_TYPE_STRING | FIELD_ID_SNAPSHOT_PACKAGE_NAME, info.package);
- proto->write(FIELD_TYPE_INT32 | FIELD_ID_SNAPSHOT_PACKAGE_VERSION, info.version);
- proto->write(FIELD_TYPE_INT32 | FIELD_ID_SNAPSHOT_PACKAGE_UID, info.uid);
- proto->end(token);
- }
- proto->end(snapshotsToken);
- }
+ // Write snapshot from current uid map state.
+ uint64_t snapshotsToken =
+ proto->start(FIELD_TYPE_MESSAGE | FIELD_COUNT_REPEATED | FIELD_ID_SNAPSHOTS);
+ proto->write(FIELD_TYPE_INT64 | FIELD_ID_SNAPSHOT_TIMESTAMP, (long long)timestamp);
+ for (const auto& kv : mMap) {
+ uint64_t token = proto->start(FIELD_TYPE_MESSAGE | FIELD_COUNT_REPEATED |
+ FIELD_ID_SNAPSHOT_PACKAGE_INFO);
+ proto->write(FIELD_TYPE_STRING | FIELD_ID_SNAPSHOT_PACKAGE_NAME, kv.first.second);
+ proto->write(FIELD_TYPE_INT32 | FIELD_ID_SNAPSHOT_PACKAGE_VERSION,
+ (int)kv.second.versionCode);
+ proto->write(FIELD_TYPE_INT32 | FIELD_ID_SNAPSHOT_PACKAGE_UID, kv.first.first);
+ proto->write(FIELD_TYPE_BOOL | FIELD_ID_SNAPSHOT_PACKAGE_DELETED, kv.second.deleted);
+ proto->end(token);
}
+ proto->end(snapshotsToken);
int64_t prevMin = getMinimumTimestampNs();
mLastUpdatePerConfigKey[key] = timestamp;
@@ -368,14 +351,6 @@
if (newMin > prevMin) { // Delete anything possible now that the minimum has
// moved forward.
int64_t cutoff_nanos = newMin;
- for (auto it_snapshots = mSnapshots.begin(); it_snapshots != mSnapshots.end();) {
- if (it_snapshots->timestampNs < cutoff_nanos) {
- mBytesUsed -= it_snapshots->bytes;
- it_snapshots = mSnapshots.erase(it_snapshots);
- } else {
- ++it_snapshots;
- }
- }
for (auto it_changes = mChanges.begin(); it_changes != mChanges.end();) {
if (it_changes->timestampNs < cutoff_nanos) {
mBytesUsed -= kBytesChangeRecord;
@@ -384,53 +359,24 @@
++it_changes;
}
}
-
- if (mSnapshots.size() == 0) {
- // Produce another snapshot. This results in extra data being uploaded but
- // helps ensure we can re-construct the UID->app name, versionCode mapping
- // in server.
- vector<const SnapshotPackageInfo> infos;
- for (const auto& it : mMap) {
- infos.emplace_back(it.second.packageName, it.second.versionCode, it.first);
- }
-
- mSnapshots.emplace_back(timestamp, infos);
- mBytesUsed += mSnapshots.back().bytes;
- }
}
StatsdStats::getInstance().setCurrentUidMapMemory(mBytesUsed);
StatsdStats::getInstance().setUidMapChanges(mChanges.size());
- StatsdStats::getInstance().setUidMapSnapshots(mSnapshots.size());
}
void UidMap::printUidMap(FILE* out) const {
lock_guard<mutex> lock(mMutex);
- for (auto it : mMap) {
- fprintf(out, "%s, v%" PRId64 " (%i)\n", it.second.packageName.c_str(),
- it.second.versionCode, it.first);
+ for (const auto& kv : mMap) {
+ if (!kv.second.deleted) {
+ fprintf(out, "%s, v%" PRId64 " (%i)\n", kv.first.second.c_str(), kv.second.versionCode,
+ kv.first.first);
+ }
}
}
void UidMap::OnConfigUpdated(const ConfigKey& key) {
mLastUpdatePerConfigKey[key] = -1;
-
- // Ensure there is at least one snapshot available since this configuration also needs to know
- // what all the uid's represent.
- if (mSnapshots.size() == 0) {
- sp<IStatsCompanionService> statsCompanion = nullptr;
- // Get statscompanion service from service manager
- const sp<IServiceManager> sm(defaultServiceManager());
- if (sm != nullptr) {
- const String16 name("statscompanion");
- statsCompanion = interface_cast<IStatsCompanionService>(sm->checkService(name));
- if (statsCompanion == nullptr) {
- ALOGW("statscompanion service unavailable!");
- return;
- }
- statsCompanion->triggerUidSnapshot();
- }
- }
}
void UidMap::OnConfigRemoved(const ConfigKey& key) {
@@ -441,9 +387,9 @@
lock_guard<mutex> lock(mMutex);
set<int32_t> results;
- for (const auto& pair : mMap) {
- if (pair.second.packageName == package) {
- results.insert(pair.first);
+ for (const auto& kv : mMap) {
+ if (kv.first.second == package && !kv.second.deleted) {
+ results.insert(kv.first.first);
}
}
return results;
diff --git a/cmds/statsd/src/packages/UidMap.h b/cmds/statsd/src/packages/UidMap.h
index a3632d2..7222e85 100644
--- a/cmds/statsd/src/packages/UidMap.h
+++ b/cmds/statsd/src/packages/UidMap.h
@@ -43,10 +43,13 @@
namespace statsd {
struct AppData {
- const string packageName;
int64_t versionCode;
+ bool deleted;
- AppData(const string& a, const int64_t v) : packageName(a), versionCode(v){};
+ // Empty constructor needed for unordered map.
+ AppData() {
+ }
+ AppData(const int64_t v) : versionCode(v), deleted(false){};
};
// When calling appendUidMap, we retrieve all the ChangeRecords since the last
@@ -57,55 +60,21 @@
const string package;
const int32_t uid;
const int32_t version;
+ const int32_t prevVersion;
ChangeRecord(const bool isDeletion, const int64_t timestampNs, const string& package,
- const int32_t uid, const int32_t version)
+ const int32_t uid, const int32_t version, const int32_t prevVersion)
: deletion(isDeletion),
timestampNs(timestampNs),
package(package),
uid(uid),
- version(version) {
+ version(version),
+ prevVersion(prevVersion) {
}
};
const unsigned int kBytesChangeRecord = sizeof(struct ChangeRecord);
-// Storing the int64 for a timestamp is expected to take 10 bytes (could take
-// less because of varint encoding).
-const unsigned int kBytesTimestampField = 10;
-
-struct SnapshotPackageInfo {
- const string package;
- const int32_t version;
- const int32_t uid;
- SnapshotPackageInfo(const string& package, const int32_t version, const int32_t uid)
- : package(package), version(version), uid(uid) {
- }
-};
-
-const unsigned int kBytesSnapshotInfo = sizeof(struct SnapshotPackageInfo);
-
-// When calling appendUidMap, we retrieve all the snapshots since the last
-// timestamp we called appendUidMap for this configuration key.
-struct SnapshotRecord {
- const int64_t timestampNs;
-
- // All the package info known.
- vector<const SnapshotPackageInfo> infos;
-
- // Tracks the number of bytes this snapshot consumes.
- uint32_t bytes;
-
- SnapshotRecord(const int64_t timestampNs, vector<const SnapshotPackageInfo>& infos)
- : timestampNs(timestampNs), infos(infos) {
- bytes = 0;
- for (auto info : infos) {
- bytes += info.package.size() + kBytesSnapshotInfo;
- }
- bytes += kBytesTimestampField;
- }
-};
-
// UidMap keeps track of what the corresponding app name (APK name) and version code for every uid
// at any given moment. This map must be updated by StatsCompanionService.
class UidMap : public virtual android::RefBase {
@@ -117,11 +86,12 @@
* All three inputs must be the same size, and the jth element in each array refers to the same
* tuple, ie. uid[j] corresponds to packageName[j] with versionCode[j].
*/
- void updateMap(const vector<int32_t>& uid, const vector<int64_t>& versionCode,
- const vector<String16>& packageName);
+ void updateMap(const int64_t& timestamp, const vector<int32_t>& uid,
+ const vector<int64_t>& versionCode, const vector<String16>& packageName);
- void updateApp(const String16& packageName, const int32_t& uid, const int64_t& versionCode);
- void removeApp(const String16& packageName, const int32_t& uid);
+ void updateApp(const int64_t& timestamp, const String16& packageName, const int32_t& uid,
+ const int64_t& versionCode);
+ void removeApp(const int64_t& timestamp, const String16& packageName, const int32_t& uid);
// Returns true if the given uid contains the specified app (eg. com.google.android.gms).
bool hasApp(int uid, const string& packageName) const;
@@ -157,7 +127,8 @@
// Gets all snapshots and changes that have occurred since the last output.
// If every config key has received a change or snapshot record, then this
// record is deleted.
- void appendUidMap(const ConfigKey& key, util::ProtoOutputStream* proto);
+ void appendUidMap(const int64_t& timestamp, const ConfigKey& key,
+ util::ProtoOutputStream* proto);
// Forces the output to be cleared. We still generate a snapshot based on the current state.
// This results in extra data uploaded but helps us reconstruct the uid mapping on the server
@@ -173,25 +144,20 @@
std::set<string> getAppNamesFromUidLocked(const int32_t& uid, bool returnNormalized) const;
string normalizeAppName(const string& appName) const;
- void updateMap(const int64_t& timestamp, const vector<int32_t>& uid,
- const vector<int64_t>& versionCode, const vector<String16>& packageName);
-
- void updateApp(const int64_t& timestamp, const String16& packageName, const int32_t& uid,
- const int64_t& versionCode);
- void removeApp(const int64_t& timestamp, const String16& packageName, const int32_t& uid);
-
- void appendUidMap(const int64_t& timestamp, const ConfigKey& key,
- util::ProtoOutputStream* proto);
-
void getListenerListCopyLocked(std::vector<wp<PackageInfoListener>>* output);
// TODO: Use shared_mutex for improved read-locking if a library can be found in Android.
mutable mutex mMutex;
mutable mutex mIsolatedMutex;
- // Maps uid to application data. This must be multimap since there is a feature in Android for
- // multiple apps to share the same uid.
- std::unordered_multimap<int, AppData> mMap;
+ struct PairHash {
+ size_t operator()(std::pair<int, string> p) const noexcept {
+ std::hash<std::string> hash_fn;
+ return hash_fn(std::to_string(p.first) + p.second);
+ }
+ };
+ // Maps uid and package name to application data.
+ std::unordered_map<std::pair<int, string>, AppData, PairHash> mMap;
// Maps isolated uid to the parent uid. Any metrics for an isolated uid will instead contribute
// to the parent uid.
@@ -200,8 +166,8 @@
// Record the changes that can be provided with the uploads.
std::list<ChangeRecord> mChanges;
- // Record the snapshots that can be provided with the uploads.
- std::list<SnapshotRecord> mSnapshots;
+ // Store which uid and apps represent deleted ones.
+ std::list<std::pair<int, string>> mDeletedApps;
// Metric producers that should be notified if there's an upgrade in any app.
set<wp<PackageInfoListener>> mSubscribers;
@@ -228,6 +194,8 @@
// Allows unit-test to access private methods.
FRIEND_TEST(UidMapTest, TestClearingOutput);
+ FRIEND_TEST(UidMapTest, TestRemovedAppRetained);
+ FRIEND_TEST(UidMapTest, TestRemovedAppOverGuardrail);
FRIEND_TEST(UidMapTest, TestOutputIncludesAtLeastOneSnapshot);
FRIEND_TEST(UidMapTest, TestMemoryComputed);
FRIEND_TEST(UidMapTest, TestMemoryGuardrail);
diff --git a/cmds/statsd/src/stats_log.proto b/cmds/statsd/src/stats_log.proto
index 9fd17b6..36b24c8 100644
--- a/cmds/statsd/src/stats_log.proto
+++ b/cmds/statsd/src/stats_log.proto
@@ -155,6 +155,8 @@
optional int64 version = 2;
optional int32 uid = 3;
+
+ optional bool deleted = 4;
}
optional int64 elapsed_timestamp_nanos = 1;
@@ -169,7 +171,8 @@
optional string app = 3;
optional int32 uid = 4;
- optional int64 version = 5;
+ optional int64 new_version = 5;
+ optional int64 prev_version = 6;
}
repeated Change changes = 2;
}
@@ -234,15 +237,16 @@
optional int64 id = 2;
optional int32 creation_time_sec = 3;
optional int32 deletion_time_sec = 4;
+ optional int32 reset_time_sec = 19;
optional int32 metric_count = 5;
optional int32 condition_count = 6;
optional int32 matcher_count = 7;
optional int32 alert_count = 8;
optional bool is_valid = 9;
-
repeated int32 broadcast_sent_time_sec = 10;
repeated int32 data_drop_time_sec = 11;
repeated int32 dump_report_time_sec = 12;
+ repeated int32 dump_report_data_size = 20;
repeated MatcherStats matcher_stats = 13;
repeated ConditionStats condition_stats = 14;
repeated MetricStats metric_stats = 15;
@@ -265,11 +269,10 @@
repeated AtomStats atom_stats = 7;
message UidMapStats {
- optional int32 snapshots = 1;
- optional int32 changes = 2;
- optional int32 bytes_used = 3;
- optional int32 dropped_snapshots = 4;
- optional int32 dropped_changes = 5;
+ optional int32 changes = 1;
+ optional int32 bytes_used = 2;
+ optional int32 dropped_changes = 3;
+ optional int32 deleted_apps = 4;
}
optional UidMapStats uidmap_stats = 8;
@@ -291,4 +294,15 @@
optional int32 error_code = 2;
}
repeated LoggerErrorStats logger_error_stats = 11;
+
+ message PeriodicAlarmStats {
+ optional int32 alarms_registered = 1;
+ }
+ optional PeriodicAlarmStats periodic_alarm_stats = 12;
+
+ message SkippedLogEventStats {
+ optional int32 tag = 1;
+ optional int64 elapsed_timestamp_nanos = 2;
+ }
+ repeated SkippedLogEventStats skipped_log_event_stats = 13;
}
diff --git a/cmds/statsd/src/statsd_config.proto b/cmds/statsd/src/statsd_config.proto
index 687f5ea..870f92e 100644
--- a/cmds/statsd/src/statsd_config.proto
+++ b/cmds/statsd/src/statsd_config.proto
@@ -354,6 +354,8 @@
}
repeated Annotation annotation = 14;
+ optional int64 ttl_in_seconds = 15;
+
// Field number 1000 is reserved for later use.
reserved 1000;
}
diff --git a/cmds/statsd/src/storage/StorageManager.cpp b/cmds/statsd/src/storage/StorageManager.cpp
index 643d2bf..ea8da14 100644
--- a/cmds/statsd/src/storage/StorageManager.cpp
+++ b/cmds/statsd/src/storage/StorageManager.cpp
@@ -252,8 +252,13 @@
}
}
-bool StorageManager::hasIdenticalConfig(const ConfigKey& key,
- const vector<uint8_t>& config) {
+bool StorageManager::readConfigFromDisk(const ConfigKey& key, StatsdConfig* config) {
+ string content;
+ return config != nullptr &&
+ StorageManager::readConfigFromDisk(key, &content) && config->ParseFromString(content);
+}
+
+bool StorageManager::readConfigFromDisk(const ConfigKey& key, string* content) {
unique_ptr<DIR, decltype(&closedir)> dir(opendir(STATS_SERVICE_DIR),
closedir);
if (dir == NULL) {
@@ -262,7 +267,6 @@
}
string suffix = StringPrintf("%d_%lld", key.GetUid(), (long long)key.GetId());
-
dirent* de;
while ((de = readdir(dir.get()))) {
char* name = de->d_name;
@@ -277,13 +281,8 @@
int fd = open(StringPrintf("%s/%s", STATS_SERVICE_DIR, name).c_str(),
O_RDONLY | O_CLOEXEC);
if (fd != -1) {
- string content;
- if (android::base::ReadFdToString(fd, &content)) {
- vector<uint8_t> vec(content.begin(), content.end());
- if (vec == config) {
- close(fd);
- return true;
- }
+ if (android::base::ReadFdToString(fd, content)) {
+ return true;
}
close(fd);
}
@@ -292,6 +291,18 @@
return false;
}
+bool StorageManager::hasIdenticalConfig(const ConfigKey& key,
+ const vector<uint8_t>& config) {
+ string content;
+ if (StorageManager::readConfigFromDisk(key, &content)) {
+ vector<uint8_t> vec(content.begin(), content.end());
+ if (vec == config) {
+ return true;
+ }
+ }
+ return false;
+}
+
void StorageManager::trimToFit(const char* path) {
unique_ptr<DIR, decltype(&closedir)> dir(opendir(path), closedir);
if (dir == NULL) {
diff --git a/cmds/statsd/src/storage/StorageManager.h b/cmds/statsd/src/storage/StorageManager.h
index fb7b085..8953be9 100644
--- a/cmds/statsd/src/storage/StorageManager.h
+++ b/cmds/statsd/src/storage/StorageManager.h
@@ -74,6 +74,13 @@
static void readConfigFromDisk(std::map<ConfigKey, StatsdConfig>& configsMap);
/**
+ * Call to load the specified config from disk. Returns false if the config file does not
+ * exist or error occurs when reading the file.
+ */
+ static bool readConfigFromDisk(const ConfigKey& key, StatsdConfig* config);
+ static bool readConfigFromDisk(const ConfigKey& key, string* config);
+
+ /**
* Trims files in the provided directory to limit the total size, number of
* files, accumulation of outdated files.
*/
diff --git a/cmds/statsd/tests/LogEntryMatcher_test.cpp b/cmds/statsd/tests/LogEntryMatcher_test.cpp
index b0da07b..4c6671d 100644
--- a/cmds/statsd/tests/LogEntryMatcher_test.cpp
+++ b/cmds/statsd/tests/LogEntryMatcher_test.cpp
@@ -146,11 +146,10 @@
attributionMatcher->mutable_matches_tuple()->mutable_field_value_matcher(0)->set_eq_string("pkg0");
EXPECT_FALSE(matchesSimple(uidMap, *simpleMatcher, event));
- uidMap.updateMap({1111, 1111, 2222, 3333, 3333} /* uid list */,
- {1, 1, 2, 1, 2} /* version list */,
- {android::String16("pkg0"), android::String16("pkg1"),
- android::String16("pkg1"), android::String16("Pkg2"),
- android::String16("PkG3")} /* package name list */);
+ uidMap.updateMap(
+ 1, {1111, 1111, 2222, 3333, 3333} /* uid list */, {1, 1, 2, 1, 2} /* version list */,
+ {android::String16("pkg0"), android::String16("pkg1"), android::String16("pkg1"),
+ android::String16("Pkg2"), android::String16("PkG3")} /* package name list */);
EXPECT_TRUE(matchesSimple(uidMap, *simpleMatcher, event));
attributionMatcher->mutable_matches_tuple()->mutable_field_value_matcher(0)
@@ -297,7 +296,7 @@
TEST(AtomMatcherTest, TestNeqAnyStringMatcher) {
UidMap uidMap;
uidMap.updateMap(
- {1111, 1111, 2222, 3333, 3333} /* uid list */, {1, 1, 2, 1, 2} /* version list */,
+ 1, {1111, 1111, 2222, 3333, 3333} /* uid list */, {1, 1, 2, 1, 2} /* version list */,
{android::String16("pkg0"), android::String16("pkg1"), android::String16("pkg1"),
android::String16("Pkg2"), android::String16("PkG3")} /* package name list */);
@@ -372,7 +371,7 @@
TEST(AtomMatcherTest, TestEqAnyStringMatcher) {
UidMap uidMap;
uidMap.updateMap(
- {1111, 1111, 2222, 3333, 3333} /* uid list */, {1, 1, 2, 1, 2} /* version list */,
+ 1, {1111, 1111, 2222, 3333, 3333} /* uid list */, {1, 1, 2, 1, 2} /* version list */,
{android::String16("pkg0"), android::String16("pkg1"), android::String16("pkg1"),
android::String16("Pkg2"), android::String16("PkG3")} /* package name list */);
diff --git a/cmds/statsd/tests/StatsLogProcessor_test.cpp b/cmds/statsd/tests/StatsLogProcessor_test.cpp
index 98f1a59..fb8877a 100644
--- a/cmds/statsd/tests/StatsLogProcessor_test.cpp
+++ b/cmds/statsd/tests/StatsLogProcessor_test.cpp
@@ -53,7 +53,7 @@
MOCK_METHOD0(byteSize, size_t());
- MOCK_METHOD1(dropData, void(const uint64_t dropTimeNs));
+ MOCK_METHOD1(dropData, void(const int64_t dropTimeNs));
};
TEST(StatsLogProcessorTest, TestRateLimitByteSize) {
@@ -126,7 +126,7 @@
TEST(StatsLogProcessorTest, TestUidMapHasSnapshot) {
// Setup simple config key corresponding to empty config.
sp<UidMap> m = new UidMap();
- m->updateMap({1, 2}, {1, 2}, {String16("p1"), String16("p2")});
+ m->updateMap(1, {1, 2}, {1, 2}, {String16("p1"), String16("p2")});
sp<AlarmMonitor> anomalyAlarmMonitor;
sp<AlarmMonitor> subscriberAlarmMonitor;
int broadcastCount = 0;
@@ -139,7 +139,7 @@
// Expect to get no metrics, but snapshot specified above in uidmap.
vector<uint8_t> bytes;
- p.onDumpReport(key, 1, &bytes);
+ p.onDumpReport(key, 1, false, &bytes);
ConfigMetricsReportList output;
output.ParseFromArray(bytes.data(), bytes.size());
@@ -167,7 +167,7 @@
// Expect to get no metrics, but snapshot specified above in uidmap.
vector<uint8_t> bytes;
- p.onDumpReport(key, 1, &bytes);
+ p.onDumpReport(key, 1, false, &bytes);
ConfigMetricsReportList output;
output.ParseFromArray(bytes.data(), bytes.size());
diff --git a/cmds/statsd/tests/UidMap_test.cpp b/cmds/statsd/tests/UidMap_test.cpp
index a9b67e0..2fab975 100644
--- a/cmds/statsd/tests/UidMap_test.cpp
+++ b/cmds/statsd/tests/UidMap_test.cpp
@@ -76,7 +76,7 @@
apps.push_back(String16(kApp2.c_str()));
versions.push_back(4);
versions.push_back(5);
- m.updateMap(uids, versions, apps);
+ m.updateMap(1, uids, versions, apps);
EXPECT_TRUE(m.hasApp(1000, kApp1));
EXPECT_TRUE(m.hasApp(1000, kApp2));
EXPECT_FALSE(m.hasApp(1000, "not.app"));
@@ -102,7 +102,7 @@
apps.push_back(String16(kApp2.c_str()));
versions.push_back(4);
versions.push_back(5);
- m.updateMap(uids, versions, apps);
+ m.updateMap(1, uids, versions, apps);
std::set<string> name_set = m.getAppNamesFromUid(1000, true /* returnNormalized */);
EXPECT_EQ(name_set.size(), 2u);
@@ -110,7 +110,7 @@
EXPECT_TRUE(name_set.find(kApp2) != name_set.end());
// Update the app1 version.
- m.updateApp(String16(kApp1.c_str()), 1000, 40);
+ m.updateApp(2, String16(kApp1.c_str()), 1000, 40);
EXPECT_EQ(40, m.getAppVersion(1000, kApp1));
name_set = m.getAppNamesFromUid(1000, true /* returnNormalized */);
@@ -118,7 +118,7 @@
EXPECT_TRUE(name_set.find(kApp1) != name_set.end());
EXPECT_TRUE(name_set.find(kApp2) != name_set.end());
- m.removeApp(String16(kApp1.c_str()), 1000);
+ m.removeApp(3, String16(kApp1.c_str()), 1000);
EXPECT_FALSE(m.hasApp(1000, kApp1));
EXPECT_TRUE(m.hasApp(1000, kApp2));
name_set = m.getAppNamesFromUid(1000, true /* returnNormalized */);
@@ -127,7 +127,7 @@
EXPECT_TRUE(name_set.find(kApp2) != name_set.end());
// Remove app2.
- m.removeApp(String16(kApp2.c_str()), 1000);
+ m.removeApp(4, String16(kApp2.c_str()), 1000);
EXPECT_FALSE(m.hasApp(1000, kApp1));
EXPECT_FALSE(m.hasApp(1000, kApp2));
name_set = m.getAppNamesFromUid(1000, true /* returnNormalized */);
@@ -136,14 +136,14 @@
TEST(UidMapTest, TestUpdateApp) {
UidMap m;
- m.updateMap({1000, 1000}, {4, 5}, {String16(kApp1.c_str()), String16(kApp2.c_str())});
+ m.updateMap(1, {1000, 1000}, {4, 5}, {String16(kApp1.c_str()), String16(kApp2.c_str())});
std::set<string> name_set = m.getAppNamesFromUid(1000, true /* returnNormalized */);
EXPECT_EQ(name_set.size(), 2u);
EXPECT_TRUE(name_set.find(kApp1) != name_set.end());
EXPECT_TRUE(name_set.find(kApp2) != name_set.end());
// Adds a new name for uid 1000.
- m.updateApp(String16("NeW_aPP1_NAmE"), 1000, 40);
+ m.updateApp(2, String16("NeW_aPP1_NAmE"), 1000, 40);
name_set = m.getAppNamesFromUid(1000, true /* returnNormalized */);
EXPECT_EQ(name_set.size(), 3u);
EXPECT_TRUE(name_set.find(kApp1) != name_set.end());
@@ -152,7 +152,7 @@
EXPECT_TRUE(name_set.find("new_app1_name") != name_set.end());
// This name is also reused by another uid 2000.
- m.updateApp(String16("NeW_aPP1_NAmE"), 2000, 1);
+ m.updateApp(3, String16("NeW_aPP1_NAmE"), 2000, 1);
name_set = m.getAppNamesFromUid(2000, true /* returnNormalized */);
EXPECT_EQ(name_set.size(), 1u);
EXPECT_TRUE(name_set.find("NeW_aPP1_NAmE") == name_set.end());
@@ -200,6 +200,66 @@
EXPECT_EQ(1, results.snapshots_size());
}
+TEST(UidMapTest, TestRemovedAppRetained) {
+ UidMap m;
+ // Initialize single config key.
+ ConfigKey config1(1, StringToId("config1"));
+ m.OnConfigUpdated(config1);
+ vector<int32_t> uids;
+ vector<int64_t> versions;
+ vector<String16> apps;
+ uids.push_back(1000);
+ apps.push_back(String16(kApp2.c_str()));
+ versions.push_back(5);
+ m.updateMap(1, uids, versions, apps);
+ m.removeApp(2, String16(kApp2.c_str()), 1000);
+
+ ProtoOutputStream proto;
+ m.appendUidMap(3, config1, &proto);
+
+ // Snapshot should still contain this item as deleted.
+ UidMapping results;
+ protoOutputStreamToUidMapping(&proto, &results);
+ EXPECT_EQ(1, results.snapshots(0).package_info_size());
+ EXPECT_EQ(true, results.snapshots(0).package_info(0).deleted());
+}
+
+TEST(UidMapTest, TestRemovedAppOverGuardrail) {
+ UidMap m;
+ // Initialize single config key.
+ ConfigKey config1(1, StringToId("config1"));
+ m.OnConfigUpdated(config1);
+ vector<int32_t> uids;
+ vector<int64_t> versions;
+ vector<String16> apps;
+ const int maxDeletedApps = StatsdStats::kMaxDeletedAppsInUidMap;
+ for (int j = 0; j < maxDeletedApps + 10; j++) {
+ uids.push_back(j);
+ apps.push_back(String16(kApp1.c_str()));
+ versions.push_back(j);
+ }
+ m.updateMap(1, uids, versions, apps);
+
+ // First, verify that we have the expected number of items.
+ UidMapping results;
+ ProtoOutputStream proto;
+ m.appendUidMap(3, config1, &proto);
+ protoOutputStreamToUidMapping(&proto, &results);
+ EXPECT_EQ(maxDeletedApps + 10, results.snapshots(0).package_info_size());
+
+ // Now remove all the apps.
+ m.updateMap(1, uids, versions, apps);
+ for (int j = 0; j < maxDeletedApps + 10; j++) {
+ m.removeApp(4, String16(kApp1.c_str()), j);
+ }
+
+ proto.clear();
+ m.appendUidMap(5, config1, &proto);
+ // Snapshot drops the first nine items.
+ protoOutputStreamToUidMapping(&proto, &results);
+ EXPECT_EQ(maxDeletedApps, results.snapshots(0).package_info_size());
+}
+
TEST(UidMapTest, TestClearingOutput) {
UidMap m;
@@ -218,7 +278,6 @@
versions.push_back(4);
versions.push_back(5);
m.updateMap(1, uids, versions, apps);
- EXPECT_EQ(1U, m.mSnapshots.size());
ProtoOutputStream proto;
m.appendUidMap(2, config1, &proto);
@@ -227,7 +286,6 @@
EXPECT_EQ(1, results.snapshots_size());
// We have to keep at least one snapshot in memory at all times.
- EXPECT_EQ(1U, m.mSnapshots.size());
proto.clear();
m.appendUidMap(2, config1, &proto);
protoOutputStreamToUidMapping(&proto, &results);
@@ -262,7 +320,6 @@
EXPECT_EQ(1, results.snapshots_size());
EXPECT_EQ(2, results.changes_size());
// At this point both should be cleared.
- EXPECT_EQ(1U, m.mSnapshots.size());
EXPECT_EQ(0U, m.mChanges.size());
}
@@ -280,11 +337,8 @@
apps.push_back(String16(kApp1.c_str()));
versions.push_back(1);
m.updateMap(1, uids, versions, apps);
- size_t snapshot_bytes = m.mBytesUsed;
- EXPECT_TRUE(snapshot_bytes > startBytes);
m.updateApp(3, String16(kApp1.c_str()), 1000, 40);
- EXPECT_TRUE(m.mBytesUsed > snapshot_bytes);
ProtoOutputStream proto;
vector<uint8_t> bytes;
@@ -313,16 +367,13 @@
versions.push_back(1);
}
m.updateMap(1, uids, versions, apps);
- EXPECT_EQ(1U, m.mSnapshots.size());
m.updateApp(3, String16("EXTREMELY_LONG_STRING_FOR_APP_TO_WASTE_MEMORY.0"), 1000, 2);
- EXPECT_EQ(1U, m.mSnapshots.size());
EXPECT_EQ(1U, m.mChanges.size());
// Now force deletion by limiting the memory to hold one delta change.
m.maxBytesOverride = 80; // Since the app string alone requires >45 characters.
m.updateApp(5, String16("EXTREMELY_LONG_STRING_FOR_APP_TO_WASTE_MEMORY.0"), 1000, 4);
- EXPECT_EQ(0U, m.mSnapshots.size());
EXPECT_EQ(1U, m.mChanges.size());
}
#else
diff --git a/cmds/statsd/tests/e2e/Attribution_e2e_test.cpp b/cmds/statsd/tests/e2e/Attribution_e2e_test.cpp
index a04a6f9..4dd0da8 100644
--- a/cmds/statsd/tests/e2e/Attribution_e2e_test.cpp
+++ b/cmds/statsd/tests/e2e/Attribution_e2e_test.cpp
@@ -18,6 +18,7 @@
#include "src/stats_log_util.h"
#include "tests/statsd_test_util.h"
+#include <iostream>
#include <vector>
namespace android {
@@ -66,14 +67,10 @@
EXPECT_TRUE(processor->mMetricsManagers.begin()->second->isConfigValid());
// Here it assumes that GMS core has two uids.
- processor->getUidMap()->updateApp(
- android::String16("com.android.gmscore"), 222 /* uid */, 1 /* version code*/);
- processor->getUidMap()->updateApp(
- android::String16("com.android.gmscore"), 444 /* uid */, 1 /* version code*/);
- processor->getUidMap()->updateApp(
- android::String16("app1"), 111 /* uid */, 2 /* version code*/);
- processor->getUidMap()->updateApp(
- android::String16("APP3"), 333 /* uid */, 2 /* version code*/);
+ processor->getUidMap()->updateMap(
+ 1, {222, 444, 111, 333}, {1, 1, 2, 2},
+ {String16("com.android.gmscore"), String16("com.android.gmscore"), String16("app1"),
+ String16("APP3")});
// GMS core node is in the middle.
std::vector<AttributionNodeInternal> attributions1 = {CreateAttribution(111, "App1"),
@@ -147,7 +144,7 @@
}
ConfigMetricsReportList reports;
vector<uint8_t> buffer;
- processor->onDumpReport(cfgKey, bucketStartTimeNs + 4 * bucketSizeNs + 1, &buffer);
+ processor->onDumpReport(cfgKey, bucketStartTimeNs + 4 * bucketSizeNs + 1, false, &buffer);
EXPECT_TRUE(buffer.size() > 0);
EXPECT_TRUE(reports.ParseFromArray(&buffer[0], buffer.size()));
EXPECT_EQ(reports.reports_size(), 1);
@@ -212,14 +209,10 @@
EXPECT_TRUE(processor->mMetricsManagers.begin()->second->isConfigValid());
// Here it assumes that GMS core has two uids.
- processor->getUidMap()->updateApp(
- android::String16("com.android.gmscore"), 222 /* uid */, 1 /* version code*/);
- processor->getUidMap()->updateApp(
- android::String16("com.android.gmscore"), 444 /* uid */, 1 /* version code*/);
- processor->getUidMap()->updateApp(
- android::String16("app1"), 111 /* uid */, 2 /* version code*/);
- processor->getUidMap()->updateApp(
- android::String16("APP3"), 333 /* uid */, 2 /* version code*/);
+ processor->getUidMap()->updateMap(
+ 1, {222, 444, 111, 333}, {1, 1, 2, 2},
+ {String16("com.android.gmscore"), String16("com.android.gmscore"), String16("app1"),
+ String16("APP3")});
// GMS core node is in the middle.
std::vector<AttributionNodeInternal> attributions1 = {CreateAttribution(111, "App1"),
@@ -293,7 +286,7 @@
}
ConfigMetricsReportList reports;
vector<uint8_t> buffer;
- processor->onDumpReport(cfgKey, bucketStartTimeNs + 4 * bucketSizeNs + 1, &buffer);
+ processor->onDumpReport(cfgKey, bucketStartTimeNs + 4 * bucketSizeNs + 1, false, &buffer);
EXPECT_TRUE(buffer.size() > 0);
EXPECT_TRUE(reports.ParseFromArray(&buffer[0], buffer.size()));
EXPECT_EQ(reports.reports_size(), 1);
diff --git a/cmds/statsd/tests/e2e/ConfigTtl_e2e_test.cpp b/cmds/statsd/tests/e2e/ConfigTtl_e2e_test.cpp
new file mode 100644
index 0000000..bb3ad64
--- /dev/null
+++ b/cmds/statsd/tests/e2e/ConfigTtl_e2e_test.cpp
@@ -0,0 +1,108 @@
+// 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 <gtest/gtest.h>
+
+#include "src/StatsLogProcessor.h"
+#include "src/stats_log_util.h"
+#include "tests/statsd_test_util.h"
+
+#include <vector>
+
+namespace android {
+namespace os {
+namespace statsd {
+
+#ifdef __ANDROID__
+
+namespace {
+
+StatsdConfig CreateStatsdConfig(int num_buckets, int threshold) {
+ StatsdConfig config;
+ config.add_allowed_log_source("AID_ROOT"); // LogEvent defaults to UID of root.
+ auto wakelockAcquireMatcher = CreateAcquireWakelockAtomMatcher();
+
+ *config.add_atom_matcher() = wakelockAcquireMatcher;
+
+ auto countMetric = config.add_count_metric();
+ countMetric->set_id(123456);
+ countMetric->set_what(wakelockAcquireMatcher.id());
+ *countMetric->mutable_dimensions_in_what() = CreateAttributionUidDimensions(
+ android::util::WAKELOCK_STATE_CHANGED, {Position::FIRST});
+ countMetric->set_bucket(FIVE_MINUTES);
+
+ auto alert = config.add_alert();
+ alert->set_id(StringToId("alert"));
+ alert->set_metric_id(123456);
+ alert->set_num_buckets(num_buckets);
+ alert->set_refractory_period_secs(10);
+ alert->set_trigger_if_sum_gt(threshold);
+
+ // Two hours
+ config.set_ttl_in_seconds(2 * 3600);
+ return config;
+}
+
+} // namespace
+
+TEST(ConfigTtlE2eTest, TestCountMetric) {
+ const int num_buckets = 1;
+ const int threshold = 3;
+ auto config = CreateStatsdConfig(num_buckets, threshold);
+ const uint64_t alert_id = config.alert(0).id();
+ const uint32_t refractory_period_sec = config.alert(0).refractory_period_secs();
+
+ int64_t bucketStartTimeNs = 10000000000;
+ int64_t bucketSizeNs =
+ TimeUnitToBucketSizeInMillis(config.count_metric(0).bucket()) * 1000000;
+
+ ConfigKey cfgKey;
+ auto processor = CreateStatsLogProcessor(bucketStartTimeNs / NS_PER_SEC, config, cfgKey);
+ EXPECT_EQ(processor->mMetricsManagers.size(), 1u);
+ EXPECT_TRUE(processor->mMetricsManagers.begin()->second->isConfigValid());
+
+ std::vector<AttributionNodeInternal> attributions1 = {CreateAttribution(111, "App1")};
+
+ FieldValue fieldValue1(Field(android::util::WAKELOCK_STATE_CHANGED, (int32_t)0x02010101),
+ Value((int32_t)111));
+ HashableDimensionKey whatKey1({fieldValue1});
+ MetricDimensionKey dimensionKey1(whatKey1, DEFAULT_DIMENSION_KEY);
+
+ FieldValue fieldValue2(Field(android::util::WAKELOCK_STATE_CHANGED, (int32_t)0x02010101),
+ Value((int32_t)222));
+ HashableDimensionKey whatKey2({fieldValue2});
+ MetricDimensionKey dimensionKey2(whatKey2, DEFAULT_DIMENSION_KEY);
+
+ auto event = CreateAcquireWakelockEvent(attributions1, "wl1", bucketStartTimeNs + 2);
+ processor->OnLogEvent(event.get());
+
+ event = CreateAcquireWakelockEvent(attributions1, "wl2", bucketStartTimeNs + bucketSizeNs + 2);
+ processor->OnLogEvent(event.get());
+
+ event = CreateAcquireWakelockEvent(
+ attributions1, "wl1", bucketStartTimeNs + 25 * bucketSizeNs + 2);
+ processor->OnLogEvent(event.get());
+
+ EXPECT_EQ((int64_t)(bucketStartTimeNs + 25 * bucketSizeNs + 2 + 2 * 3600 * NS_PER_SEC),
+ processor->mMetricsManagers.begin()->second->getTtlEndNs());
+}
+
+
+#else
+GTEST_LOG_(INFO) << "This test does nothing.\n";
+#endif
+
+} // namespace statsd
+} // namespace os
+} // namespace android
diff --git a/cmds/statsd/tests/e2e/DimensionInCondition_e2e_combination_AND_cond_test.cpp b/cmds/statsd/tests/e2e/DimensionInCondition_e2e_combination_AND_cond_test.cpp
index 63e23ce..eb57d470 100644
--- a/cmds/statsd/tests/e2e/DimensionInCondition_e2e_combination_AND_cond_test.cpp
+++ b/cmds/statsd/tests/e2e/DimensionInCondition_e2e_combination_AND_cond_test.cpp
@@ -172,7 +172,8 @@
ConfigMetricsReportList reports;
vector<uint8_t> buffer;
- processor->onDumpReport(cfgKey, bucketStartTimeNs + 2 * bucketSizeNs + 1, &buffer);
+ processor->onDumpReport(cfgKey, bucketStartTimeNs + 2 * bucketSizeNs + 1,
+ false, &buffer);
EXPECT_TRUE(buffer.size() > 0);
EXPECT_TRUE(reports.ParseFromArray(&buffer[0], buffer.size()));
@@ -488,7 +489,8 @@
ConfigMetricsReportList reports;
vector<uint8_t> buffer;
- processor->onDumpReport(cfgKey, bucketStartTimeNs + 2 * bucketSizeNs + 1, &buffer);
+ processor->onDumpReport(cfgKey, bucketStartTimeNs + 2 * bucketSizeNs + 1, false,
+ &buffer);
EXPECT_TRUE(buffer.size() > 0);
EXPECT_TRUE(reports.ParseFromArray(&buffer[0], buffer.size()));
@@ -731,7 +733,7 @@
ConfigMetricsReportList reports;
vector<uint8_t> buffer;
- processor->onDumpReport(cfgKey, bucketStartTimeNs + 2 * bucketSizeNs + 1, &buffer);
+ processor->onDumpReport(cfgKey, bucketStartTimeNs + 2 * bucketSizeNs + 1, false, &buffer);
EXPECT_TRUE(buffer.size() > 0);
EXPECT_TRUE(reports.ParseFromArray(&buffer[0], buffer.size()));
diff --git a/cmds/statsd/tests/e2e/DimensionInCondition_e2e_combination_OR_cond_test.cpp b/cmds/statsd/tests/e2e/DimensionInCondition_e2e_combination_OR_cond_test.cpp
index c2334d8..9729a2e 100644
--- a/cmds/statsd/tests/e2e/DimensionInCondition_e2e_combination_OR_cond_test.cpp
+++ b/cmds/statsd/tests/e2e/DimensionInCondition_e2e_combination_OR_cond_test.cpp
@@ -130,7 +130,7 @@
ConfigMetricsReportList reports;
vector<uint8_t> buffer;
- processor->onDumpReport(cfgKey, bucketStartTimeNs + 2 * bucketSizeNs + 1, &buffer);
+ processor->onDumpReport(cfgKey, bucketStartTimeNs + 2 * bucketSizeNs + 1, false, &buffer);
EXPECT_TRUE(buffer.size() > 0);
EXPECT_TRUE(reports.ParseFromArray(&buffer[0], buffer.size()));
@@ -342,7 +342,7 @@
ConfigMetricsReportList reports;
vector<uint8_t> buffer;
- processor->onDumpReport(cfgKey, bucketStartTimeNs + 2 * bucketSizeNs + 1, &buffer);
+ processor->onDumpReport(cfgKey, bucketStartTimeNs + 2 * bucketSizeNs + 1, false, &buffer);
EXPECT_TRUE(buffer.size() > 0);
EXPECT_TRUE(reports.ParseFromArray(&buffer[0], buffer.size()));
@@ -521,7 +521,7 @@
ConfigMetricsReportList reports;
vector<uint8_t> buffer;
- processor->onDumpReport(cfgKey, bucketStartTimeNs + 2 * bucketSizeNs + 1, &buffer);
+ processor->onDumpReport(cfgKey, bucketStartTimeNs + 2 * bucketSizeNs + 1, false, &buffer);
EXPECT_TRUE(buffer.size() > 0);
EXPECT_TRUE(reports.ParseFromArray(&buffer[0], buffer.size()));
@@ -718,7 +718,7 @@
ConfigMetricsReportList reports;
vector<uint8_t> buffer;
- processor->onDumpReport(cfgKey, bucketStartTimeNs + 2 * bucketSizeNs + 1, &buffer);
+ processor->onDumpReport(cfgKey, bucketStartTimeNs + 2 * bucketSizeNs + 1, false, &buffer);
EXPECT_TRUE(buffer.size() > 0);
EXPECT_TRUE(reports.ParseFromArray(&buffer[0], buffer.size()));
diff --git a/cmds/statsd/tests/e2e/DimensionInCondition_e2e_simple_cond_test.cpp b/cmds/statsd/tests/e2e/DimensionInCondition_e2e_simple_cond_test.cpp
index ab37140..4e2c36e 100644
--- a/cmds/statsd/tests/e2e/DimensionInCondition_e2e_simple_cond_test.cpp
+++ b/cmds/statsd/tests/e2e/DimensionInCondition_e2e_simple_cond_test.cpp
@@ -142,7 +142,8 @@
ConfigMetricsReportList reports;
vector<uint8_t> buffer;
- processor->onDumpReport(cfgKey, bucketStartTimeNs + 2 * bucketSizeNs + 1, &buffer);
+ processor->onDumpReport(cfgKey, bucketStartTimeNs + 2 * bucketSizeNs + 1, false,
+ &buffer);
EXPECT_TRUE(buffer.size() > 0);
EXPECT_TRUE(reports.ParseFromArray(&buffer[0], buffer.size()));
@@ -433,7 +434,8 @@
ConfigMetricsReportList reports;
vector<uint8_t> buffer;
- processor->onDumpReport(cfgKey, bucketStartTimeNs + 2 * bucketSizeNs + 1, &buffer);
+ processor->onDumpReport(cfgKey, bucketStartTimeNs + 2 * bucketSizeNs + 1, false,
+ &buffer);
EXPECT_TRUE(buffer.size() > 0);
EXPECT_TRUE(reports.ParseFromArray(&buffer[0], buffer.size()));
@@ -650,7 +652,7 @@
ConfigMetricsReportList reports;
vector<uint8_t> buffer;
- processor->onDumpReport(cfgKey, bucketStartTimeNs + 2 * bucketSizeNs + 1, &buffer);
+ processor->onDumpReport(cfgKey, bucketStartTimeNs + 2 * bucketSizeNs + 1, false, &buffer);
EXPECT_TRUE(buffer.size() > 0);
EXPECT_TRUE(reports.ParseFromArray(&buffer[0], buffer.size()));
diff --git a/cmds/statsd/tests/e2e/GaugeMetric_e2e_push_test.cpp b/cmds/statsd/tests/e2e/GaugeMetric_e2e_push_test.cpp
index 2b91324..18a0485 100644
--- a/cmds/statsd/tests/e2e/GaugeMetric_e2e_push_test.cpp
+++ b/cmds/statsd/tests/e2e/GaugeMetric_e2e_push_test.cpp
@@ -148,7 +148,7 @@
}
ConfigMetricsReportList reports;
vector<uint8_t> buffer;
- processor->onDumpReport(cfgKey, bucketStartTimeNs + 3 * bucketSizeNs, &buffer);
+ processor->onDumpReport(cfgKey, bucketStartTimeNs + 3 * bucketSizeNs, false, &buffer);
EXPECT_TRUE(buffer.size() > 0);
EXPECT_TRUE(reports.ParseFromArray(&buffer[0], buffer.size()));
EXPECT_EQ(1, reports.reports_size());
diff --git a/cmds/statsd/tests/e2e/MetricConditionLink_e2e_test.cpp b/cmds/statsd/tests/e2e/MetricConditionLink_e2e_test.cpp
index 1440f29..1952a6f 100644
--- a/cmds/statsd/tests/e2e/MetricConditionLink_e2e_test.cpp
+++ b/cmds/statsd/tests/e2e/MetricConditionLink_e2e_test.cpp
@@ -200,7 +200,7 @@
}
ConfigMetricsReportList reports;
vector<uint8_t> buffer;
- processor->onDumpReport(cfgKey, bucketStartTimeNs + 2 * bucketSizeNs - 1, &buffer);
+ processor->onDumpReport(cfgKey, bucketStartTimeNs + 2 * bucketSizeNs - 1, false, &buffer);
EXPECT_TRUE(buffer.size() > 0);
EXPECT_TRUE(reports.ParseFromArray(&buffer[0], buffer.size()));
EXPECT_EQ(reports.reports_size(), 1);
@@ -314,7 +314,7 @@
ConfigMetricsReportList reports;
vector<uint8_t> buffer;
- processor->onDumpReport(cfgKey, bucketStartTimeNs + 2 * bucketSizeNs + 1, &buffer);
+ processor->onDumpReport(cfgKey, bucketStartTimeNs + 2 * bucketSizeNs + 1, false, &buffer);
EXPECT_TRUE(buffer.size() > 0);
EXPECT_TRUE(reports.ParseFromArray(&buffer[0], buffer.size()));
EXPECT_EQ(reports.reports_size(), 1);
diff --git a/cmds/statsd/tests/e2e/PartialBucket_e2e_test.cpp b/cmds/statsd/tests/e2e/PartialBucket_e2e_test.cpp
new file mode 100644
index 0000000..d4892ed
--- /dev/null
+++ b/cmds/statsd/tests/e2e/PartialBucket_e2e_test.cpp
@@ -0,0 +1,137 @@
+// Copyright (C) 2017 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#include <gtest/gtest.h>
+
+#include "src/StatsLogProcessor.h"
+#include "src/StatsService.h"
+#include "src/stats_log_util.h"
+#include "tests/statsd_test_util.h"
+
+#include <vector>
+
+namespace android {
+namespace os {
+namespace statsd {
+
+#ifdef __ANDROID__
+
+const string kApp1 = "app1.sharing.1";
+const int kConfigKey = 789130123; // Randomly chosen to avoid collisions with existing configs.
+
+void SendConfig(StatsService& service, const StatsdConfig& config) {
+ string str;
+ config.SerializeToString(&str);
+ std::vector<uint8_t> configAsVec(str.begin(), str.end());
+ bool success;
+ service.addConfiguration(kConfigKey, configAsVec, &success);
+}
+
+ConfigMetricsReport GetReports(StatsService& service) {
+ vector<uint8_t> output;
+ service.getData(kConfigKey, &output);
+ ConfigMetricsReportList reports;
+ reports.ParseFromArray(output.data(), output.size());
+ EXPECT_EQ(1, reports.reports_size());
+ return reports.reports(0);
+}
+
+StatsdConfig MakeConfig() {
+ StatsdConfig config;
+ config.add_allowed_log_source("AID_ROOT"); // LogEvent defaults to UID of root.
+
+ auto appCrashMatcher = CreateProcessCrashAtomMatcher();
+ *config.add_atom_matcher() = appCrashMatcher;
+ auto countMetric = config.add_count_metric();
+ countMetric->set_id(StringToId("AppCrashes"));
+ countMetric->set_what(appCrashMatcher.id());
+ countMetric->set_bucket(FIVE_MINUTES);
+ return config;
+}
+
+TEST(PartialBucketE2eTest, TestCountMetricWithoutSplit) {
+ StatsService service(nullptr);
+ SendConfig(service, MakeConfig());
+ const long start = getElapsedRealtimeNs(); // This is the start-time the metrics producers are
+ // initialized with.
+
+ service.mProcessor->OnLogEvent(CreateAppCrashEvent(100, start + 1).get());
+ service.mProcessor->OnLogEvent(CreateAppCrashEvent(100, start + 2).get());
+
+ ConfigMetricsReport report = GetReports(service);
+ // Expect no metrics since the bucket has not finished yet.
+ EXPECT_EQ(0, report.metrics_size());
+}
+
+TEST(PartialBucketE2eTest, TestCountMetricNoSplitOnNewApp) {
+ StatsService service(nullptr);
+ SendConfig(service, MakeConfig());
+ const long start = getElapsedRealtimeNs(); // This is the start-time the metrics producers are
+ // initialized with.
+
+ // Force the uidmap to update at timestamp 2.
+ service.mProcessor->OnLogEvent(CreateAppCrashEvent(100, start + 1).get());
+ // This is a new installation, so there shouldn't be a split (should be same as the without
+ // split case).
+ service.mUidMap->updateApp(start + 2, String16(kApp1.c_str()), 1, 2);
+ // Goes into the second bucket.
+ service.mProcessor->OnLogEvent(CreateAppCrashEvent(100, start + 3).get());
+
+ ConfigMetricsReport report = GetReports(service);
+ EXPECT_EQ(0, report.metrics_size());
+}
+
+TEST(PartialBucketE2eTest, TestCountMetricSplitOnUpgrade) {
+ StatsService service(nullptr);
+ SendConfig(service, MakeConfig());
+ const long start = getElapsedRealtimeNs(); // This is the start-time the metrics producers are
+ // initialized with.
+ service.mUidMap->updateMap(start, {1}, {1}, {String16(kApp1.c_str())});
+
+ // Force the uidmap to update at timestamp 2.
+ service.mProcessor->OnLogEvent(CreateAppCrashEvent(100, start + 1).get());
+ service.mUidMap->updateApp(start + 2, String16(kApp1.c_str()), 1, 2);
+ // Goes into the second bucket.
+ service.mProcessor->OnLogEvent(CreateAppCrashEvent(100, start + 3).get());
+
+ ConfigMetricsReport report = GetReports(service);
+ EXPECT_EQ(1, report.metrics_size());
+ EXPECT_EQ(1, report.metrics(0).count_metrics().data(0).bucket_info(0).count());
+}
+
+TEST(PartialBucketE2eTest, TestCountMetricSplitOnRemoval) {
+ StatsService service(nullptr);
+ SendConfig(service, MakeConfig());
+ const long start = getElapsedRealtimeNs(); // This is the start-time the metrics producers are
+ // initialized with.
+ service.mUidMap->updateMap(start, {1}, {1}, {String16(kApp1.c_str())});
+
+ // Force the uidmap to update at timestamp 2.
+ service.mProcessor->OnLogEvent(CreateAppCrashEvent(100, start + 1).get());
+ service.mUidMap->removeApp(start + 2, String16(kApp1.c_str()), 1);
+ // Goes into the second bucket.
+ service.mProcessor->OnLogEvent(CreateAppCrashEvent(100, start + 3).get());
+
+ ConfigMetricsReport report = GetReports(service);
+ EXPECT_EQ(1, report.metrics_size());
+ EXPECT_EQ(1, report.metrics(0).count_metrics().data(0).bucket_info(0).count());
+}
+
+#else
+GTEST_LOG_(INFO) << "This test does nothing.\n";
+#endif
+
+} // namespace statsd
+} // namespace os
+} // namespace android
\ No newline at end of file
diff --git a/cmds/statsd/tests/e2e/WakelockDuration_e2e_test.cpp b/cmds/statsd/tests/e2e/WakelockDuration_e2e_test.cpp
index bfae8bc..f2d47c7 100644
--- a/cmds/statsd/tests/e2e/WakelockDuration_e2e_test.cpp
+++ b/cmds/statsd/tests/e2e/WakelockDuration_e2e_test.cpp
@@ -127,7 +127,7 @@
FeedEvents(config, processor);
vector<uint8_t> buffer;
ConfigMetricsReportList reports;
- processor->onDumpReport(cfgKey, bucketStartTimeNs + 2 * bucketSizeNs - 1, &buffer);
+ processor->onDumpReport(cfgKey, bucketStartTimeNs + 2 * bucketSizeNs - 1, false, &buffer);
EXPECT_TRUE(buffer.size() > 0);
EXPECT_TRUE(reports.ParseFromArray(&buffer[0], buffer.size()));
@@ -161,7 +161,7 @@
vector<uint8_t> buffer;
ConfigMetricsReportList reports;
- processor->onDumpReport(cfgKey, bucketStartTimeNs + 2 * bucketSizeNs + 1, &buffer);
+ processor->onDumpReport(cfgKey, bucketStartTimeNs + 2 * bucketSizeNs + 1, false, &buffer);
EXPECT_TRUE(buffer.size() > 0);
EXPECT_TRUE(reports.ParseFromArray(&buffer[0], buffer.size()));
EXPECT_EQ(reports.reports_size(), 1);
@@ -208,7 +208,7 @@
processor->OnLogEvent(event.get());
}
- processor->onDumpReport(cfgKey, bucketStartTimeNs + 6 * bucketSizeNs + 1, &buffer);
+ processor->onDumpReport(cfgKey, bucketStartTimeNs + 6 * bucketSizeNs + 1, false, &buffer);
EXPECT_TRUE(buffer.size() > 0);
EXPECT_TRUE(reports.ParseFromArray(&buffer[0], buffer.size()));
EXPECT_EQ(reports.reports_size(), 1);
@@ -237,7 +237,7 @@
FeedEvents(config, processor);
ConfigMetricsReportList reports;
vector<uint8_t> buffer;
- processor->onDumpReport(cfgKey, bucketStartTimeNs + 2 * bucketSizeNs - 1, &buffer);
+ processor->onDumpReport(cfgKey, bucketStartTimeNs + 2 * bucketSizeNs - 1, false, &buffer);
EXPECT_TRUE(buffer.size() > 0);
EXPECT_TRUE(reports.ParseFromArray(&buffer[0], buffer.size()));
@@ -262,7 +262,7 @@
FeedEvents(config, processor);
ConfigMetricsReportList reports;
vector<uint8_t> buffer;
- processor->onDumpReport(cfgKey, bucketStartTimeNs + 2 * bucketSizeNs + 1, &buffer);
+ processor->onDumpReport(cfgKey, bucketStartTimeNs + 2 * bucketSizeNs + 1, false, &buffer);
EXPECT_TRUE(buffer.size() > 0);
EXPECT_TRUE(reports.ParseFromArray(&buffer[0], buffer.size()));
EXPECT_EQ(reports.reports_size(), 1);
@@ -304,7 +304,7 @@
processor->OnLogEvent(event.get());
}
- processor->onDumpReport(cfgKey, bucketStartTimeNs + 6 * bucketSizeNs + 1, &buffer);
+ processor->onDumpReport(cfgKey, bucketStartTimeNs + 6 * bucketSizeNs + 1, false, &buffer);
EXPECT_TRUE(buffer.size() > 0);
EXPECT_TRUE(reports.ParseFromArray(&buffer[0], buffer.size()));
EXPECT_EQ(reports.reports_size(), 1);
diff --git a/cmds/statsd/tests/guardrail/StatsdStats_test.cpp b/cmds/statsd/tests/guardrail/StatsdStats_test.cpp
index 5c35d96..e99e402 100644
--- a/cmds/statsd/tests/guardrail/StatsdStats_test.cpp
+++ b/cmds/statsd/tests/guardrail/StatsdStats_test.cpp
@@ -129,9 +129,9 @@
stats.noteDataDropped(key);
// dump report -> 3
- stats.noteMetricsReportSent(key);
- stats.noteMetricsReportSent(key);
- stats.noteMetricsReportSent(key);
+ stats.noteMetricsReportSent(key, 0);
+ stats.noteMetricsReportSent(key, 0);
+ stats.noteMetricsReportSent(key, 0);
vector<uint8_t> output;
stats.dumpStats(&output, true); // Dump and reset stats
@@ -143,6 +143,7 @@
EXPECT_EQ(2, configReport.broadcast_sent_time_sec_size());
EXPECT_EQ(1, configReport.data_drop_time_sec_size());
EXPECT_EQ(3, configReport.dump_report_time_sec_size());
+ EXPECT_EQ(3, configReport.dump_report_data_size_size());
EXPECT_EQ(1, configReport.annotation_size());
EXPECT_EQ(123, configReport.annotation(0).field_int64());
EXPECT_EQ(456, configReport.annotation(0).field_int32());
@@ -268,7 +269,7 @@
for (int i = 0; i < StatsdStats::kMaxTimestampCount; i++) {
stats.noteDataDropped(key, timestamps[i]);
stats.noteBroadcastSent(key, timestamps[i]);
- stats.noteMetricsReportSent(key, timestamps[i]);
+ stats.noteMetricsReportSent(key, 0, timestamps[i]);
}
int32_t newTimestamp = 10000;
@@ -276,7 +277,7 @@
// now it should trigger removing oldest timestamp
stats.noteDataDropped(key, 10000);
stats.noteBroadcastSent(key, 10000);
- stats.noteMetricsReportSent(key, 10000);
+ stats.noteMetricsReportSent(key, 0, 10000);
EXPECT_TRUE(stats.mConfigStats.find(key) != stats.mConfigStats.end());
const auto& configStats = stats.mConfigStats[key];
@@ -284,7 +285,7 @@
size_t maxCount = StatsdStats::kMaxTimestampCount;
EXPECT_EQ(maxCount, configStats->broadcast_sent_time_sec.size());
EXPECT_EQ(maxCount, configStats->data_drop_time_sec.size());
- EXPECT_EQ(maxCount, configStats->dump_report_time_sec.size());
+ EXPECT_EQ(maxCount, configStats->dump_report_stats.size());
// the oldest timestamp is the second timestamp in history
EXPECT_EQ(1, configStats->broadcast_sent_time_sec.front());
@@ -294,7 +295,7 @@
// the last timestamp is the newest timestamp.
EXPECT_EQ(newTimestamp, configStats->broadcast_sent_time_sec.back());
EXPECT_EQ(newTimestamp, configStats->data_drop_time_sec.back());
- EXPECT_EQ(newTimestamp, configStats->dump_report_time_sec.back());
+ EXPECT_EQ(newTimestamp, configStats->dump_report_stats.back().first);
}
} // namespace statsd
diff --git a/cmds/statsd/tests/metrics/CountMetricProducer_test.cpp b/cmds/statsd/tests/metrics/CountMetricProducer_test.cpp
index fff1155..9a8919e 100644
--- a/cmds/statsd/tests/metrics/CountMetricProducer_test.cpp
+++ b/cmds/statsd/tests/metrics/CountMetricProducer_test.cpp
@@ -203,9 +203,9 @@
TEST(CountMetricProducerTest, TestEventWithAppUpgrade) {
sp<AlarmMonitor> alarmMonitor;
- uint64_t bucketStartTimeNs = 10000000000;
- uint64_t bucketSizeNs = TimeUnitToBucketSizeInMillis(ONE_MINUTE) * 1000000LL;
- uint64_t eventUpgradeTimeNs = bucketStartTimeNs + 15 * NS_PER_SEC;
+ int64_t bucketStartTimeNs = 10000000000;
+ int64_t bucketSizeNs = TimeUnitToBucketSizeInMillis(ONE_MINUTE) * 1000000LL;
+ int64_t eventUpgradeTimeNs = bucketStartTimeNs + 15 * NS_PER_SEC;
int tagId = 1;
int conditionTagId = 2;
@@ -244,7 +244,7 @@
// Anomaly tracker only contains full buckets.
EXPECT_EQ(0, anomalyTracker->getSumOverPastBuckets(DEFAULT_METRIC_DIMENSION_KEY));
- uint64_t lastEndTimeNs = countProducer.getCurrentBucketEndTimeNs();
+ int64_t lastEndTimeNs = countProducer.getCurrentBucketEndTimeNs();
// Next event occurs in same bucket as partial bucket created.
LogEvent event2(tagId, bucketStartTimeNs + 59 * NS_PER_SEC + 10);
event2.write("222"); // uid
@@ -265,9 +265,9 @@
}
TEST(CountMetricProducerTest, TestEventWithAppUpgradeInNextBucket) {
- uint64_t bucketStartTimeNs = 10000000000;
- uint64_t bucketSizeNs = TimeUnitToBucketSizeInMillis(ONE_MINUTE) * 1000000LL;
- uint64_t eventUpgradeTimeNs = bucketStartTimeNs + 65 * NS_PER_SEC;
+ int64_t bucketStartTimeNs = 10000000000;
+ int64_t bucketSizeNs = TimeUnitToBucketSizeInMillis(ONE_MINUTE) * 1000000LL;
+ int64_t eventUpgradeTimeNs = bucketStartTimeNs + 65 * NS_PER_SEC;
int tagId = 1;
int conditionTagId = 2;
@@ -294,7 +294,7 @@
EXPECT_EQ((int64_t)bucketStartTimeNs,
countProducer.mPastBuckets[DEFAULT_METRIC_DIMENSION_KEY][0].mBucketStartNs);
EXPECT_EQ(bucketStartTimeNs + bucketSizeNs,
- (uint64_t)countProducer.mPastBuckets[DEFAULT_METRIC_DIMENSION_KEY][0].mBucketEndNs);
+ countProducer.mPastBuckets[DEFAULT_METRIC_DIMENSION_KEY][0].mBucketEndNs);
EXPECT_EQ(eventUpgradeTimeNs, countProducer.mCurrentBucketStartTimeNs);
// Next event occurs in same bucket as partial bucket created.
@@ -313,7 +313,7 @@
EXPECT_EQ((int64_t)eventUpgradeTimeNs,
countProducer.mPastBuckets[DEFAULT_METRIC_DIMENSION_KEY][1].mBucketStartNs);
EXPECT_EQ(bucketStartTimeNs + 2 * bucketSizeNs,
- (uint64_t)countProducer.mPastBuckets[DEFAULT_METRIC_DIMENSION_KEY][1].mBucketEndNs);
+ countProducer.mPastBuckets[DEFAULT_METRIC_DIMENSION_KEY][1].mBucketEndNs);
}
TEST(CountMetricProducerTest, TestAnomalyDetectionUnSliced) {
diff --git a/cmds/statsd/tests/metrics/DurationMetricProducer_test.cpp b/cmds/statsd/tests/metrics/DurationMetricProducer_test.cpp
index 1b22d75..7ef8c5b 100644
--- a/cmds/statsd/tests/metrics/DurationMetricProducer_test.cpp
+++ b/cmds/statsd/tests/metrics/DurationMetricProducer_test.cpp
@@ -41,7 +41,7 @@
TEST(DurationMetricTrackerTest, TestNoCondition) {
sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
- uint64_t bucketStartTimeNs = 10000000000;
+ int64_t bucketStartTimeNs = 10000000000;
int64_t bucketSizeNs = TimeUnitToBucketSizeInMillis(ONE_MINUTE) * 1000000LL;
DurationMetric metric;
@@ -71,15 +71,15 @@
EXPECT_EQ(2UL, buckets.size());
EXPECT_EQ(bucketStartTimeNs, buckets[0].mBucketStartNs);
EXPECT_EQ(bucketStartTimeNs + bucketSizeNs, buckets[0].mBucketEndNs);
- EXPECT_EQ(bucketSizeNs - 1ULL, buckets[0].mDuration);
+ EXPECT_EQ(bucketSizeNs - 1LL, buckets[0].mDuration);
EXPECT_EQ(bucketStartTimeNs + bucketSizeNs, buckets[1].mBucketStartNs);
EXPECT_EQ(bucketStartTimeNs + 2 * bucketSizeNs, buckets[1].mBucketEndNs);
- EXPECT_EQ(2ULL, buckets[1].mDuration);
+ EXPECT_EQ(2LL, buckets[1].mDuration);
}
TEST(DurationMetricTrackerTest, TestNonSlicedCondition) {
sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
- uint64_t bucketStartTimeNs = 10000000000;
+ int64_t bucketStartTimeNs = 10000000000;
int64_t bucketSizeNs = TimeUnitToBucketSizeInMillis(ONE_MINUTE) * 1000000LL;
DurationMetric metric;
@@ -122,7 +122,7 @@
EXPECT_EQ(1UL, buckets2.size());
EXPECT_EQ(bucketStartTimeNs + bucketSizeNs, buckets2[0].mBucketStartNs);
EXPECT_EQ(bucketStartTimeNs + 2 * bucketSizeNs, buckets2[0].mBucketEndNs);
- EXPECT_EQ(1ULL, buckets2[0].mDuration);
+ EXPECT_EQ(1LL, buckets2[0].mDuration);
}
TEST(DurationMetricTrackerTest, TestSumDurationWithUpgrade) {
@@ -135,11 +135,11 @@
* - [70,130]: All 60 secs
* - [130, 210]: Only 5 secs (event ended at 135sec)
*/
- uint64_t bucketStartTimeNs = 10000000000;
- uint64_t bucketSizeNs = TimeUnitToBucketSizeInMillis(ONE_MINUTE) * 1000000LL;
- uint64_t eventUpgradeTimeNs = bucketStartTimeNs + 15 * NS_PER_SEC;
- uint64_t startTimeNs = bucketStartTimeNs + 1 * NS_PER_SEC;
- uint64_t endTimeNs = startTimeNs + 125 * NS_PER_SEC;
+ int64_t bucketStartTimeNs = 10000000000;
+ int64_t bucketSizeNs = TimeUnitToBucketSizeInMillis(ONE_MINUTE) * 1000000LL;
+ int64_t eventUpgradeTimeNs = bucketStartTimeNs + 15 * NS_PER_SEC;
+ int64_t startTimeNs = bucketStartTimeNs + 1 * NS_PER_SEC;
+ int64_t endTimeNs = startTimeNs + 125 * NS_PER_SEC;
int tagId = 1;
@@ -190,11 +190,11 @@
* - [70,75]: 5 sec
* - [75,130]: 55 secs
*/
- uint64_t bucketStartTimeNs = 10000000000;
- uint64_t bucketSizeNs = TimeUnitToBucketSizeInMillis(ONE_MINUTE) * 1000000LL;
- uint64_t eventUpgradeTimeNs = bucketStartTimeNs + 65 * NS_PER_SEC;
- uint64_t startTimeNs = bucketStartTimeNs + 1 * NS_PER_SEC;
- uint64_t endTimeNs = startTimeNs + 125 * NS_PER_SEC;
+ int64_t bucketStartTimeNs = 10000000000;
+ int64_t bucketSizeNs = TimeUnitToBucketSizeInMillis(ONE_MINUTE) * 1000000LL;
+ int64_t eventUpgradeTimeNs = bucketStartTimeNs + 65 * NS_PER_SEC;
+ int64_t startTimeNs = bucketStartTimeNs + 1 * NS_PER_SEC;
+ int64_t endTimeNs = startTimeNs + 125 * NS_PER_SEC;
int tagId = 1;
@@ -240,11 +240,11 @@
TEST(DurationMetricTrackerTest, TestSumDurationAnomalyWithUpgrade) {
sp<AlarmMonitor> alarmMonitor;
- uint64_t bucketStartTimeNs = 10000000000;
- uint64_t bucketSizeNs = TimeUnitToBucketSizeInMillis(ONE_MINUTE) * 1000000LL;
- uint64_t eventUpgradeTimeNs = bucketStartTimeNs + 15 * NS_PER_SEC;
- uint64_t startTimeNs = bucketStartTimeNs + 1;
- uint64_t endTimeNs = startTimeNs + 65 * NS_PER_SEC;
+ int64_t bucketStartTimeNs = 10000000000;
+ int64_t bucketSizeNs = TimeUnitToBucketSizeInMillis(ONE_MINUTE) * 1000000LL;
+ int64_t eventUpgradeTimeNs = bucketStartTimeNs + 15 * NS_PER_SEC;
+ int64_t startTimeNs = bucketStartTimeNs + 1;
+ int64_t endTimeNs = startTimeNs + 65 * NS_PER_SEC;
int tagId = 1;
@@ -277,15 +277,15 @@
durationProducer.onMatchedLogEvent(2 /* stop index*/, end_event);
EXPECT_EQ(bucketStartTimeNs + bucketSizeNs - startTimeNs,
- (uint64_t)anomalyTracker->getSumOverPastBuckets(DEFAULT_METRIC_DIMENSION_KEY));
+ anomalyTracker->getSumOverPastBuckets(DEFAULT_METRIC_DIMENSION_KEY));
}
TEST(DurationMetricTrackerTest, TestMaxDurationWithUpgrade) {
- uint64_t bucketStartTimeNs = 10000000000;
- uint64_t bucketSizeNs = TimeUnitToBucketSizeInMillis(ONE_MINUTE) * 1000000LL;
- uint64_t eventUpgradeTimeNs = bucketStartTimeNs + 15 * NS_PER_SEC;
- uint64_t startTimeNs = bucketStartTimeNs + 1;
- uint64_t endTimeNs = startTimeNs + 125 * NS_PER_SEC;
+ int64_t bucketStartTimeNs = 10000000000;
+ int64_t bucketSizeNs = TimeUnitToBucketSizeInMillis(ONE_MINUTE) * 1000000LL;
+ int64_t eventUpgradeTimeNs = bucketStartTimeNs + 15 * NS_PER_SEC;
+ int64_t startTimeNs = bucketStartTimeNs + 1;
+ int64_t endTimeNs = startTimeNs + 125 * NS_PER_SEC;
int tagId = 1;
@@ -329,11 +329,11 @@
}
TEST(DurationMetricTrackerTest, TestMaxDurationWithUpgradeInNextBucket) {
- uint64_t bucketStartTimeNs = 10000000000;
- uint64_t bucketSizeNs = TimeUnitToBucketSizeInMillis(ONE_MINUTE) * 1000000LL;
- uint64_t eventUpgradeTimeNs = bucketStartTimeNs + 65 * NS_PER_SEC;
- uint64_t startTimeNs = bucketStartTimeNs + 1;
- uint64_t endTimeNs = startTimeNs + 115 * NS_PER_SEC;
+ int64_t bucketStartTimeNs = 10000000000;
+ int64_t bucketSizeNs = TimeUnitToBucketSizeInMillis(ONE_MINUTE) * 1000000LL;
+ int64_t eventUpgradeTimeNs = bucketStartTimeNs + 65 * NS_PER_SEC;
+ int64_t startTimeNs = bucketStartTimeNs + 1;
+ int64_t endTimeNs = startTimeNs + 115 * NS_PER_SEC;
int tagId = 1;
diff --git a/cmds/statsd/tests/metrics/EventMetricProducer_test.cpp b/cmds/statsd/tests/metrics/EventMetricProducer_test.cpp
index 23d3171..3a15466 100644
--- a/cmds/statsd/tests/metrics/EventMetricProducer_test.cpp
+++ b/cmds/statsd/tests/metrics/EventMetricProducer_test.cpp
@@ -36,9 +36,9 @@
const ConfigKey kConfigKey(0, 12345);
TEST(EventMetricProducerTest, TestNoCondition) {
- uint64_t bucketStartTimeNs = 10000000000;
- uint64_t eventStartTimeNs = bucketStartTimeNs + 1;
- uint64_t bucketSizeNs = 30 * 1000 * 1000 * 1000LL;
+ int64_t bucketStartTimeNs = 10000000000;
+ int64_t eventStartTimeNs = bucketStartTimeNs + 1;
+ int64_t bucketSizeNs = 30 * 1000 * 1000 * 1000LL;
EventMetric metric;
metric.set_id(1);
@@ -59,9 +59,9 @@
}
TEST(EventMetricProducerTest, TestEventsWithNonSlicedCondition) {
- uint64_t bucketStartTimeNs = 10000000000;
- uint64_t eventStartTimeNs = bucketStartTimeNs + 1;
- uint64_t bucketSizeNs = 30 * 1000 * 1000 * 1000LL;
+ int64_t bucketStartTimeNs = 10000000000;
+ int64_t eventStartTimeNs = bucketStartTimeNs + 1;
+ int64_t bucketSizeNs = 30 * 1000 * 1000 * 1000LL;
EventMetric metric;
metric.set_id(1);
@@ -86,8 +86,8 @@
}
TEST(EventMetricProducerTest, TestEventsWithSlicedCondition) {
- uint64_t bucketStartTimeNs = 10000000000;
- uint64_t bucketSizeNs = 30 * 1000 * 1000 * 1000LL;
+ int64_t bucketStartTimeNs = 10000000000;
+ int64_t bucketSizeNs = 30 * 1000 * 1000 * 1000LL;
int tagId = 1;
int conditionTagId = 2;
diff --git a/cmds/statsd/tests/metrics/GaugeMetricProducer_test.cpp b/cmds/statsd/tests/metrics/GaugeMetricProducer_test.cpp
index 7ca66fd..a1f865d 100644
--- a/cmds/statsd/tests/metrics/GaugeMetricProducer_test.cpp
+++ b/cmds/statsd/tests/metrics/GaugeMetricProducer_test.cpp
@@ -45,7 +45,7 @@
const int64_t bucket2StartTimeNs = bucketStartTimeNs + bucketSizeNs;
const int64_t bucket3StartTimeNs = bucketStartTimeNs + 2 * bucketSizeNs;
const int64_t bucket4StartTimeNs = bucketStartTimeNs + 3 * bucketSizeNs;
-const uint64_t eventUpgradeTimeNs = bucketStartTimeNs + 15 * NS_PER_SEC;
+const int64_t eventUpgradeTimeNs = bucketStartTimeNs + 15 * NS_PER_SEC;
TEST(GaugeMetricProducerTest, TestNoCondition) {
GaugeMetric metric;
@@ -160,7 +160,7 @@
gaugeProducer.notifyAppUpgrade(eventUpgradeTimeNs, "ANY.APP", 1, 1);
EXPECT_EQ(0UL, (*gaugeProducer.mCurrentSlicedBucket).count(DEFAULT_METRIC_DIMENSION_KEY));
EXPECT_EQ(1UL, gaugeProducer.mPastBuckets[DEFAULT_METRIC_DIMENSION_KEY].size());
- EXPECT_EQ(0UL, gaugeProducer.mCurrentBucketNum);
+ EXPECT_EQ(0L, gaugeProducer.mCurrentBucketNum);
EXPECT_EQ(eventUpgradeTimeNs, gaugeProducer.mCurrentBucketStartTimeNs);
// Partial buckets are not sent to anomaly tracker.
EXPECT_EQ(0, anomalyTracker->getSumOverPastBuckets(DEFAULT_METRIC_DIMENSION_KEY));
@@ -171,9 +171,9 @@
event2->write(10);
event2->init();
gaugeProducer.onMatchedLogEvent(1 /*log matcher index*/, *event2);
- EXPECT_EQ(0UL, gaugeProducer.mCurrentBucketNum);
+ EXPECT_EQ(0L, gaugeProducer.mCurrentBucketNum);
EXPECT_EQ(1UL, gaugeProducer.mPastBuckets[DEFAULT_METRIC_DIMENSION_KEY].size());
- EXPECT_EQ((uint64_t)eventUpgradeTimeNs, gaugeProducer.mCurrentBucketStartTimeNs);
+ EXPECT_EQ((int64_t)eventUpgradeTimeNs, gaugeProducer.mCurrentBucketStartTimeNs);
// Partial buckets are not sent to anomaly tracker.
EXPECT_EQ(0, anomalyTracker->getSumOverPastBuckets(DEFAULT_METRIC_DIMENSION_KEY));
@@ -184,9 +184,9 @@
event3->write(10);
event3->init();
gaugeProducer.onMatchedLogEvent(1 /*log matcher index*/, *event3);
- EXPECT_EQ(1UL, gaugeProducer.mCurrentBucketNum);
+ EXPECT_EQ(1L, gaugeProducer.mCurrentBucketNum);
EXPECT_EQ(2UL, gaugeProducer.mPastBuckets[DEFAULT_METRIC_DIMENSION_KEY].size());
- EXPECT_EQ((uint64_t)bucketStartTimeNs + bucketSizeNs, gaugeProducer.mCurrentBucketStartTimeNs);
+ EXPECT_EQ((int64_t)bucketStartTimeNs + bucketSizeNs, gaugeProducer.mCurrentBucketStartTimeNs);
EXPECT_EQ(1, anomalyTracker->getSumOverPastBuckets(DEFAULT_METRIC_DIMENSION_KEY));
// Next event should trigger creation of new bucket.
@@ -196,7 +196,7 @@
event4->write(10);
event4->init();
gaugeProducer.onMatchedLogEvent(1 /*log matcher index*/, *event4);
- EXPECT_EQ(2UL, gaugeProducer.mCurrentBucketNum);
+ EXPECT_EQ(2L, gaugeProducer.mCurrentBucketNum);
EXPECT_EQ(3UL, gaugeProducer.mPastBuckets[DEFAULT_METRIC_DIMENSION_KEY].size());
EXPECT_EQ(2, anomalyTracker->getSumOverPastBuckets(DEFAULT_METRIC_DIMENSION_KEY));
}
@@ -246,8 +246,8 @@
gaugeProducer.notifyAppUpgrade(eventUpgradeTimeNs, "ANY.APP", 1, 1);
EXPECT_EQ(1UL, gaugeProducer.mPastBuckets[DEFAULT_METRIC_DIMENSION_KEY].size());
- EXPECT_EQ(0UL, gaugeProducer.mCurrentBucketNum);
- EXPECT_EQ((uint64_t)eventUpgradeTimeNs, gaugeProducer.mCurrentBucketStartTimeNs);
+ EXPECT_EQ(0L, gaugeProducer.mCurrentBucketNum);
+ EXPECT_EQ((int64_t)eventUpgradeTimeNs, gaugeProducer.mCurrentBucketStartTimeNs);
EXPECT_EQ(1UL, gaugeProducer.mCurrentSlicedBucket->size());
EXPECT_EQ(2, gaugeProducer.mCurrentSlicedBucket->begin()
->second.front()
diff --git a/cmds/statsd/tests/metrics/MaxDurationTracker_test.cpp b/cmds/statsd/tests/metrics/MaxDurationTracker_test.cpp
index a0f1c00..bf04752 100644
--- a/cmds/statsd/tests/metrics/MaxDurationTracker_test.cpp
+++ b/cmds/statsd/tests/metrics/MaxDurationTracker_test.cpp
@@ -45,7 +45,7 @@
const HashableDimensionKey conditionKey = getMockedDimensionKey(TagId, 4, "1");
const HashableDimensionKey key1 = getMockedDimensionKey(TagId, 1, "1");
const HashableDimensionKey key2 = getMockedDimensionKey(TagId, 1, "2");
-const uint64_t bucketSizeNs = 30 * 1000 * 1000 * 1000LL;
+const int64_t bucketSizeNs = 30 * 1000 * 1000 * 1000LL;
TEST(MaxDurationTrackerTest, TestSimpleMaxDuration) {
const MetricDimensionKey eventKey = getMockedMetricDimensionKey(TagId, 0, "1");
@@ -58,9 +58,9 @@
unordered_map<MetricDimensionKey, vector<DurationBucket>> buckets;
- uint64_t bucketStartTimeNs = 10000000000;
- uint64_t bucketEndTimeNs = bucketStartTimeNs + bucketSizeNs;
- uint64_t bucketNum = 0;
+ int64_t bucketStartTimeNs = 10000000000;
+ int64_t bucketEndTimeNs = bucketStartTimeNs + bucketSizeNs;
+ int64_t bucketNum = 0;
int64_t metricId = 1;
MaxDurationTracker tracker(kConfigKey, metricId, eventKey, wizard, -1, dimensionInCondition,
@@ -80,7 +80,7 @@
tracker.flushIfNeeded(bucketStartTimeNs + bucketSizeNs + 1, &buckets);
EXPECT_TRUE(buckets.find(eventKey) != buckets.end());
EXPECT_EQ(1u, buckets[eventKey].size());
- EXPECT_EQ(20ULL, buckets[eventKey][0].mDuration);
+ EXPECT_EQ(20LL, buckets[eventKey][0].mDuration);
}
TEST(MaxDurationTrackerTest, TestStopAll) {
@@ -93,10 +93,10 @@
unordered_map<MetricDimensionKey, vector<DurationBucket>> buckets;
- uint64_t bucketSizeNs = 30 * 1000 * 1000 * 1000LL;
- uint64_t bucketStartTimeNs = 10000000000;
- uint64_t bucketEndTimeNs = bucketStartTimeNs + bucketSizeNs;
- uint64_t bucketNum = 0;
+ int64_t bucketSizeNs = 30 * 1000 * 1000 * 1000LL;
+ int64_t bucketStartTimeNs = 10000000000;
+ int64_t bucketEndTimeNs = bucketStartTimeNs + bucketSizeNs;
+ int64_t bucketNum = 0;
int64_t metricId = 1;
MaxDurationTracker tracker(kConfigKey, metricId, eventKey, wizard, -1, dimensionInCondition,
@@ -129,10 +129,10 @@
unordered_map<MetricDimensionKey, vector<DurationBucket>> buckets;
- uint64_t bucketSizeNs = 30 * 1000 * 1000 * 1000LL;
- uint64_t bucketStartTimeNs = 10000000000;
- uint64_t bucketEndTimeNs = bucketStartTimeNs + bucketSizeNs;
- uint64_t bucketNum = 0;
+ int64_t bucketSizeNs = 30 * 1000 * 1000 * 1000LL;
+ int64_t bucketStartTimeNs = 10000000000;
+ int64_t bucketEndTimeNs = bucketStartTimeNs + bucketSizeNs;
+ int64_t bucketNum = 0;
int64_t metricId = 1;
MaxDurationTracker tracker(kConfigKey, metricId, eventKey, wizard, -1, dimensionInCondition,
@@ -170,10 +170,10 @@
unordered_map<MetricDimensionKey, vector<DurationBucket>> buckets;
- uint64_t bucketSizeNs = 30 * 1000 * 1000 * 1000LL;
- uint64_t bucketStartTimeNs = 10000000000;
- uint64_t bucketEndTimeNs = bucketStartTimeNs + bucketSizeNs;
- uint64_t bucketNum = 0;
+ int64_t bucketSizeNs = 30 * 1000 * 1000 * 1000LL;
+ int64_t bucketStartTimeNs = 10000000000;
+ int64_t bucketEndTimeNs = bucketStartTimeNs + bucketSizeNs;
+ int64_t bucketNum = 0;
int64_t metricId = 1;
MaxDurationTracker tracker(kConfigKey, metricId, eventKey, wizard, -1, dimensionInCondition,
@@ -213,14 +213,14 @@
Start in first bucket, stop in second bucket. Condition turns on and off in the first bucket
and again turns on and off in the second bucket.
*/
- uint64_t bucketStartTimeNs = 10000000000;
- uint64_t bucketEndTimeNs = bucketStartTimeNs + bucketSizeNs;
- uint64_t eventStartTimeNs = bucketStartTimeNs + 1 * NS_PER_SEC;
- uint64_t conditionStarts1 = bucketStartTimeNs + 11 * NS_PER_SEC;
- uint64_t conditionStops1 = bucketStartTimeNs + 14 * NS_PER_SEC;
- uint64_t conditionStarts2 = bucketStartTimeNs + bucketSizeNs + 5 * NS_PER_SEC;
- uint64_t conditionStops2 = conditionStarts2 + 10 * NS_PER_SEC;
- uint64_t eventStopTimeNs = conditionStops2 + 8 * NS_PER_SEC;
+ int64_t bucketStartTimeNs = 10000000000;
+ int64_t bucketEndTimeNs = bucketStartTimeNs + bucketSizeNs;
+ int64_t eventStartTimeNs = bucketStartTimeNs + 1 * NS_PER_SEC;
+ int64_t conditionStarts1 = bucketStartTimeNs + 11 * NS_PER_SEC;
+ int64_t conditionStops1 = bucketStartTimeNs + 14 * NS_PER_SEC;
+ int64_t conditionStarts2 = bucketStartTimeNs + bucketSizeNs + 5 * NS_PER_SEC;
+ int64_t conditionStops2 = conditionStarts2 + 10 * NS_PER_SEC;
+ int64_t eventStopTimeNs = conditionStops2 + 8 * NS_PER_SEC;
int64_t metricId = 1;
MaxDurationTracker tracker(kConfigKey, metricId, eventKey, wizard, 1, dimensionInCondition,
@@ -242,7 +242,7 @@
EXPECT_EQ(1U, buckets.size());
vector<DurationBucket> item = buckets.begin()->second;
EXPECT_EQ(1UL, item.size());
- EXPECT_EQ(13ULL * NS_PER_SEC, item[0].mDuration);
+ EXPECT_EQ((int64_t)(13LL * NS_PER_SEC), item[0].mDuration);
}
TEST(MaxDurationTrackerTest, TestAnomalyDetection) {
@@ -255,11 +255,11 @@
unordered_map<MetricDimensionKey, vector<DurationBucket>> buckets;
- uint64_t bucketSizeNs = 30 * 1000 * 1000 * 1000LL;
- uint64_t bucketStartTimeNs = 10000000000;
- uint64_t bucketEndTimeNs = bucketStartTimeNs + bucketSizeNs;
- uint64_t bucketNum = 0;
- uint64_t eventStartTimeNs = 13000000000;
+ int64_t bucketSizeNs = 30 * 1000 * 1000 * 1000LL;
+ int64_t bucketStartTimeNs = 10000000000;
+ int64_t bucketEndTimeNs = bucketStartTimeNs + bucketSizeNs;
+ int64_t bucketNum = 0;
+ int64_t eventStartTimeNs = 13000000000;
int64_t durationTimeNs = 2 * 1000;
int64_t metricId = 1;
@@ -312,15 +312,15 @@
* dimension has already been running for 4 seconds. Thus, we have 40-4=36 seconds remaining
* before we trigger the anomaly.
*/
- uint64_t bucketSizeNs = 30 * 1000 * 1000 * 1000LL;
- uint64_t bucketStartTimeNs = 10000000000;
- uint64_t bucketEndTimeNs = bucketStartTimeNs + bucketSizeNs;
- uint64_t bucketNum = 0;
- uint64_t eventStartTimeNs = bucketStartTimeNs + 5 * NS_PER_SEC; // Condition is off at start.
- uint64_t conditionStarts1 = bucketStartTimeNs + 11 * NS_PER_SEC;
- uint64_t conditionStops1 = bucketStartTimeNs + 14 * NS_PER_SEC;
- uint64_t conditionStarts2 = bucketStartTimeNs + 20 * NS_PER_SEC;
- uint64_t eventStartTimeNs2 = conditionStarts2 - 4 * NS_PER_SEC;
+ int64_t bucketSizeNs = 30 * 1000 * 1000 * 1000LL;
+ int64_t bucketStartTimeNs = 10000000000;
+ int64_t bucketEndTimeNs = bucketStartTimeNs + bucketSizeNs;
+ int64_t bucketNum = 0;
+ int64_t eventStartTimeNs = bucketStartTimeNs + 5 * NS_PER_SEC; // Condition is off at start.
+ int64_t conditionStarts1 = bucketStartTimeNs + 11 * NS_PER_SEC;
+ int64_t conditionStops1 = bucketStartTimeNs + 14 * NS_PER_SEC;
+ int64_t conditionStarts2 = bucketStartTimeNs + 20 * NS_PER_SEC;
+ int64_t eventStartTimeNs2 = conditionStarts2 - 4 * NS_PER_SEC;
int64_t metricId = 1;
Alert alert;
@@ -344,9 +344,9 @@
tracker.noteConditionChanged(key1, true, conditionStarts2);
EXPECT_EQ(1U, anomalyTracker->mAlarms.size());
auto alarm = anomalyTracker->mAlarms.begin()->second;
- uint64_t anomalyFireTimeSec = alarm->timestampSec;
+ int64_t anomalyFireTimeSec = alarm->timestampSec;
EXPECT_EQ(conditionStarts2 + 36 * NS_PER_SEC,
- (unsigned long long)anomalyFireTimeSec * NS_PER_SEC);
+ (long long)anomalyFireTimeSec * NS_PER_SEC);
// Now we test the calculation now that there's a refractory period.
// At the correct time, declare the anomaly. This will set a refractory period. Make sure it
@@ -354,23 +354,23 @@
std::unordered_set<sp<const InternalAlarm>, SpHash<InternalAlarm>> firedAlarms({alarm});
anomalyTracker->informAlarmsFired(anomalyFireTimeSec * NS_PER_SEC, firedAlarms);
EXPECT_EQ(0u, anomalyTracker->mAlarms.size());
- uint64_t refractoryPeriodEndsSec = anomalyFireTimeSec + refPeriodSec;
+ int64_t refractoryPeriodEndsSec = anomalyFireTimeSec + refPeriodSec;
EXPECT_EQ(anomalyTracker->getRefractoryPeriodEndsSec(eventKey), refractoryPeriodEndsSec);
// Now stop and start again. Make sure the new predictAnomalyTimestampNs takes into account
// the refractory period correctly.
- uint64_t eventStopTimeNs = anomalyFireTimeSec * NS_PER_SEC + 10;
+ int64_t eventStopTimeNs = anomalyFireTimeSec * NS_PER_SEC + 10;
tracker.noteStop(key1, eventStopTimeNs, false);
tracker.noteStop(key2, eventStopTimeNs, false);
tracker.noteStart(key1, true, eventStopTimeNs + 1000000, conditionKey1);
// Anomaly is ongoing, but we're still in the refractory period.
EXPECT_EQ(1U, anomalyTracker->mAlarms.size());
alarm = anomalyTracker->mAlarms.begin()->second;
- EXPECT_EQ(refractoryPeriodEndsSec, (unsigned long long)(alarm->timestampSec));
+ EXPECT_EQ(refractoryPeriodEndsSec, (long long)(alarm->timestampSec));
// Makes sure it is correct after the refractory period is over.
tracker.noteStop(key1, eventStopTimeNs + 2000000, false);
- uint64_t justBeforeRefPeriodNs = (refractoryPeriodEndsSec - 2) * NS_PER_SEC;
+ int64_t justBeforeRefPeriodNs = (refractoryPeriodEndsSec - 2) * NS_PER_SEC;
tracker.noteStart(key1, true, justBeforeRefPeriodNs, conditionKey1);
alarm = anomalyTracker->mAlarms.begin()->second;
EXPECT_EQ(justBeforeRefPeriodNs + 40 * NS_PER_SEC,
@@ -397,13 +397,13 @@
* nested dimensions, are started for 8 seconds. When we stop, the other nested dimension has
* been started for 5 seconds. So we can only allow 35 more seconds from now.
*/
- uint64_t bucketSizeNs = 30 * 1000 * 1000 * 1000LL;
- uint64_t bucketStartTimeNs = 10000000000;
- uint64_t bucketEndTimeNs = bucketStartTimeNs + bucketSizeNs;
- uint64_t bucketNum = 0;
- uint64_t eventStartTimeNs1 = bucketStartTimeNs + 5 * NS_PER_SEC; // Condition is off at start.
- uint64_t eventStopTimeNs1 = bucketStartTimeNs + 13 * NS_PER_SEC;
- uint64_t eventStartTimeNs2 = bucketStartTimeNs + 8 * NS_PER_SEC;
+ int64_t bucketSizeNs = 30 * 1000 * 1000 * 1000LL;
+ int64_t bucketStartTimeNs = 10000000000;
+ int64_t bucketEndTimeNs = bucketStartTimeNs + bucketSizeNs;
+ int64_t bucketNum = 0;
+ int64_t eventStartTimeNs1 = bucketStartTimeNs + 5 * NS_PER_SEC; // Condition is off at start.
+ int64_t eventStopTimeNs1 = bucketStartTimeNs + 13 * NS_PER_SEC;
+ int64_t eventStartTimeNs2 = bucketStartTimeNs + 8 * NS_PER_SEC;
int64_t metricId = 1;
Alert alert;
diff --git a/cmds/statsd/tests/metrics/OringDurationTracker_test.cpp b/cmds/statsd/tests/metrics/OringDurationTracker_test.cpp
index 817dcae..7c2b423 100644
--- a/cmds/statsd/tests/metrics/OringDurationTracker_test.cpp
+++ b/cmds/statsd/tests/metrics/OringDurationTracker_test.cpp
@@ -44,7 +44,7 @@
const HashableDimensionKey kConditionKey1 = getMockedDimensionKey(TagId, 1, "maps");
const HashableDimensionKey kEventKey1 = getMockedDimensionKey(TagId, 2, "maps");
const HashableDimensionKey kEventKey2 = getMockedDimensionKey(TagId, 3, "maps");
-const uint64_t bucketSizeNs = 30 * NS_PER_SEC;
+const int64_t bucketSizeNs = 30 * NS_PER_SEC;
TEST(OringDurationTrackerTest, TestDurationOverlap) {
const MetricDimensionKey eventKey = getMockedMetricDimensionKey(TagId, 0, "event");
@@ -56,11 +56,11 @@
unordered_map<MetricDimensionKey, vector<DurationBucket>> buckets;
- uint64_t bucketSizeNs = 30 * 1000 * 1000 * 1000LL;
- uint64_t bucketStartTimeNs = 10000000000;
- uint64_t bucketNum = 0;
- uint64_t eventStartTimeNs = bucketStartTimeNs + 1;
- uint64_t durationTimeNs = 2 * 1000;
+ int64_t bucketSizeNs = 30 * 1000 * 1000 * 1000LL;
+ int64_t bucketStartTimeNs = 10000000000;
+ int64_t bucketNum = 0;
+ int64_t eventStartTimeNs = bucketStartTimeNs + 1;
+ int64_t durationTimeNs = 2 * 1000;
OringDurationTracker tracker(kConfigKey, metricId, eventKey, wizard, 1, dimensionInCondition,
false, bucketStartTimeNs, bucketNum, bucketStartTimeNs,
@@ -89,10 +89,10 @@
unordered_map<MetricDimensionKey, vector<DurationBucket>> buckets;
- uint64_t bucketSizeNs = 30 * 1000 * 1000 * 1000LL;
- uint64_t bucketStartTimeNs = 10000000000;
- uint64_t bucketNum = 0;
- uint64_t eventStartTimeNs = bucketStartTimeNs + 1;
+ int64_t bucketSizeNs = 30 * 1000 * 1000 * 1000LL;
+ int64_t bucketStartTimeNs = 10000000000;
+ int64_t bucketNum = 0;
+ int64_t eventStartTimeNs = bucketStartTimeNs + 1;
OringDurationTracker tracker(kConfigKey, metricId, eventKey, wizard, 1, dimensionInCondition,
true, bucketStartTimeNs, bucketNum, bucketStartTimeNs,
@@ -107,7 +107,7 @@
tracker.flushIfNeeded(bucketStartTimeNs + bucketSizeNs + 1, &buckets);
EXPECT_TRUE(buckets.find(eventKey) != buckets.end());
EXPECT_EQ(1u, buckets[eventKey].size());
- EXPECT_EQ(2003ULL, buckets[eventKey][0].mDuration);
+ EXPECT_EQ(2003LL, buckets[eventKey][0].mDuration);
}
TEST(OringDurationTrackerTest, TestStopAll) {
@@ -122,10 +122,10 @@
unordered_map<MetricDimensionKey, vector<DurationBucket>> buckets;
- uint64_t bucketSizeNs = 30 * 1000 * 1000 * 1000LL;
- uint64_t bucketStartTimeNs = 10000000000;
- uint64_t bucketNum = 0;
- uint64_t eventStartTimeNs = bucketStartTimeNs + 1;
+ int64_t bucketSizeNs = 30 * 1000 * 1000 * 1000LL;
+ int64_t bucketStartTimeNs = 10000000000;
+ int64_t bucketNum = 0;
+ int64_t eventStartTimeNs = bucketStartTimeNs + 1;
OringDurationTracker tracker(kConfigKey, metricId, eventKey, wizard, 1, dimensionInCondition,
true, bucketStartTimeNs, bucketNum, bucketStartTimeNs,
@@ -139,7 +139,7 @@
tracker.flushIfNeeded(bucketStartTimeNs + bucketSizeNs + 1, &buckets);
EXPECT_TRUE(buckets.find(eventKey) != buckets.end());
EXPECT_EQ(1u, buckets[eventKey].size());
- EXPECT_EQ(2003ULL, buckets[eventKey][0].mDuration);
+ EXPECT_EQ(2003LL, buckets[eventKey][0].mDuration);
}
TEST(OringDurationTrackerTest, TestCrossBucketBoundary) {
@@ -152,11 +152,11 @@
unordered_map<MetricDimensionKey, vector<DurationBucket>> buckets;
- uint64_t bucketSizeNs = 30 * 1000 * 1000 * 1000LL;
- uint64_t bucketStartTimeNs = 10000000000;
- uint64_t bucketNum = 0;
- uint64_t eventStartTimeNs = bucketStartTimeNs + 1;
- uint64_t durationTimeNs = 2 * 1000;
+ int64_t bucketSizeNs = 30 * 1000 * 1000 * 1000LL;
+ int64_t bucketStartTimeNs = 10000000000;
+ int64_t bucketNum = 0;
+ int64_t eventStartTimeNs = bucketStartTimeNs + 1;
+ int64_t durationTimeNs = 2 * 1000;
OringDurationTracker tracker(kConfigKey, metricId, eventKey, wizard, 1, dimensionInCondition,
true, bucketStartTimeNs, bucketNum, bucketStartTimeNs,
@@ -197,11 +197,11 @@
unordered_map<MetricDimensionKey, vector<DurationBucket>> buckets;
- uint64_t bucketSizeNs = 30 * 1000 * 1000 * 1000LL;
- uint64_t bucketStartTimeNs = 10000000000;
- uint64_t bucketNum = 0;
- uint64_t eventStartTimeNs = bucketStartTimeNs + 1;
- uint64_t durationTimeNs = 2 * 1000;
+ int64_t bucketSizeNs = 30 * 1000 * 1000 * 1000LL;
+ int64_t bucketStartTimeNs = 10000000000;
+ int64_t bucketNum = 0;
+ int64_t eventStartTimeNs = bucketStartTimeNs + 1;
+ int64_t durationTimeNs = 2 * 1000;
OringDurationTracker tracker(kConfigKey, metricId, eventKey, wizard, 1, dimensionInCondition,
false, bucketStartTimeNs, bucketNum, bucketStartTimeNs,
@@ -216,7 +216,7 @@
tracker.flushIfNeeded(bucketStartTimeNs + bucketSizeNs + 1, &buckets);
EXPECT_TRUE(buckets.find(eventKey) != buckets.end());
EXPECT_EQ(1u, buckets[eventKey].size());
- EXPECT_EQ(5ULL, buckets[eventKey][0].mDuration);
+ EXPECT_EQ(5LL, buckets[eventKey][0].mDuration);
}
TEST(OringDurationTrackerTest, TestDurationConditionChange2) {
@@ -237,11 +237,11 @@
unordered_map<MetricDimensionKey, vector<DurationBucket>> buckets;
- uint64_t bucketStartTimeNs = 10000000000;
- uint64_t bucketSizeNs = 30 * 1000 * 1000 * 1000LL;
- uint64_t bucketNum = 0;
- uint64_t eventStartTimeNs = bucketStartTimeNs + 1;
- uint64_t durationTimeNs = 2 * 1000;
+ int64_t bucketStartTimeNs = 10000000000;
+ int64_t bucketSizeNs = 30 * 1000 * 1000 * 1000LL;
+ int64_t bucketNum = 0;
+ int64_t eventStartTimeNs = bucketStartTimeNs + 1;
+ int64_t durationTimeNs = 2 * 1000;
OringDurationTracker tracker(kConfigKey, metricId, eventKey, wizard, 1, dimensionInCondition,
false, bucketStartTimeNs, bucketNum, bucketStartTimeNs,
@@ -258,7 +258,7 @@
tracker.flushIfNeeded(bucketStartTimeNs + bucketSizeNs + 1, &buckets);
EXPECT_TRUE(buckets.find(eventKey) != buckets.end());
EXPECT_EQ(1u, buckets[eventKey].size());
- EXPECT_EQ(1005ULL, buckets[eventKey][0].mDuration);
+ EXPECT_EQ(1005LL, buckets[eventKey][0].mDuration);
}
TEST(OringDurationTrackerTest, TestDurationConditionChangeNested) {
@@ -277,10 +277,10 @@
unordered_map<MetricDimensionKey, vector<DurationBucket>> buckets;
- uint64_t bucketStartTimeNs = 10000000000;
- uint64_t bucketSizeNs = 30 * 1000 * 1000 * 1000LL;
- uint64_t bucketNum = 0;
- uint64_t eventStartTimeNs = bucketStartTimeNs + 1;
+ int64_t bucketStartTimeNs = 10000000000;
+ int64_t bucketSizeNs = 30 * 1000 * 1000 * 1000LL;
+ int64_t bucketNum = 0;
+ int64_t eventStartTimeNs = bucketStartTimeNs + 1;
OringDurationTracker tracker(kConfigKey, metricId, eventKey, wizard, 1, dimensionInCondition,
true, bucketStartTimeNs, bucketNum, bucketStartTimeNs,
@@ -298,7 +298,7 @@
tracker.flushIfNeeded(bucketStartTimeNs + bucketSizeNs + 1, &buckets);
EXPECT_TRUE(buckets.find(eventKey) != buckets.end());
EXPECT_EQ(1u, buckets[eventKey].size());
- EXPECT_EQ(15ULL, buckets[eventKey][0].mDuration);
+ EXPECT_EQ(15LL, buckets[eventKey][0].mDuration);
}
TEST(OringDurationTrackerTest, TestPredictAnomalyTimestamp) {
@@ -317,9 +317,9 @@
unordered_map<MetricDimensionKey, vector<DurationBucket>> buckets;
sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
- uint64_t bucketStartTimeNs = 10 * NS_PER_SEC;
- uint64_t bucketNum = 0;
- uint64_t eventStartTimeNs = bucketStartTimeNs + NS_PER_SEC + 1;
+ int64_t bucketStartTimeNs = 10 * NS_PER_SEC;
+ int64_t bucketNum = 0;
+ int64_t eventStartTimeNs = bucketStartTimeNs + NS_PER_SEC + 1;
sp<AlarmMonitor> alarmMonitor;
sp<DurationAnomalyTracker> anomalyTracker =
@@ -336,26 +336,26 @@
tracker.noteStop(DEFAULT_DIMENSION_KEY, eventStartTimeNs + 3, false);
EXPECT_EQ(0u, buckets[eventKey].size());
- uint64_t event1StartTimeNs = eventStartTimeNs + 10;
+ int64_t event1StartTimeNs = eventStartTimeNs + 10;
tracker.noteStart(kEventKey1, true, event1StartTimeNs, ConditionKey());
// No past buckets. The anomaly will happen in bucket #0.
EXPECT_EQ((long long)(event1StartTimeNs + alert.trigger_if_sum_gt() - 3),
tracker.predictAnomalyTimestampNs(*anomalyTracker, event1StartTimeNs));
- uint64_t event1StopTimeNs = eventStartTimeNs + bucketSizeNs + 10;
+ int64_t event1StopTimeNs = eventStartTimeNs + bucketSizeNs + 10;
tracker.flushIfNeeded(event1StopTimeNs, &buckets);
tracker.noteStop(kEventKey1, event1StopTimeNs, false);
EXPECT_TRUE(buckets.find(eventKey) != buckets.end());
EXPECT_EQ(1u, buckets[eventKey].size());
- EXPECT_EQ(3ULL + bucketStartTimeNs + bucketSizeNs - eventStartTimeNs - 10,
+ EXPECT_EQ(3LL + bucketStartTimeNs + bucketSizeNs - eventStartTimeNs - 10,
buckets[eventKey][0].mDuration);
const int64_t bucket0Duration = 3ULL + bucketStartTimeNs + bucketSizeNs - eventStartTimeNs - 10;
const int64_t bucket1Duration = eventStartTimeNs + 10 - bucketStartTimeNs;
// One past buckets. The anomaly will happen in bucket #1.
- uint64_t event2StartTimeNs = eventStartTimeNs + bucketSizeNs + 15;
+ int64_t event2StartTimeNs = eventStartTimeNs + bucketSizeNs + 15;
tracker.noteStart(kEventKey1, true, event2StartTimeNs, ConditionKey());
EXPECT_EQ((long long)(event2StartTimeNs + alert.trigger_if_sum_gt() - bucket0Duration -
bucket1Duration),
@@ -364,7 +364,7 @@
// Only one past buckets is applicable. Bucket +0 should be trashed. The anomaly will happen in
// bucket #2.
- uint64_t event3StartTimeNs = bucketStartTimeNs + 2 * bucketSizeNs - 9 * NS_PER_SEC;
+ int64_t event3StartTimeNs = bucketStartTimeNs + 2 * bucketSizeNs - 9 * NS_PER_SEC;
tracker.noteStart(kEventKey1, true, event3StartTimeNs, ConditionKey());
EXPECT_EQ((long long)(event3StartTimeNs + alert.trigger_if_sum_gt() - bucket1Duration - 1LL),
tracker.predictAnomalyTimestampNs(*anomalyTracker, event3StartTimeNs));
@@ -379,8 +379,8 @@
alert.set_num_buckets(1);
alert.set_refractory_period_secs(20);
- uint64_t bucketStartTimeNs = 10 * NS_PER_SEC;
- uint64_t bucketNum = 0;
+ int64_t bucketStartTimeNs = 10 * NS_PER_SEC;
+ int64_t bucketNum = 0;
sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
sp<AlarmMonitor> alarmMonitor;
@@ -391,7 +391,7 @@
true, bucketStartTimeNs, bucketNum, bucketStartTimeNs,
bucketSizeNs, true, false, {anomalyTracker});
- uint64_t eventStartTimeNs = bucketStartTimeNs + 9 * NS_PER_SEC;
+ int64_t eventStartTimeNs = bucketStartTimeNs + 9 * NS_PER_SEC;
tracker.noteStart(DEFAULT_DIMENSION_KEY, true, eventStartTimeNs, ConditionKey());
// Anomaly happens in the bucket #1.
EXPECT_EQ((long long)(bucketStartTimeNs + 14 * NS_PER_SEC),
@@ -402,7 +402,7 @@
EXPECT_EQ((long long)(bucketStartTimeNs + 34 * NS_PER_SEC) / NS_PER_SEC,
anomalyTracker->getRefractoryPeriodEndsSec(DEFAULT_METRIC_DIMENSION_KEY));
- uint64_t event2StartTimeNs = bucketStartTimeNs + 22 * NS_PER_SEC;
+ int64_t event2StartTimeNs = bucketStartTimeNs + 22 * NS_PER_SEC;
EXPECT_EQ((long long)(bucketStartTimeNs + 34 * NS_PER_SEC) / NS_PER_SEC,
anomalyTracker->getRefractoryPeriodEndsSec(DEFAULT_METRIC_DIMENSION_KEY));
EXPECT_EQ((long long)(bucketStartTimeNs + 35 * NS_PER_SEC),
@@ -413,7 +413,7 @@
// Test the cases where the refractory period is smaller than the bucket size, longer than
// the bucket size, and longer than 2x of the anomaly detection window.
for (int j = 0; j < 3; j++) {
- uint64_t thresholdNs = j * bucketSizeNs + 5 * NS_PER_SEC;
+ int64_t thresholdNs = j * bucketSizeNs + 5 * NS_PER_SEC;
for (int i = 0; i <= 7; ++i) {
vector<Matcher> dimensionInCondition;
Alert alert;
@@ -424,8 +424,8 @@
alert.set_refractory_period_secs(
bucketSizeNs / NS_PER_SEC / 2 + i * bucketSizeNs / NS_PER_SEC);
- uint64_t bucketStartTimeNs = 10 * NS_PER_SEC;
- uint64_t bucketNum = 101;
+ int64_t bucketStartTimeNs = 10 * NS_PER_SEC;
+ int64_t bucketNum = 101;
sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
sp<AlarmMonitor> alarmMonitor;
@@ -436,32 +436,32 @@
true, bucketStartTimeNs, bucketNum, bucketStartTimeNs,
bucketSizeNs, true, false, {anomalyTracker});
- uint64_t eventStartTimeNs = bucketStartTimeNs + 9 * NS_PER_SEC;
+ int64_t eventStartTimeNs = bucketStartTimeNs + 9 * NS_PER_SEC;
tracker.noteStart(DEFAULT_DIMENSION_KEY, true, eventStartTimeNs, ConditionKey());
EXPECT_EQ((long long)(eventStartTimeNs + thresholdNs),
tracker.predictAnomalyTimestampNs(*anomalyTracker, eventStartTimeNs));
- uint64_t eventStopTimeNs = eventStartTimeNs + thresholdNs + NS_PER_SEC;
+ int64_t eventStopTimeNs = eventStartTimeNs + thresholdNs + NS_PER_SEC;
tracker.noteStop(DEFAULT_DIMENSION_KEY, eventStopTimeNs, false);
- uint64_t refractoryPeriodEndSec =
+ int64_t refractoryPeriodEndSec =
anomalyTracker->getRefractoryPeriodEndsSec(DEFAULT_METRIC_DIMENSION_KEY);
- EXPECT_EQ((long long)(eventStopTimeNs) / NS_PER_SEC + alert.refractory_period_secs(),
+ EXPECT_EQ(eventStopTimeNs / (int64_t)NS_PER_SEC + alert.refractory_period_secs(),
refractoryPeriodEndSec);
// Acquire and release a wakelock in the next bucket.
- uint64_t event2StartTimeNs = eventStopTimeNs + bucketSizeNs;
+ int64_t event2StartTimeNs = eventStopTimeNs + bucketSizeNs;
tracker.noteStart(DEFAULT_DIMENSION_KEY, true, event2StartTimeNs, ConditionKey());
- uint64_t event2StopTimeNs = event2StartTimeNs + 4 * NS_PER_SEC;
+ int64_t event2StopTimeNs = event2StartTimeNs + 4 * NS_PER_SEC;
tracker.noteStop(DEFAULT_DIMENSION_KEY, event2StopTimeNs, false);
// Test the alarm prediction works well when seeing another wakelock start event.
for (int k = 0; k <= 2; ++k) {
- uint64_t event3StartTimeNs = event2StopTimeNs + NS_PER_SEC + k * bucketSizeNs;
- uint64_t alarmTimestampNs =
+ int64_t event3StartTimeNs = event2StopTimeNs + NS_PER_SEC + k * bucketSizeNs;
+ int64_t alarmTimestampNs =
tracker.predictAnomalyTimestampNs(*anomalyTracker, event3StartTimeNs);
EXPECT_GT(alarmTimestampNs, 0u);
EXPECT_GE(alarmTimestampNs, event3StartTimeNs);
- EXPECT_GE(alarmTimestampNs, refractoryPeriodEndSec * NS_PER_SEC);
+ EXPECT_GE(alarmTimestampNs, refractoryPeriodEndSec *(int64_t) NS_PER_SEC);
}
}
}
@@ -484,9 +484,9 @@
unordered_map<MetricDimensionKey, vector<DurationBucket>> buckets;
sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
- uint64_t bucketStartTimeNs = 10 * NS_PER_SEC;
- uint64_t bucketNum = 0;
- uint64_t eventStartTimeNs = bucketStartTimeNs + NS_PER_SEC + 1;
+ int64_t bucketStartTimeNs = 10 * NS_PER_SEC;
+ int64_t bucketNum = 0;
+ int64_t eventStartTimeNs = bucketStartTimeNs + NS_PER_SEC + 1;
sp<AlarmMonitor> alarmMonitor;
sp<DurationAnomalyTracker> anomalyTracker =
@@ -535,8 +535,8 @@
sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
ConditionKey conkey;
conkey[StringToId("APP_BACKGROUND")] = kConditionKey1;
- uint64_t bucketStartTimeNs = 10 * NS_PER_SEC;
- uint64_t bucketSizeNs = 30 * NS_PER_SEC;
+ int64_t bucketStartTimeNs = 10 * NS_PER_SEC;
+ int64_t bucketSizeNs = 30 * NS_PER_SEC;
sp<AlarmMonitor> alarmMonitor;
sp<DurationAnomalyTracker> anomalyTracker =
diff --git a/cmds/statsd/tests/metrics/ValueMetricProducer_test.cpp b/cmds/statsd/tests/metrics/ValueMetricProducer_test.cpp
index c650a06..a2bb734 100644
--- a/cmds/statsd/tests/metrics/ValueMetricProducer_test.cpp
+++ b/cmds/statsd/tests/metrics/ValueMetricProducer_test.cpp
@@ -234,7 +234,7 @@
valueProducer.notifyAppUpgrade(eventUpgradeTimeNs, "ANY.APP", 1, 1);
EXPECT_EQ(1UL, valueProducer.mPastBuckets[DEFAULT_METRIC_DIMENSION_KEY].size());
- EXPECT_EQ((uint64_t)eventUpgradeTimeNs, valueProducer.mCurrentBucketStartTimeNs);
+ EXPECT_EQ(eventUpgradeTimeNs, valueProducer.mCurrentBucketStartTimeNs);
shared_ptr<LogEvent> event2 = make_shared<LogEvent>(tagId, bucketStartTimeNs + 59 * NS_PER_SEC);
event2->write(1);
@@ -242,7 +242,7 @@
event2->init();
valueProducer.onMatchedLogEvent(1 /*log matcher index*/, *event2);
EXPECT_EQ(1UL, valueProducer.mPastBuckets[DEFAULT_METRIC_DIMENSION_KEY].size());
- EXPECT_EQ((uint64_t)eventUpgradeTimeNs, valueProducer.mCurrentBucketStartTimeNs);
+ EXPECT_EQ(eventUpgradeTimeNs, valueProducer.mCurrentBucketStartTimeNs);
// Next value should create a new bucket.
shared_ptr<LogEvent> event3 = make_shared<LogEvent>(tagId, bucketStartTimeNs + 65 * NS_PER_SEC);
@@ -251,7 +251,7 @@
event3->init();
valueProducer.onMatchedLogEvent(1 /*log matcher index*/, *event3);
EXPECT_EQ(2UL, valueProducer.mPastBuckets[DEFAULT_METRIC_DIMENSION_KEY].size());
- EXPECT_EQ((uint64_t)bucketStartTimeNs + bucketSizeNs, valueProducer.mCurrentBucketStartTimeNs);
+ EXPECT_EQ(bucketStartTimeNs + bucketSizeNs, valueProducer.mCurrentBucketStartTimeNs);
}
TEST(ValueMetricProducerTest, TestPulledValueWithUpgrade) {
@@ -294,7 +294,7 @@
valueProducer.notifyAppUpgrade(eventUpgradeTimeNs, "ANY.APP", 1, 1);
EXPECT_EQ(1UL, valueProducer.mPastBuckets[DEFAULT_METRIC_DIMENSION_KEY].size());
- EXPECT_EQ((uint64_t)eventUpgradeTimeNs, valueProducer.mCurrentBucketStartTimeNs);
+ EXPECT_EQ(eventUpgradeTimeNs, valueProducer.mCurrentBucketStartTimeNs);
EXPECT_EQ(20L, valueProducer.mPastBuckets[DEFAULT_METRIC_DIMENSION_KEY][0].mValue);
allData.clear();
@@ -305,7 +305,7 @@
allData.push_back(event);
valueProducer.onDataPulled(allData);
EXPECT_EQ(2UL, valueProducer.mPastBuckets[DEFAULT_METRIC_DIMENSION_KEY].size());
- EXPECT_EQ((uint64_t)bucket2StartTimeNs, valueProducer.mCurrentBucketStartTimeNs);
+ EXPECT_EQ(bucket2StartTimeNs, valueProducer.mCurrentBucketStartTimeNs);
EXPECT_EQ(30L, valueProducer.mPastBuckets[DEFAULT_METRIC_DIMENSION_KEY][1].mValue);
}
diff --git a/cmds/statsd/tests/statsd_test_util.cpp b/cmds/statsd/tests/statsd_test_util.cpp
index 0acd297..649c399 100644
--- a/cmds/statsd/tests/statsd_test_util.cpp
+++ b/cmds/statsd/tests/statsd_test_util.cpp
@@ -455,7 +455,7 @@
[](const sp<IStatsCompanionService>&){});
sp<StatsLogProcessor> processor = new StatsLogProcessor(
uidMap, anomalyAlarmMonitor, periodicAlarmMonitor, timeBaseSec, [](const ConfigKey&){});
- processor->OnConfigUpdated(timeBaseSec, key, config);
+ processor->OnConfigUpdated(timeBaseSec * NS_PER_SEC, key, config);
return processor;
}
diff --git a/config/hiddenapi-light-greylist.txt b/config/hiddenapi-light-greylist.txt
index 36cb49c..422eec6 100644
--- a/config/hiddenapi-light-greylist.txt
+++ b/config/hiddenapi-light-greylist.txt
@@ -3,6 +3,7 @@
Landroid/accounts/IAccountManager$Stub;->asInterface(Landroid/os/IBinder;)Landroid/accounts/IAccountManager;
Landroid/accounts/IAccountManager$Stub$Proxy;-><init>(Landroid/os/IBinder;)V
Landroid/animation/LayoutTransition;->cancel()V
+Landroid/animation/LayoutTransition;->cancel(I)V
Landroid/animation/ValueAnimator;->animateValue(F)V
Landroid/animation/ValueAnimator;->sDurationScale:F
Landroid/app/Activity;->getActivityOptions()Landroid/app/ActivityOptions;
@@ -393,6 +394,7 @@
Landroid/appwidget/AppWidgetManager;->bindAppWidgetId(ILandroid/content/ComponentName;Landroid/os/Bundle;)V
Landroid/appwidget/AppWidgetManager;->bindAppWidgetId(ILandroid/content/ComponentName;)V
Landroid/appwidget/AppWidgetManager;->mService:Lcom/android/internal/appwidget/IAppWidgetService;
+Landroid/appwidget/AppWidgetProviderInfo;->providerInfo:Landroid/content/pm/ActivityInfo;
Landroid/bluetooth/BluetoothA2dp;->connect(Landroid/bluetooth/BluetoothDevice;)Z
Landroid/bluetooth/BluetoothAdapter;->disable(Z)Z
Landroid/bluetooth/BluetoothAdapter;->factoryReset()Z
@@ -761,7 +763,6 @@
Landroid/graphics/GraphicBuffer;->CREATOR:Landroid/os/Parcelable$Creator;
Landroid/graphics/GraphicBuffer;-><init>(IIIIJ)V
Landroid/graphics/GraphicBuffer;->mNativeObject:J
-Landroid/graphics/ImageDecoder;-><init>(JIIZ)V
Landroid/graphics/ImageDecoder;->postProcessAndRelease(Landroid/graphics/Canvas;)I
Landroid/graphics/LinearGradient;->mColors:[I
Landroid/graphics/Matrix;->native_instance:J
@@ -2268,6 +2269,7 @@
Landroid/view/View;->computeOpaqueFlags()V
Landroid/view/ViewConfiguration;->getDeviceGlobalActionKeyTimeout()J
Landroid/view/ViewConfiguration;->getDoubleTapMinTime()I
+Landroid/view/ViewConfiguration;->getScaledScrollFactor()I
Landroid/view/ViewConfiguration;->mFadingMarqueeEnabled:Z
Landroid/view/ViewConfiguration;->sHasPermanentMenuKeySet:Z
Landroid/view/ViewConfiguration;->sHasPermanentMenuKey:Z
diff --git a/core/java/android/app/ApplicationPackageManager.java b/core/java/android/app/ApplicationPackageManager.java
index a68136b..27bbc4b 100644
--- a/core/java/android/app/ApplicationPackageManager.java
+++ b/core/java/android/app/ApplicationPackageManager.java
@@ -2155,10 +2155,10 @@
public String[] setPackagesSuspended(String[] packageNames, boolean suspended,
PersistableBundle appExtras, PersistableBundle launcherExtras,
String dialogMessage) {
- // TODO (b/75332201): Pass in the dialogMessage and use it in the interceptor dialog
try {
return mPM.setPackagesSuspendedAsUser(packageNames, suspended, appExtras,
- launcherExtras, mContext.getOpPackageName(), mContext.getUserId());
+ launcherExtras, dialogMessage, mContext.getOpPackageName(),
+ mContext.getUserId());
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
diff --git a/core/java/android/app/ContextImpl.java b/core/java/android/app/ContextImpl.java
index 71b88fa..9a491bc 100644
--- a/core/java/android/app/ContextImpl.java
+++ b/core/java/android/app/ContextImpl.java
@@ -16,6 +16,7 @@
package android.app;
+import android.annotation.IntDef;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.TestApi;
@@ -88,11 +89,12 @@
import java.io.FilenameFilter;
import java.io.IOException;
import java.io.InputStream;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
import java.nio.ByteOrder;
import java.util.ArrayList;
import java.util.Objects;
import java.util.concurrent.Executor;
-import java.util.concurrent.atomic.AtomicInteger;
class ReceiverRestrictedContext extends ContextWrapper {
ReceiverRestrictedContext(Context base) {
@@ -212,13 +214,24 @@
static final int STATE_UNINITIALIZED = 0;
static final int STATE_INITIALIZING = 1;
static final int STATE_READY = 2;
+ static final int STATE_NOT_FOUND = 3;
+
+ /** @hide */
+ @IntDef(prefix = { "STATE_" }, value = {
+ STATE_UNINITIALIZED,
+ STATE_INITIALIZING,
+ STATE_READY,
+ STATE_NOT_FOUND,
+ })
+ @Retention(RetentionPolicy.SOURCE)
+ @interface ServiceInitializationState {}
/**
* Initialization state for each service. Any of {@link #STATE_UNINITIALIZED},
* {@link #STATE_INITIALIZING} or {@link #STATE_READY},
*/
- final AtomicInteger[] mServiceInitializationStateArray =
- SystemServiceRegistry.createServiceInitializationStateArray();
+ @ServiceInitializationState
+ final int[] mServiceInitializationStateArray = new int[mServiceCache.length];
static ContextImpl getImpl(Context context) {
Context nextContext;
diff --git a/core/java/android/app/Notification.java b/core/java/android/app/Notification.java
index 4326ee3..86fedb1 100644
--- a/core/java/android/app/Notification.java
+++ b/core/java/android/app/Notification.java
@@ -6678,7 +6678,8 @@
public RemoteViews makeContentView(boolean increasedHeight) {
mBuilder.mOriginalActions = mBuilder.mActions;
mBuilder.mActions = new ArrayList<>();
- RemoteViews remoteViews = makeMessagingView(true /* isCollapsed */);
+ RemoteViews remoteViews = makeMessagingView(true /* displayImagesAtEnd */,
+ true /* showReplyIcon */);
mBuilder.mActions = mBuilder.mOriginalActions;
mBuilder.mOriginalActions = null;
return remoteViews;
@@ -6765,11 +6766,19 @@
*/
@Override
public RemoteViews makeBigContentView() {
- return makeMessagingView(false /* isCollapsed */);
+ return makeMessagingView(false /* displayImagesAtEnd */, false /* showReplyIcon */);
}
+ /**
+ * Create a messaging layout.
+ *
+ * @param displayImagesAtEnd should images be displayed at the end of the content instead
+ * of inline.
+ * @param showReplyIcon Should the reply affordance be shown at the end of the notification
+ * @return the created remoteView.
+ */
@NonNull
- private RemoteViews makeMessagingView(boolean isCollapsed) {
+ private RemoteViews makeMessagingView(boolean displayImagesAtEnd, boolean showReplyIcon) {
CharSequence conversationTitle = !TextUtils.isEmpty(super.mBigContentTitle)
? super.mBigContentTitle
: mConversationTitle;
@@ -6780,24 +6789,24 @@
nameReplacement = conversationTitle;
conversationTitle = null;
}
- boolean hideLargeIcon = !isCollapsed || isOneToOne;
+ boolean hideLargeIcon = !showReplyIcon || isOneToOne;
RemoteViews contentView = mBuilder.applyStandardTemplateWithActions(
mBuilder.getMessagingLayoutResource(),
mBuilder.mParams.reset().hasProgress(false).title(conversationTitle).text(null)
.hideLargeIcon(hideLargeIcon)
.headerTextSecondary(conversationTitle)
- .alwaysShowReply(isCollapsed));
+ .alwaysShowReply(showReplyIcon));
addExtras(mBuilder.mN.extras);
// also update the end margin if there is an image
int endMargin = R.dimen.notification_content_margin_end;
- if (isCollapsed) {
+ if (showReplyIcon) {
endMargin = R.dimen.notification_content_plus_picture_margin_end;
}
contentView.setViewLayoutMarginEndDimen(R.id.notification_main_column, endMargin);
contentView.setInt(R.id.status_bar_latest_event_content, "setLayoutColor",
mBuilder.resolveContrastColor());
- contentView.setBoolean(R.id.status_bar_latest_event_content, "setIsCollapsed",
- isCollapsed);
+ contentView.setBoolean(R.id.status_bar_latest_event_content, "setDisplayImagesAtEnd",
+ displayImagesAtEnd);
contentView.setIcon(R.id.status_bar_latest_event_content, "setLargeIcon",
mBuilder.mN.mLargeIcon);
contentView.setCharSequence(R.id.status_bar_latest_event_content, "setNameReplacement",
@@ -6864,7 +6873,8 @@
*/
@Override
public RemoteViews makeHeadsUpContentView(boolean increasedHeight) {
- RemoteViews remoteViews = makeMessagingView(true /* isCollapsed */);
+ RemoteViews remoteViews = makeMessagingView(true /* displayImagesAtEnd */,
+ false /* showReplyIcon */);
remoteViews.setInt(R.id.notification_messaging, "setMaxDisplayedLines", 1);
return remoteViews;
}
diff --git a/core/java/android/app/SystemServiceRegistry.java b/core/java/android/app/SystemServiceRegistry.java
index 95e4f93..3ee1ed5 100644
--- a/core/java/android/app/SystemServiceRegistry.java
+++ b/core/java/android/app/SystemServiceRegistry.java
@@ -18,6 +18,7 @@
import android.accounts.AccountManager;
import android.accounts.IAccountManager;
+import android.app.ContextImpl.ServiceInitializationState;
import android.app.admin.DevicePolicyManager;
import android.app.admin.IDevicePolicyManager;
import android.app.job.IJobScheduler;
@@ -160,7 +161,6 @@
import com.android.internal.policy.PhoneLayoutInflater;
import java.util.HashMap;
-import java.util.concurrent.atomic.AtomicInteger;
/**
* Manages all of the system services that can be returned by {@link Context#getSystemService}.
@@ -993,10 +993,6 @@
return new Object[sServiceCacheSize];
}
- public static AtomicInteger[] createServiceInitializationStateArray() {
- return new AtomicInteger[sServiceCacheSize];
- }
-
/**
* Gets a system service from a given context.
*/
@@ -1037,7 +1033,10 @@
static abstract class CachedServiceFetcher<T> implements ServiceFetcher<T> {
private final int mCacheIndex;
- public CachedServiceFetcher() {
+ CachedServiceFetcher() {
+ // Note this class must be instantiated only by the static initializer of the
+ // outer class (SystemServiceRegistry), which already does the synchronization,
+ // so bare access to sServiceCacheSize is okay here.
mCacheIndex = sServiceCacheSize++;
}
@@ -1045,95 +1044,73 @@
@SuppressWarnings("unchecked")
public final T getService(ContextImpl ctx) {
final Object[] cache = ctx.mServiceCache;
+ final int[] gates = ctx.mServiceInitializationStateArray;
- // Fast path. If it's already cached, just return it.
- Object service = cache[mCacheIndex];
- if (service != null) {
- return (T) service;
- }
+ for (;;) {
+ boolean doInitialize = false;
+ synchronized (cache) {
+ // Return it if we already have a cached instance.
+ T service = (T) cache[mCacheIndex];
+ if (service != null || gates[mCacheIndex] == ContextImpl.STATE_NOT_FOUND) {
+ return service;
+ }
- // Slow path.
- final AtomicInteger[] gates = ctx.mServiceInitializationStateArray;
- final AtomicInteger gate;
+ // If we get here, there's no cached instance.
- synchronized (cache) {
- // See if it's cached or not again, with the lock held this time.
- service = cache[mCacheIndex];
- if (service != null) {
- return (T) service;
+ // Grr... if gate is STATE_READY, then this means we initialized the service
+ // once but someone cleared it.
+ // We start over from STATE_UNINITIALIZED.
+ if (gates[mCacheIndex] == ContextImpl.STATE_READY) {
+ gates[mCacheIndex] = ContextImpl.STATE_UNINITIALIZED;
+ }
+
+ // It's possible for multiple threads to get here at the same time, so
+ // use the "gate" to make sure only the first thread will call createService().
+
+ // At this point, the gate must be either UNINITIALIZED or INITIALIZING.
+ if (gates[mCacheIndex] == ContextImpl.STATE_UNINITIALIZED) {
+ doInitialize = true;
+ gates[mCacheIndex] = ContextImpl.STATE_INITIALIZING;
+ }
}
- // Not initialized yet. Create an atomic boolean to control which thread should
- // instantiate the service.
- if (gates[mCacheIndex] != null) {
- gate = gates[mCacheIndex];
- } else {
- gate = new AtomicInteger(ContextImpl.STATE_UNINITIALIZED);
- gates[mCacheIndex] = gate;
- }
- }
+ if (doInitialize) {
+ // Only the first thread gets here.
- // Not cached yet.
- //
- // Note multiple threads can reach here for the same service on the same context
- // concurrently.
- //
- // Now we're going to instantiate the service, but do so without the cache held;
- // otherwise it could deadlock. (b/71882178)
- //
- // However we still don't want to instantiate the same service multiple times, so
- // use the atomic integer to ensure only one thread will call createService().
-
- if (gate.compareAndSet(
- ContextImpl.STATE_UNINITIALIZED, ContextImpl.STATE_INITIALIZING)) {
- try {
- // This thread is the first one to get here. Instantiate the service
- // *without* the cache lock held.
+ T service = null;
+ @ServiceInitializationState int newState = ContextImpl.STATE_NOT_FOUND;
try {
+ // This thread is the first one to get here. Instantiate the service
+ // *without* the cache lock held.
service = createService(ctx);
+ newState = ContextImpl.STATE_READY;
- synchronized (cache) {
- cache[mCacheIndex] = service;
- }
} catch (ServiceNotFoundException e) {
onServiceNotFound(e);
- }
- } finally {
- // Tell the all other threads that the cache is ready now.
- // (But it's still be null in case of ServiceNotFoundException.)
- synchronized (gate) {
- gate.set(ContextImpl.STATE_READY);
- gate.notifyAll();
- }
- }
- return (T) service;
- }
- // Other threads will wait on the gate lock.
- synchronized (gate) {
- boolean interrupted = false;
- // Note: We check whether "state == STATE_READY", not
- // "cache[mCacheIndex] != null", because "cache[mCacheIndex] == null"
- // is still a valid outcome in the ServiceNotFoundException case.
- while (gate.get() != ContextImpl.STATE_READY) {
- try {
- gate.wait();
- } catch (InterruptedException e) {
- Log.w(TAG, "getService() interrupted");
- interrupted = true;
+ } finally {
+ synchronized (cache) {
+ cache[mCacheIndex] = service;
+ gates[mCacheIndex] = newState;
+ cache.notifyAll();
+ }
+ }
+ return service;
+ }
+ // The other threads will wait for the first thread to call notifyAll(),
+ // and go back to the top and retry.
+ synchronized (cache) {
+ while (gates[mCacheIndex] < ContextImpl.STATE_READY) {
+ try {
+ cache.wait();
+ } catch (InterruptedException e) {
+ Log.w(TAG, "getService() interrupted");
+ Thread.currentThread().interrupt();
+ return null;
+ }
}
}
- if (interrupted) {
- Thread.currentThread().interrupt();
- }
}
- // Now the first thread has initialized it.
- // It may still be null if ServiceNotFoundException was thrown, but that shouldn't
- // happen, so we'll just return null here in that case.
- synchronized (cache) {
- service = cache[mCacheIndex];
- }
- return (T) service;
}
public abstract T createService(ContextImpl ctx) throws ServiceNotFoundException;
diff --git a/core/java/android/app/admin/DevicePolicyManager.java b/core/java/android/app/admin/DevicePolicyManager.java
index f7fb02a..8f1b328 100644
--- a/core/java/android/app/admin/DevicePolicyManager.java
+++ b/core/java/android/app/admin/DevicePolicyManager.java
@@ -4218,6 +4218,15 @@
return null;
}
+ /**
+ * Returns {@code true} if the device supports attestation of device identifiers in addition
+ * to key attestation.
+ * @return {@code true} if Device ID attestation is supported.
+ */
+ public boolean isDeviceIdAttestationSupported() {
+ PackageManager pm = mContext.getPackageManager();
+ return pm.hasSystemFeature(PackageManager.FEATURE_DEVICE_ID_ATTESTATION);
+ }
/**
* Called by a device or profile owner, or delegated certificate installer, to associate
diff --git a/core/java/android/app/usage/TimeSparseArray.java b/core/java/android/app/usage/TimeSparseArray.java
index 9ef88e4..4ec0e9e 100644
--- a/core/java/android/app/usage/TimeSparseArray.java
+++ b/core/java/android/app/usage/TimeSparseArray.java
@@ -88,7 +88,7 @@
key++;
keyIndex++;
}
- if (key >= origKey + 10) {
+ if (key >= origKey + 100) {
Slog.w(TAG, "Value " + value + " supposed to be inserted at " + origKey
+ " displaced to " + key);
}
diff --git a/core/java/android/content/Intent.java b/core/java/android/content/Intent.java
index 000912c..efc9b6d 100644
--- a/core/java/android/content/Intent.java
+++ b/core/java/android/content/Intent.java
@@ -2282,6 +2282,28 @@
public static final String ACTION_MY_PACKAGE_SUSPENDED = "android.intent.action.MY_PACKAGE_SUSPENDED";
/**
+ * Activity Action: Started to show more details about why an application was suspended.
+ *
+ * <p>Apps holding {@link android.Manifest.permission#SUSPEND_APPS} must declare an activity
+ * handling this intent and protect it with
+ * {@link android.Manifest.permission#SEND_SHOW_SUSPENDED_APP_DETAILS}.
+ *
+ * <p>Includes an extra {@link #EXTRA_PACKAGE_NAME} which is the name of the suspended package.
+ *
+ * <p class="note">This is a protected intent that can only be sent
+ * by the system.
+ *
+ * @see PackageManager#isPackageSuspended()
+ * @see #ACTION_PACKAGES_SUSPENDED
+ *
+ * @hide
+ */
+ @SystemApi
+ @SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION)
+ public static final String ACTION_SHOW_SUSPENDED_APP_DETAILS =
+ "android.intent.action.SHOW_SUSPENDED_APP_DETAILS";
+
+ /**
* Broadcast Action: Sent to a package that has been unsuspended.
*
* <p class="note">This is a protected intent that can only be sent
diff --git a/core/java/android/content/pm/ApplicationInfo.java b/core/java/android/content/pm/ApplicationInfo.java
index e85058d..6748cdb 100644
--- a/core/java/android/content/pm/ApplicationInfo.java
+++ b/core/java/android/content/pm/ApplicationInfo.java
@@ -590,26 +590,33 @@
public static final int PRIVATE_FLAG_VIRTUAL_PRELOAD = 1 << 16;
/**
- * Value for {@linl #privateFlags}: whether this app is pre-installed on the
+ * Value for {@link #privateFlags}: whether this app is pre-installed on the
* OEM partition of the system image.
* @hide
*/
public static final int PRIVATE_FLAG_OEM = 1 << 17;
/**
- * Value for {@linl #privateFlags}: whether this app is pre-installed on the
+ * Value for {@link #privateFlags}: whether this app is pre-installed on the
* vendor partition of the system image.
* @hide
*/
public static final int PRIVATE_FLAG_VENDOR = 1 << 18;
/**
- * Value for {@linl #privateFlags}: whether this app is pre-installed on the
+ * Value for {@link #privateFlags}: whether this app is pre-installed on the
* product partition of the system image.
* @hide
*/
public static final int PRIVATE_FLAG_PRODUCT = 1 << 19;
+ /**
+ * Value for {@link #privateFlags}: whether this app is signed with the
+ * platform key.
+ * @hide
+ */
+ public static final int PRIVATE_FLAG_SIGNED_WITH_PLATFORM_KEY = 1 << 20;
+
/** @hide */
@IntDef(flag = true, prefix = { "PRIVATE_FLAG_" }, value = {
PRIVATE_FLAG_ACTIVITIES_RESIZE_MODE_RESIZEABLE,
@@ -629,6 +636,7 @@
PRIVATE_FLAG_PRIVILEGED,
PRIVATE_FLAG_PRODUCT,
PRIVATE_FLAG_REQUIRED_FOR_SYSTEM_USER,
+ PRIVATE_FLAG_SIGNED_WITH_PLATFORM_KEY,
PRIVATE_FLAG_STATIC_SHARED_LIBRARY,
PRIVATE_FLAG_VENDOR,
PRIVATE_FLAG_VIRTUAL_PRELOAD,
@@ -904,7 +912,17 @@
* The app's declared version code.
* @hide
*/
- public long versionCode;
+ public long longVersionCode;
+
+ /**
+ * An integer representation of the app's declared version code. This is being left in place as
+ * some apps were using reflection to access it before the move to long in
+ * {@link android.os.Build.VERSION_CODES#P}
+ * @deprecated Use {@link #longVersionCode} instead.
+ * @hide
+ */
+ @Deprecated
+ public int versionCode;
/**
* The user-visible SDK version (ex. 26) of the framework against which the application claims
@@ -1214,7 +1232,7 @@
pw.println(prefix + "enabled=" + enabled
+ " minSdkVersion=" + minSdkVersion
+ " targetSdkVersion=" + targetSdkVersion
- + " versionCode=" + versionCode
+ + " versionCode=" + longVersionCode
+ " targetSandboxVersion=" + targetSandboxVersion);
if ((dumpFlags & DUMP_FLAG_DETAILS) != 0) {
if (manageSpaceActivityName != null) {
@@ -1287,7 +1305,7 @@
proto.write(ApplicationInfoProto.Version.ENABLED, enabled);
proto.write(ApplicationInfoProto.Version.MIN_SDK_VERSION, minSdkVersion);
proto.write(ApplicationInfoProto.Version.TARGET_SDK_VERSION, targetSdkVersion);
- proto.write(ApplicationInfoProto.Version.VERSION_CODE, versionCode);
+ proto.write(ApplicationInfoProto.Version.VERSION_CODE, longVersionCode);
proto.write(ApplicationInfoProto.Version.TARGET_SANDBOX_VERSION, targetSandboxVersion);
proto.end(versionToken);
@@ -1421,7 +1439,7 @@
uid = orig.uid;
minSdkVersion = orig.minSdkVersion;
targetSdkVersion = orig.targetSdkVersion;
- versionCode = orig.versionCode;
+ setVersionCode(orig.longVersionCode);
enabled = orig.enabled;
enabledSetting = orig.enabledSetting;
installLocation = orig.installLocation;
@@ -1495,7 +1513,7 @@
dest.writeInt(uid);
dest.writeInt(minSdkVersion);
dest.writeInt(targetSdkVersion);
- dest.writeLong(versionCode);
+ dest.writeLong(longVersionCode);
dest.writeInt(enabled ? 1 : 0);
dest.writeInt(enabledSetting);
dest.writeInt(installLocation);
@@ -1566,7 +1584,7 @@
uid = source.readInt();
minSdkVersion = source.readInt();
targetSdkVersion = source.readInt();
- versionCode = source.readLong();
+ setVersionCode(source.readLong());
enabled = source.readInt() != 0;
enabledSetting = source.readInt();
installLocation = source.readInt();
@@ -1658,6 +1676,11 @@
return SystemConfig.getInstance().getHiddenApiWhitelistedApps().contains(packageName);
}
+ private boolean isAllowedToUseHiddenApis() {
+ return isSignedWithPlatformKey()
+ || (isPackageWhitelistedForHiddenApis() && (isSystemApp() || isUpdatedSystemApp()));
+ }
+
/**
* @hide
*/
@@ -1665,7 +1688,7 @@
if (mHiddenApiPolicy != HIDDEN_API_ENFORCEMENT_DEFAULT) {
return mHiddenApiPolicy;
}
- if (isPackageWhitelistedForHiddenApis() && (isSystemApp() || isUpdatedSystemApp())) {
+ if (isAllowedToUseHiddenApis()) {
return HIDDEN_API_ENFORCEMENT_NONE;
}
return HIDDEN_API_ENFORCEMENT_BLACK;
@@ -1684,6 +1707,14 @@
/**
* @hide
*/
+ public void setVersionCode(long newVersionCode) {
+ longVersionCode = newVersionCode;
+ versionCode = (int) newVersionCode;
+ }
+
+ /**
+ * @hide
+ */
@Override
public Drawable loadDefaultIcon(PackageManager pm) {
if ((flags & FLAG_EXTERNAL_STORAGE) != 0
@@ -1758,6 +1789,11 @@
}
/** @hide */
+ public boolean isSignedWithPlatformKey() {
+ return (privateFlags & ApplicationInfo.PRIVATE_FLAG_SIGNED_WITH_PLATFORM_KEY) != 0;
+ }
+
+ /** @hide */
@TestApi
public boolean isPrivilegedApp() {
return (privateFlags & ApplicationInfo.PRIVATE_FLAG_PRIVILEGED) != 0;
diff --git a/core/java/android/content/pm/IPackageManager.aidl b/core/java/android/content/pm/IPackageManager.aidl
index 277738b..02ce47b8 100644
--- a/core/java/android/content/pm/IPackageManager.aidl
+++ b/core/java/android/content/pm/IPackageManager.aidl
@@ -273,8 +273,8 @@
void clearCrossProfileIntentFilters(int sourceUserId, String ownerPackage);
String[] setPackagesSuspendedAsUser(in String[] packageNames, boolean suspended,
- in PersistableBundle launcherExtras, in PersistableBundle appExtras,
- String callingPackage, int userId);
+ in PersistableBundle appExtras, in PersistableBundle launcherExtras,
+ String dialogMessage, String callingPackage, int userId);
boolean isPackageSuspendedForUser(String packageName, int userId);
diff --git a/core/java/android/content/pm/PackageManager.java b/core/java/android/content/pm/PackageManager.java
index 491f0af..dd86d47 100644
--- a/core/java/android/content/pm/PackageManager.java
+++ b/core/java/android/content/pm/PackageManager.java
@@ -2629,6 +2629,17 @@
"android.hardware.strongbox_keystore";
/**
+ * Feature for {@link #getSystemAvailableFeatures} and {@link #hasSystemFeature}:
+ * The device has a Keymaster implementation that supports Device ID attestation.
+ *
+ * @see DevicePolicyManager#isDeviceIdAttestationSupported
+ * @hide
+ */
+ @SdkConstant(SdkConstantType.FEATURE)
+ public static final String FEATURE_DEVICE_ID_ATTESTATION =
+ "android.software.device_id_attestation";
+
+ /**
* Action to external storage service to clean out removed apps.
* @hide
*/
diff --git a/core/java/android/content/pm/PackageManagerInternal.java b/core/java/android/content/pm/PackageManagerInternal.java
index c9b78c0..a9d0911 100644
--- a/core/java/android/content/pm/PackageManagerInternal.java
+++ b/core/java/android/content/pm/PackageManagerInternal.java
@@ -191,10 +191,10 @@
/**
* Retrieve launcher extras for a suspended package provided to the system in
* {@link PackageManager#setPackagesSuspended(String[], boolean, PersistableBundle,
- * PersistableBundle, String)}
+ * PersistableBundle, String)}.
*
* @param packageName The package for which to return launcher extras.
- * @param userId The user for which to check,
+ * @param userId The user for which to check.
* @return The launcher extras.
*
* @see PackageManager#setPackagesSuspended(String[], boolean, PersistableBundle,
@@ -205,6 +205,38 @@
int userId);
/**
+ * Internal api to query the suspended state of a package.
+ * @param packageName The package to check.
+ * @param userId The user id to check for.
+ * @return {@code true} if the package is suspended, {@code false} otherwise.
+ * @see PackageManager#isPackageSuspended(String)
+ */
+ public abstract boolean isPackageSuspended(String packageName, int userId);
+
+ /**
+ * Get the name of the package that suspended the given package. Packages can be suspended by
+ * device administrators or apps holding {@link android.Manifest.permission#MANAGE_USERS} or
+ * {@link android.Manifest.permission#SUSPEND_APPS}.
+ *
+ * @param suspendedPackage The package that has been suspended.
+ * @param userId The user for which to check.
+ * @return Name of the package that suspended the given package. Returns {@code null} if the
+ * given package is not currently suspended and the platform package name - i.e.
+ * {@code "android"} - if the package was suspended by a device admin.
+ */
+ public abstract String getSuspendingPackage(String suspendedPackage, int userId);
+
+ /**
+ * Get the dialog message to be shown to the user when they try to launch a suspended
+ * application.
+ *
+ * @param suspendedPackage The package that has been suspended.
+ * @param userId The user for which to check.
+ * @return The dialog message to be shown to the user.
+ */
+ public abstract String getSuspendedDialogMessage(String suspendedPackage, int userId);
+
+ /**
* Do a straight uid lookup for the given package/application in the given user.
* @see PackageManager#getPackageUidAsUser(String, int, int)
* @return The app's uid, or < 0 if the package was not found in that user
@@ -429,7 +461,7 @@
* Resolves an activity intent, allowing instant apps to be resolved.
*/
public abstract ResolveInfo resolveIntent(Intent intent, String resolvedType,
- int flags, int userId, boolean resolveForStart);
+ int flags, int userId, boolean resolveForStart, int filterCallingUid);
/**
* Resolves a service intent, allowing instant apps to be resolved.
diff --git a/core/java/android/content/pm/PackageParser.java b/core/java/android/content/pm/PackageParser.java
index 2f0faf2..3e0db60 100644
--- a/core/java/android/content/pm/PackageParser.java
+++ b/core/java/android/content/pm/PackageParser.java
@@ -1918,7 +1918,7 @@
com.android.internal.R.styleable.AndroidManifest_versionCode, 0);
pkg.mVersionCodeMajor = sa.getInteger(
com.android.internal.R.styleable.AndroidManifest_versionCodeMajor, 0);
- pkg.applicationInfo.versionCode = pkg.getLongVersionCode();
+ pkg.applicationInfo.setVersionCode(pkg.getLongVersionCode());
pkg.baseRevisionCode = sa.getInteger(
com.android.internal.R.styleable.AndroidManifest_revisionCode, 0);
pkg.mVersionName = sa.getNonConfigurationString(
diff --git a/core/java/android/content/pm/PackageUserState.java b/core/java/android/content/pm/PackageUserState.java
index f7b6e09..f471a1d 100644
--- a/core/java/android/content/pm/PackageUserState.java
+++ b/core/java/android/content/pm/PackageUserState.java
@@ -34,6 +34,7 @@
import com.android.internal.util.ArrayUtils;
import java.util.Arrays;
+import java.util.Objects;
/**
* Per-user state information about a package.
@@ -47,6 +48,7 @@
public boolean hidden; // Is the app restricted by owner / admin
public boolean suspended;
public String suspendingPackage;
+ public String dialogMessage; // Message to show when a suspended package launch attempt is made
public PersistableBundle suspendedAppExtras;
public PersistableBundle suspendedLauncherExtras;
public boolean instantApp;
@@ -82,6 +84,7 @@
hidden = o.hidden;
suspended = o.suspended;
suspendingPackage = o.suspendingPackage;
+ dialogMessage = o.dialogMessage;
suspendedAppExtras = o.suspendedAppExtras;
suspendedLauncherExtras = o.suspendedLauncherExtras;
instantApp = o.instantApp;
@@ -208,6 +211,9 @@
|| !suspendingPackage.equals(oldState.suspendingPackage)) {
return false;
}
+ if (!Objects.equals(dialogMessage, oldState.dialogMessage)) {
+ return false;
+ }
if (!BaseBundle.kindofEquals(suspendedAppExtras,
oldState.suspendedAppExtras)) {
return false;
diff --git a/core/java/android/hardware/biometrics/BiometricDialog.java b/core/java/android/hardware/biometrics/BiometricPrompt.java
similarity index 93%
rename from core/java/android/hardware/biometrics/BiometricDialog.java
rename to core/java/android/hardware/biometrics/BiometricPrompt.java
index dd848a3..1c9de45 100644
--- a/core/java/android/hardware/biometrics/BiometricDialog.java
+++ b/core/java/android/hardware/biometrics/BiometricPrompt.java
@@ -38,7 +38,7 @@
/**
* A class that manages a system-provided biometric dialog.
*/
-public class BiometricDialog implements BiometricAuthenticator, BiometricConstants {
+public class BiometricPrompt implements BiometricAuthenticator, BiometricConstants {
/**
* @hide
@@ -190,11 +190,11 @@
}
/**
- * Creates a {@link BiometricDialog}.
- * @return a {@link BiometricDialog}
+ * Creates a {@link BiometricPrompt}.
+ * @return a {@link BiometricPrompt}
* @throws IllegalArgumentException if any of the required fields are not set.
*/
- public BiometricDialog build() {
+ public BiometricPrompt build() {
final CharSequence title = mBundle.getCharSequence(KEY_TITLE);
final CharSequence negative = mBundle.getCharSequence(KEY_NEGATIVE_TEXT);
@@ -203,7 +203,7 @@
} else if (TextUtils.isEmpty(negative)) {
throw new IllegalArgumentException("Negative text must be set and non-empty");
}
- return new BiometricDialog(mContext, mBundle, mPositiveButtonInfo, mNegativeButtonInfo);
+ return new BiometricPrompt(mContext, mBundle, mPositiveButtonInfo, mNegativeButtonInfo);
}
}
@@ -213,7 +213,7 @@
private ButtonInfo mPositiveButtonInfo;
private ButtonInfo mNegativeButtonInfo;
- IBiometricDialogReceiver mDialogReceiver = new IBiometricDialogReceiver.Stub() {
+ IBiometricPromptReceiver mDialogReceiver = new IBiometricPromptReceiver.Stub() {
@Override
public void onDialogDismissed(int reason) {
// Check the reason and invoke OnClickListener(s) if necessary
@@ -229,7 +229,7 @@
}
};
- private BiometricDialog(Context context, Bundle bundle,
+ private BiometricPrompt(Context context, Bundle bundle,
ButtonInfo positiveButtonInfo, ButtonInfo negativeButtonInfo) {
mBundle = bundle;
mPositiveButtonInfo = positiveButtonInfo;
@@ -239,7 +239,7 @@
}
/**
- * A wrapper class for the crypto objects supported by BiometricDialog. Currently the framework
+ * A wrapper class for the crypto objects supported by BiometricPrompt. Currently the framework
* supports {@link Signature}, {@link Cipher} and {@link Mac} objects.
*/
public static final class CryptoObject extends android.hardware.biometrics.CryptoObject {
@@ -308,8 +308,8 @@
}
/**
- * Callback structure provided to {@link BiometricDialog#authenticate(CancellationSignal,
- * Executor, AuthenticationCallback)} or {@link BiometricDialog#authenticate(CryptoObject,
+ * Callback structure provided to {@link BiometricPrompt#authenticate(CancellationSignal,
+ * Executor, AuthenticationCallback)} or {@link BiometricPrompt#authenticate(CryptoObject,
* CancellationSignal, Executor, AuthenticationCallback)}. Users must provide an implementation
* of this for listening to authentication events.
*/
@@ -378,7 +378,7 @@
@NonNull CancellationSignal cancel,
@NonNull @CallbackExecutor Executor executor,
@NonNull BiometricAuthenticator.AuthenticationCallback callback) {
- if (!(callback instanceof BiometricDialog.AuthenticationCallback)) {
+ if (!(callback instanceof BiometricPrompt.AuthenticationCallback)) {
throw new IllegalArgumentException("Callback cannot be casted");
}
authenticate(crypto, cancel, executor, (AuthenticationCallback) callback);
@@ -395,7 +395,7 @@
public void authenticate(@NonNull CancellationSignal cancel,
@NonNull @CallbackExecutor Executor executor,
@NonNull BiometricAuthenticator.AuthenticationCallback callback) {
- if (!(callback instanceof BiometricDialog.AuthenticationCallback)) {
+ if (!(callback instanceof BiometricPrompt.AuthenticationCallback)) {
throw new IllegalArgumentException("Callback cannot be casted");
}
authenticate(cancel, executor, (AuthenticationCallback) callback);
@@ -410,8 +410,8 @@
* operation can be canceled by using the provided cancel object. The application will receive
* authentication errors through {@link AuthenticationCallback}, and button events through the
* corresponding callback set in {@link Builder#setNegativeButton(CharSequence, Executor,
- * DialogInterface.OnClickListener)}. It is safe to reuse the {@link BiometricDialog} object,
- * and calling {@link BiometricDialog#authenticate( CancellationSignal, Executor,
+ * DialogInterface.OnClickListener)}. It is safe to reuse the {@link BiometricPrompt} object,
+ * and calling {@link BiometricPrompt#authenticate( CancellationSignal, Executor,
* AuthenticationCallback)} while an existing authentication attempt is occurring will stop the
* previous client and start a new authentication. The interrupted client will receive a
* cancelled notification through {@link AuthenticationCallback#onAuthenticationError(int,
@@ -445,8 +445,8 @@
* provided cancel object. The application will receive authentication errors through {@link
* AuthenticationCallback}, and button events through the corresponding callback set in {@link
* Builder#setNegativeButton(CharSequence, Executor, DialogInterface.OnClickListener)}. It is
- * safe to reuse the {@link BiometricDialog} object, and calling {@link
- * BiometricDialog#authenticate(CancellationSignal, Executor, AuthenticationCallback)} while
+ * safe to reuse the {@link BiometricPrompt} object, and calling {@link
+ * BiometricPrompt#authenticate(CancellationSignal, Executor, AuthenticationCallback)} while
* an existing authentication attempt is occurring will stop the previous client and start a new
* authentication. The interrupted client will receive a cancelled notification through {@link
* AuthenticationCallback#onAuthenticationError(int, CharSequence)}.
@@ -470,15 +470,15 @@
private boolean handlePreAuthenticationErrors(AuthenticationCallback callback,
Executor executor) {
if (!mPackageManager.hasSystemFeature(PackageManager.FEATURE_FINGERPRINT)) {
- sendError(BiometricDialog.BIOMETRIC_ERROR_HW_NOT_PRESENT, callback,
+ sendError(BiometricPrompt.BIOMETRIC_ERROR_HW_NOT_PRESENT, callback,
executor);
return true;
} else if (!mFingerprintManager.isHardwareDetected()) {
- sendError(BiometricDialog.BIOMETRIC_ERROR_HW_UNAVAILABLE, callback,
+ sendError(BiometricPrompt.BIOMETRIC_ERROR_HW_UNAVAILABLE, callback,
executor);
return true;
} else if (!mFingerprintManager.hasEnrolledFingerprints()) {
- sendError(BiometricDialog.BIOMETRIC_ERROR_NO_BIOMETRICS, callback,
+ sendError(BiometricPrompt.BIOMETRIC_ERROR_NO_BIOMETRICS, callback,
executor);
return true;
}
diff --git a/core/java/android/hardware/biometrics/IBiometricDialogReceiver.aidl b/core/java/android/hardware/biometrics/IBiometricPromptReceiver.aidl
similarity index 87%
rename from core/java/android/hardware/biometrics/IBiometricDialogReceiver.aidl
rename to core/java/android/hardware/biometrics/IBiometricPromptReceiver.aidl
index e528aa7..67c9346 100644
--- a/core/java/android/hardware/biometrics/IBiometricDialogReceiver.aidl
+++ b/core/java/android/hardware/biometrics/IBiometricPromptReceiver.aidl
@@ -19,9 +19,9 @@
import android.os.UserHandle;
/**
- * Communication channel from the BiometricDialog (SysUI) back to AuthenticationClient.
+ * Communication channel from the BiometricPrompt (SysUI) back to AuthenticationClient.
* @hide
*/
-oneway interface IBiometricDialogReceiver {
+oneway interface IBiometricPromptReceiver {
void onDialogDismissed(int reason);
}
diff --git a/core/java/android/hardware/fingerprint/FingerprintManager.java b/core/java/android/hardware/fingerprint/FingerprintManager.java
index a6c8c67..40d31bf 100644
--- a/core/java/android/hardware/fingerprint/FingerprintManager.java
+++ b/core/java/android/hardware/fingerprint/FingerprintManager.java
@@ -31,9 +31,9 @@
import android.content.Context;
import android.content.pm.PackageManager;
import android.hardware.biometrics.BiometricAuthenticator;
-import android.hardware.biometrics.BiometricDialog;
import android.hardware.biometrics.BiometricFingerprintConstants;
-import android.hardware.biometrics.IBiometricDialogReceiver;
+import android.hardware.biometrics.BiometricPrompt;
+import android.hardware.biometrics.IBiometricPromptReceiver;
import android.os.Binder;
import android.os.Bundle;
import android.os.CancellationSignal;
@@ -57,7 +57,7 @@
/**
* A class that coordinates access to the fingerprint hardware.
- * @deprecated See {@link BiometricDialog} which shows a system-provided dialog upon starting
+ * @deprecated See {@link BiometricPrompt} which shows a system-provided dialog upon starting
* authentication. In a world where devices may have different types of biometric authentication,
* it's much more realistic to have a system-provided authentication dialog since the method may
* vary by vendor/device.
@@ -111,7 +111,7 @@
/**
* A wrapper class for the crypto objects supported by FingerprintManager. Currently the
* framework supports {@link Signature}, {@link Cipher} and {@link Mac} objects.
- * @deprecated See {@link android.hardware.biometrics.BiometricDialog.CryptoObject}
+ * @deprecated See {@link android.hardware.biometrics.BiometricPrompt.CryptoObject}
*/
@Deprecated
public static final class CryptoObject extends android.hardware.biometrics.CryptoObject {
@@ -155,7 +155,7 @@
/**
* Container for callback data from {@link FingerprintManager#authenticate(CryptoObject,
* CancellationSignal, int, AuthenticationCallback, Handler)}.
- * @deprecated See {@link android.hardware.biometrics.BiometricDialog.AuthenticationResult}
+ * @deprecated See {@link android.hardware.biometrics.BiometricPrompt.AuthenticationResult}
*/
@Deprecated
public static class AuthenticationResult {
@@ -204,7 +204,7 @@
* FingerprintManager#authenticate(CryptoObject, CancellationSignal,
* int, AuthenticationCallback, Handler) } must provide an implementation of this for listening to
* fingerprint events.
- * @deprecated See {@link android.hardware.biometrics.BiometricDialog.AuthenticationCallback}
+ * @deprecated See {@link android.hardware.biometrics.BiometricPrompt.AuthenticationCallback}
*/
@Deprecated
public static abstract class AuthenticationCallback
@@ -378,10 +378,10 @@
* by <a href="{@docRoot}training/articles/keystore.html">Android Keystore
* facility</a>.
* @throws IllegalStateException if the crypto primitive is not initialized.
- * @deprecated See {@link BiometricDialog#authenticate(CancellationSignal, Executor,
- * BiometricDialog.AuthenticationCallback)} and {@link BiometricDialog#authenticate(
- * BiometricDialog.CryptoObject, CancellationSignal, Executor,
- * BiometricDialog.AuthenticationCallback)}
+ * @deprecated See {@link BiometricPrompt#authenticate(CancellationSignal, Executor,
+ * BiometricPrompt.AuthenticationCallback)} and {@link BiometricPrompt#authenticate(
+ * BiometricPrompt.CryptoObject, CancellationSignal, Executor,
+ * BiometricPrompt.AuthenticationCallback)}
*/
@Deprecated
@RequiresPermission(anyOf = {USE_BIOMETRIC, USE_FINGERPRINT})
@@ -444,7 +444,7 @@
/**
* Per-user version, see {@link FingerprintManager#authenticate(CryptoObject,
- * CancellationSignal, Bundle, Executor, IBiometricDialogReceiver, AuthenticationCallback)}
+ * CancellationSignal, Bundle, Executor, IBiometricPromptReceiver, AuthenticationCallback)}
* @param userId the user ID that the fingerprint hardware will authenticate for.
*/
private void authenticate(int userId,
@@ -452,7 +452,7 @@
@NonNull CancellationSignal cancel,
@NonNull Bundle bundle,
@NonNull @CallbackExecutor Executor executor,
- @NonNull IBiometricDialogReceiver receiver,
+ @NonNull IBiometricPromptReceiver receiver,
@NonNull BiometricAuthenticator.AuthenticationCallback callback) {
mCryptoObject = crypto;
if (cancel.isCanceled()) {
@@ -480,8 +480,8 @@
}
/**
- * Private method, see {@link BiometricDialog#authenticate(CancellationSignal, Executor,
- * BiometricDialog.AuthenticationCallback)}
+ * Private method, see {@link BiometricPrompt#authenticate(CancellationSignal, Executor,
+ * BiometricPrompt.AuthenticationCallback)}
* @param cancel
* @param executor
* @param callback
@@ -491,7 +491,7 @@
@NonNull CancellationSignal cancel,
@NonNull Bundle bundle,
@NonNull @CallbackExecutor Executor executor,
- @NonNull IBiometricDialogReceiver receiver,
+ @NonNull IBiometricPromptReceiver receiver,
@NonNull BiometricAuthenticator.AuthenticationCallback callback) {
if (cancel == null) {
throw new IllegalArgumentException("Must supply a cancellation signal");
@@ -512,8 +512,8 @@
}
/**
- * Private method, see {@link BiometricDialog#authenticate(BiometricDialog.CryptoObject,
- * CancellationSignal, Executor, BiometricDialog.AuthenticationCallback)}
+ * Private method, see {@link BiometricPrompt#authenticate(BiometricPrompt.CryptoObject,
+ * CancellationSignal, Executor, BiometricPrompt.AuthenticationCallback)}
* @param crypto
* @param cancel
* @param executor
@@ -524,7 +524,7 @@
@NonNull CancellationSignal cancel,
@NonNull Bundle bundle,
@NonNull @CallbackExecutor Executor executor,
- @NonNull IBiometricDialogReceiver receiver,
+ @NonNull IBiometricPromptReceiver receiver,
@NonNull BiometricAuthenticator.AuthenticationCallback callback) {
if (crypto == null) {
throw new IllegalArgumentException("Must supply a crypto object");
@@ -743,7 +743,7 @@
* Determine if there is at least one fingerprint enrolled.
*
* @return true if at least one fingerprint is enrolled, false otherwise
- * @deprecated See {@link BiometricDialog} and
+ * @deprecated See {@link BiometricPrompt} and
* {@link FingerprintManager#FINGERPRINT_ERROR_NO_FINGERPRINTS}
*/
@Deprecated
@@ -777,7 +777,7 @@
* Determine if fingerprint hardware is present and functional.
*
* @return true if hardware is present and functional, false otherwise.
- * @deprecated See {@link BiometricDialog} and
+ * @deprecated See {@link BiometricPrompt} and
* {@link FingerprintManager#FINGERPRINT_ERROR_HW_UNAVAILABLE}
*/
@Deprecated
@@ -1158,7 +1158,7 @@
@Override // binder call
public void onError(long deviceId, int error, int vendorCode) {
if (mExecutor != null) {
- // BiometricDialog case
+ // BiometricPrompt case
if (error == FingerprintManager.FINGERPRINT_ERROR_USER_CANCELED) {
// User tapped somewhere to cancel, the biometric dialog is already dismissed.
mExecutor.execute(() -> {
@@ -1172,7 +1172,7 @@
mExecutor.execute(() -> {
sendErrorResult(deviceId, error, vendorCode);
});
- }, BiometricDialog.HIDE_DIALOG_DELAY);
+ }, BiometricPrompt.HIDE_DIALOG_DELAY);
}
} else {
mHandler.obtainMessage(MSG_ERROR, error, vendorCode, deviceId).sendToTarget();
diff --git a/core/java/android/hardware/fingerprint/IFingerprintService.aidl b/core/java/android/hardware/fingerprint/IFingerprintService.aidl
index 78d01e5..8aa2183 100644
--- a/core/java/android/hardware/fingerprint/IFingerprintService.aidl
+++ b/core/java/android/hardware/fingerprint/IFingerprintService.aidl
@@ -16,7 +16,7 @@
package android.hardware.fingerprint;
import android.os.Bundle;
-import android.hardware.biometrics.IBiometricDialogReceiver;
+import android.hardware.biometrics.IBiometricPromptReceiver;
import android.hardware.fingerprint.IFingerprintClientActiveCallback;
import android.hardware.fingerprint.IFingerprintServiceReceiver;
import android.hardware.fingerprint.IFingerprintServiceLockoutResetCallback;
@@ -31,7 +31,7 @@
// Authenticate the given sessionId with a fingerprint
void authenticate(IBinder token, long sessionId, int userId,
IFingerprintServiceReceiver receiver, int flags, String opPackageName,
- in Bundle bundle, IBiometricDialogReceiver dialogReceiver);
+ in Bundle bundle, IBiometricPromptReceiver dialogReceiver);
// Cancel authentication for the given sessionId
void cancelAuthentication(IBinder token, String opPackageName);
diff --git a/core/java/android/net/IpSecManager.java b/core/java/android/net/IpSecManager.java
index e0654fd..ade6374 100644
--- a/core/java/android/net/IpSecManager.java
+++ b/core/java/android/net/IpSecManager.java
@@ -684,14 +684,15 @@
* tunneled traffic.
*
* @param address the local address for traffic inside the tunnel
+ * @param prefixLen length of the InetAddress prefix
* @hide
*/
@SystemApi
@RequiresPermission(android.Manifest.permission.MANAGE_IPSEC_TUNNELS)
- public void addAddress(@NonNull LinkAddress address) throws IOException {
+ public void addAddress(@NonNull InetAddress address, int prefixLen) throws IOException {
try {
mService.addAddressToTunnelInterface(
- mResourceId, address, mOpPackageName);
+ mResourceId, new LinkAddress(address, prefixLen), mOpPackageName);
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
@@ -703,14 +704,15 @@
* <p>Remove an address which was previously added to the IpSecTunnelInterface
*
* @param address to be removed
+ * @param prefixLen length of the InetAddress prefix
* @hide
*/
@SystemApi
@RequiresPermission(android.Manifest.permission.MANAGE_IPSEC_TUNNELS)
- public void removeAddress(@NonNull LinkAddress address) throws IOException {
+ public void removeAddress(@NonNull InetAddress address, int prefixLen) throws IOException {
try {
mService.removeAddressFromTunnelInterface(
- mResourceId, address, mOpPackageName);
+ mResourceId, new LinkAddress(address, prefixLen), mOpPackageName);
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
diff --git a/core/java/android/os/StrictMode.java b/core/java/android/os/StrictMode.java
index a93e25a..59380fd 100644
--- a/core/java/android/os/StrictMode.java
+++ b/core/java/android/os/StrictMode.java
@@ -39,6 +39,7 @@
import android.os.strictmode.IntentReceiverLeakedViolation;
import android.os.strictmode.LeakedClosableViolation;
import android.os.strictmode.NetworkViolation;
+import android.os.strictmode.NonSdkApiUsedViolation;
import android.os.strictmode.ResourceMismatchViolation;
import android.os.strictmode.ServiceConnectionLeakedViolation;
import android.os.strictmode.SqliteObjectLeakedViolation;
@@ -76,6 +77,7 @@
import java.util.concurrent.Executor;
import java.util.concurrent.RejectedExecutionException;
import java.util.concurrent.atomic.AtomicInteger;
+import java.util.function.Consumer;
/**
* StrictMode is a developer tool which detects things you might be doing by accident and brings
@@ -262,6 +264,9 @@
/** @hide */
@TestApi public static final int DETECT_VM_UNTAGGED_SOCKET = 0x80 << 24; // for VmPolicy
+ /** @hide */
+ @TestApi public static final int DETECT_VM_NON_SDK_API_USAGE = 0x40 << 24; // for VmPolicy
+
private static final int ALL_VM_DETECT_BITS =
DETECT_VM_CURSOR_LEAKS
| DETECT_VM_CLOSABLE_LEAKS
@@ -271,7 +276,9 @@
| DETECT_VM_FILE_URI_EXPOSURE
| DETECT_VM_CLEARTEXT_NETWORK
| DETECT_VM_CONTENT_URI_WITHOUT_PERMISSION
- | DETECT_VM_UNTAGGED_SOCKET;
+ | DETECT_VM_UNTAGGED_SOCKET
+ | DETECT_VM_NON_SDK_API_USAGE;
+
// Byte 3: Penalty
@@ -413,6 +420,13 @@
*/
private static final AtomicInteger sDropboxCallsInFlight = new AtomicInteger(0);
+ /**
+ * Callback supplied to dalvik / libcore to get informed of usages of java API that are not
+ * a part of the public SDK.
+ */
+ private static final Consumer<String> sNonSdkApiUsageConsumer =
+ message -> onVmPolicyViolation(new NonSdkApiUsedViolation(message));
+
private StrictMode() {}
/**
@@ -796,6 +810,23 @@
}
/**
+ * Detect reflective usage of APIs that are not part of the public Android SDK.
+ */
+ public Builder detectNonSdkApiUsage() {
+ return enable(DETECT_VM_NON_SDK_API_USAGE);
+ }
+
+ /**
+ * Permit reflective usage of APIs that are not part of the public Android SDK. Note
+ * that this <b>only</b> affects {@code StrictMode}, the underlying runtime may
+ * continue to restrict or warn on access to methods that are not part of the
+ * public SDK.
+ */
+ public Builder permitNonSdkApiUsage() {
+ return disable(DETECT_VM_NON_SDK_API_USAGE);
+ }
+
+ /**
* Detect everything that's potentially suspect.
*
* <p>In the Honeycomb release this includes leaks of SQLite cursors, Activities, and
@@ -826,6 +857,8 @@
detectContentUriWithoutPermission();
detectUntaggedSockets();
}
+
+ // TODO: Decide whether to detect non SDK API usage beyond a certain API level.
return this;
}
@@ -1848,6 +1881,13 @@
} else if (networkPolicy != NETWORK_POLICY_ACCEPT) {
Log.w(TAG, "Dropping requested network policy due to missing service!");
}
+
+
+ if ((sVmPolicy.mask & DETECT_VM_NON_SDK_API_USAGE) != 0) {
+ VMRuntime.setNonSdkApiUsageConsumer(sNonSdkApiUsageConsumer);
+ } else {
+ VMRuntime.setNonSdkApiUsageConsumer(null);
+ }
}
}
@@ -2576,6 +2616,8 @@
return DETECT_VM_CONTENT_URI_WITHOUT_PERMISSION;
} else if (mViolation instanceof UntaggedSocketViolation) {
return DETECT_VM_UNTAGGED_SOCKET;
+ } else if (mViolation instanceof NonSdkApiUsedViolation) {
+ return DETECT_VM_NON_SDK_API_USAGE;
}
throw new IllegalStateException("missing violation bit");
}
diff --git a/core/java/android/hardware/biometrics/IBiometricDialogReceiver.aidl b/core/java/android/os/strictmode/NonSdkApiUsedViolation.java
similarity index 68%
copy from core/java/android/hardware/biometrics/IBiometricDialogReceiver.aidl
copy to core/java/android/os/strictmode/NonSdkApiUsedViolation.java
index e528aa7..2f0cb50 100644
--- a/core/java/android/hardware/biometrics/IBiometricDialogReceiver.aidl
+++ b/core/java/android/os/strictmode/NonSdkApiUsedViolation.java
@@ -13,15 +13,16 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-package android.hardware.biometrics;
-import android.os.Bundle;
-import android.os.UserHandle;
+package android.os.strictmode;
/**
- * Communication channel from the BiometricDialog (SysUI) back to AuthenticationClient.
- * @hide
+ * Subclass of {@code Violation} that is used when a process accesses
+ * a non SDK API.
*/
-oneway interface IBiometricDialogReceiver {
- void onDialogDismissed(int reason);
+public final class NonSdkApiUsedViolation extends Violation {
+ /** @hide */
+ public NonSdkApiUsedViolation(String message) {
+ super(message);
+ }
}
diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java
index 98d8666..b2a2c60 100644
--- a/core/java/android/provider/Settings.java
+++ b/core/java/android/provider/Settings.java
@@ -3753,17 +3753,6 @@
new SettingsValidators.InclusiveIntegerRangeValidator(0, 3);
/**
- * User-selected RTT mode. When on, outgoing and incoming calls will be answered as RTT
- * calls when supported by the device and carrier. Boolean value.
- * 0 = OFF
- * 1 = ON
- */
- public static final String RTT_CALLING_MODE = "rtt_calling_mode";
-
- /** @hide */
- public static final Validator RTT_CALLING_MODE_VALIDATOR = BOOLEAN_VALIDATOR;
-
- /**
* Whether the sounds effects (key clicks, lid open ...) are enabled. The value is
* boolean (1 or 0).
*/
@@ -4088,7 +4077,6 @@
DTMF_TONE_WHEN_DIALING,
DTMF_TONE_TYPE_WHEN_DIALING,
HEARING_AID,
- RTT_CALLING_MODE,
TTY_MODE,
MASTER_MONO,
SOUND_EFFECTS_ENABLED,
@@ -4287,7 +4275,6 @@
VALIDATORS.put(DTMF_TONE_TYPE_WHEN_DIALING, DTMF_TONE_TYPE_WHEN_DIALING_VALIDATOR);
VALIDATORS.put(HEARING_AID, HEARING_AID_VALIDATOR);
VALIDATORS.put(TTY_MODE, TTY_MODE_VALIDATOR);
- VALIDATORS.put(RTT_CALLING_MODE, RTT_CALLING_MODE_VALIDATOR);
VALIDATORS.put(NOTIFICATION_LIGHT_PULSE, NOTIFICATION_LIGHT_PULSE_VALIDATOR);
VALIDATORS.put(POINTER_LOCATION, POINTER_LOCATION_VALIDATOR);
VALIDATORS.put(SHOW_TOUCHES, SHOW_TOUCHES_VALIDATOR);
@@ -6660,6 +6647,17 @@
private static final Validator TTY_MODE_ENABLED_VALIDATOR = BOOLEAN_VALIDATOR;
/**
+ * User-selected RTT mode. When on, outgoing and incoming calls will be answered as RTT
+ * calls when supported by the device and carrier. Boolean value.
+ * 0 = OFF
+ * 1 = ON
+ */
+ public static final String RTT_CALLING_MODE = "rtt_calling_mode";
+
+ private static final Validator RTT_CALLING_MODE_VALIDATOR = BOOLEAN_VALIDATOR;
+
+ /**
+ /**
* Controls whether settings backup is enabled.
* Type: int ( 0 = disabled, 1 = enabled )
* @hide
@@ -7885,6 +7883,7 @@
PREFERRED_TTY_MODE,
ENHANCED_VOICE_PRIVACY_ENABLED,
TTY_MODE_ENABLED,
+ RTT_CALLING_MODE,
INCALL_POWER_BUTTON_BEHAVIOR,
NIGHT_DISPLAY_CUSTOM_START_TIME,
NIGHT_DISPLAY_CUSTOM_END_TIME,
@@ -8014,6 +8013,7 @@
VALIDATORS.put(ENHANCED_VOICE_PRIVACY_ENABLED,
ENHANCED_VOICE_PRIVACY_ENABLED_VALIDATOR);
VALIDATORS.put(TTY_MODE_ENABLED, TTY_MODE_ENABLED_VALIDATOR);
+ VALIDATORS.put(RTT_CALLING_MODE, RTT_CALLING_MODE_VALIDATOR);
VALIDATORS.put(INCALL_POWER_BUTTON_BEHAVIOR, INCALL_POWER_BUTTON_BEHAVIOR_VALIDATOR);
VALIDATORS.put(NIGHT_DISPLAY_CUSTOM_START_TIME,
NIGHT_DISPLAY_CUSTOM_START_TIME_VALIDATOR);
@@ -12541,6 +12541,19 @@
*/
public static final String SWAP_ENABLED = "swap_enabled";
+ /**
+ * Blacklist of GNSS satellites.
+ *
+ * This is a list of integers separated by commas to represent pairs of (constellation,
+ * svid). Thus, the number of integers should be even.
+ *
+ * E.g.: "3,0,5,24" denotes (constellation=3, svid=0) and (constellation=5, svid=24) are
+ * blacklisted. Note that svid=0 denotes all svids in the
+ * constellation are blacklisted.
+ *
+ * @hide
+ */
+ public static final String GNSS_SATELLITE_BLACKLIST = "gnss_satellite_blacklist";
}
/**
diff --git a/core/java/android/security/ConfirmationCallback.java b/core/java/android/security/ConfirmationCallback.java
index 4670bce..fd027f0 100644
--- a/core/java/android/security/ConfirmationCallback.java
+++ b/core/java/android/security/ConfirmationCallback.java
@@ -33,22 +33,22 @@
*
* @param dataThatWasConfirmed the data that was confirmed, see above for the format.
*/
- public void onConfirmedByUser(@NonNull byte[] dataThatWasConfirmed) {}
+ public void onConfirmed(@NonNull byte[] dataThatWasConfirmed) {}
/**
* Called when the requested prompt was dismissed (not accepted) by the user.
*/
- public void onDismissedByUser() {}
+ public void onDismissed() {}
/**
* Called when the requested prompt was dismissed by the application.
*/
- public void onDismissedByApplication() {}
+ public void onCanceled() {}
/**
* Called when the requested prompt was dismissed because of a low-level error.
*
- * @param e an exception representing the error.
+ * @param e a throwable representing the error.
*/
- public void onError(Exception e) {}
+ public void onError(Throwable e) {}
}
diff --git a/core/java/android/security/ConfirmationDialog.java b/core/java/android/security/ConfirmationPrompt.java
similarity index 88%
rename from core/java/android/security/ConfirmationDialog.java
rename to core/java/android/security/ConfirmationPrompt.java
index 1697106..5330cff 100644
--- a/core/java/android/security/ConfirmationDialog.java
+++ b/core/java/android/security/ConfirmationPrompt.java
@@ -68,7 +68,7 @@
* {@link #presentPrompt presentPrompt()} method. The <i>Relying Party</i> stores the nonce locally
* since it'll use it in a later step.
* <li> If the user approves the prompt a <i>Confirmation Response</i> is returned in the
- * {@link ConfirmationCallback#onConfirmedByUser onConfirmedByUser(byte[])} callback as the
+ * {@link ConfirmationCallback#onConfirmed onConfirmed(byte[])} callback as the
* <code>dataThatWasConfirmed</code> parameter. This blob contains the text that was shown to the
* user, the <code>extraData</code> parameter, and possibly other data.
* <li> The application signs the <i>Confirmation Response</i> with the previously created key and
@@ -82,8 +82,8 @@
* last bullet, is to have the <i>Relying Party</i> generate <code>promptText</code> and store it
* along the nonce in the <code>extraData</code> blob.
*/
-public class ConfirmationDialog {
- private static final String TAG = "ConfirmationDialog";
+public class ConfirmationPrompt {
+ private static final String TAG = "ConfirmationPrompt";
private CharSequence mPromptText;
private byte[] mExtraData;
@@ -97,15 +97,15 @@
ConfirmationCallback callback) {
switch (responseCode) {
case KeyStore.CONFIRMATIONUI_OK:
- callback.onConfirmedByUser(dataThatWasConfirmed);
+ callback.onConfirmed(dataThatWasConfirmed);
break;
case KeyStore.CONFIRMATIONUI_CANCELED:
- callback.onDismissedByUser();
+ callback.onDismissed();
break;
case KeyStore.CONFIRMATIONUI_ABORTED:
- callback.onDismissedByApplication();
+ callback.onCanceled();
break;
case KeyStore.CONFIRMATIONUI_SYSTEM_ERROR:
@@ -145,21 +145,25 @@
};
/**
- * A builder that collects arguments, to be shown on the system-provided confirmation dialog.
+ * A builder that collects arguments, to be shown on the system-provided confirmation prompt.
*/
- public static class Builder {
+ public static final class Builder {
+ private Context mContext;
private CharSequence mPromptText;
private byte[] mExtraData;
/**
- * Creates a builder for the confirmation dialog.
+ * Creates a builder for the confirmation prompt.
+ *
+ * @param context the application context
*/
- public Builder() {
+ public Builder(Context context) {
+ mContext = context;
}
/**
- * Sets the prompt text for the dialog.
+ * Sets the prompt text for the prompt.
*
* @param promptText the text to present in the prompt.
* @return the builder.
@@ -170,7 +174,7 @@
}
/**
- * Sets the extra data for the dialog.
+ * Sets the extra data for the prompt.
*
* @param extraData data to include in the response data.
* @return the builder.
@@ -181,24 +185,23 @@
}
/**
- * Creates a {@link ConfirmationDialog} with the arguments supplied to this builder.
+ * Creates a {@link ConfirmationPrompt} with the arguments supplied to this builder.
*
- * @param context the application context
- * @return a {@link ConfirmationDialog}
+ * @return a {@link ConfirmationPrompt}
* @throws IllegalArgumentException if any of the required fields are not set.
*/
- public ConfirmationDialog build(Context context) {
+ public ConfirmationPrompt build() {
if (TextUtils.isEmpty(mPromptText)) {
throw new IllegalArgumentException("prompt text must be set and non-empty");
}
if (mExtraData == null) {
throw new IllegalArgumentException("extraData must be set");
}
- return new ConfirmationDialog(context, mPromptText, mExtraData);
+ return new ConfirmationPrompt(mContext, mPromptText, mExtraData);
}
}
- private ConfirmationDialog(Context context, CharSequence promptText, byte[] extraData) {
+ private ConfirmationPrompt(Context context, CharSequence promptText, byte[] extraData) {
mContext = context;
mPromptText = promptText;
mExtraData = extraData;
@@ -227,10 +230,10 @@
return uiOptionsAsFlags;
}
- private boolean isAccessibilityServiceRunning() {
+ private static boolean isAccessibilityServiceRunning(Context context) {
boolean serviceRunning = false;
try {
- ContentResolver contentResolver = mContext.getContentResolver();
+ ContentResolver contentResolver = context.getContentResolver();
int a11yEnabled = Settings.Secure.getInt(contentResolver,
Settings.Secure.ACCESSIBILITY_ENABLED);
if (a11yEnabled == 1) {
@@ -249,12 +252,12 @@
* When the prompt is no longer being presented, one of the methods in
* {@link ConfirmationCallback} is called on the supplied callback object.
*
- * Confirmation dialogs may not be available when accessibility services are running so this
+ * Confirmation prompts may not be available when accessibility services are running so this
* may fail with a {@link ConfirmationNotAvailableException} exception even if
* {@link #isSupported} returns {@code true}.
*
* @param executor the executor identifying the thread that will receive the callback.
- * @param callback the callback to use when the dialog is done showing.
+ * @param callback the callback to use when the prompt is done showing.
* @throws IllegalArgumentException if the prompt text is too long or malfomed.
* @throws ConfirmationAlreadyPresentingException if another prompt is being presented.
* @throws ConfirmationNotAvailableException if confirmation prompts are not supported.
@@ -265,7 +268,7 @@
if (mCallback != null) {
throw new ConfirmationAlreadyPresentingException();
}
- if (isAccessibilityServiceRunning()) {
+ if (isAccessibilityServiceRunning(mContext)) {
throw new ConfirmationNotAvailableException();
}
mCallback = callback;
@@ -301,7 +304,7 @@
* Cancels a prompt currently being displayed.
*
* On success, the
- * {@link ConfirmationCallback#onDismissedByApplication onDismissedByApplication()} method on
+ * {@link ConfirmationCallback#onCanceled onCanceled()} method on
* the supplied callback object will be called asynchronously.
*
* @throws IllegalStateException if no prompt is currently being presented.
@@ -324,9 +327,13 @@
/**
* Checks if the device supports confirmation prompts.
*
+ * @param context the application context.
* @return true if confirmation prompts are supported by the device.
*/
- public static boolean isSupported() {
+ public static boolean isSupported(Context context) {
+ if (isAccessibilityServiceRunning(context)) {
+ return false;
+ }
return KeyStore.getInstance().isConfirmationPromptSupported();
}
}
diff --git a/core/java/android/service/textclassifier/TextClassifierService.java b/core/java/android/service/textclassifier/TextClassifierService.java
index f1bb72c..b461c0d 100644
--- a/core/java/android/service/textclassifier/TextClassifierService.java
+++ b/core/java/android/service/textclassifier/TextClassifierService.java
@@ -17,6 +17,7 @@
package android.service.textclassifier;
import android.Manifest;
+import android.annotation.IntRange;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.SystemApi;
@@ -97,7 +98,8 @@
Preconditions.checkNotNull(request);
Preconditions.checkNotNull(callback);
TextClassifierService.this.onSuggestSelection(
- sessionId, request, mCancellationSignal,
+ request.getText(), request.getStartIndex(), request.getEndIndex(),
+ TextSelection.Options.from(sessionId, request), mCancellationSignal,
new Callback<TextSelection>() {
@Override
public void onSuccess(TextSelection result) {
@@ -130,7 +132,8 @@
Preconditions.checkNotNull(request);
Preconditions.checkNotNull(callback);
TextClassifierService.this.onClassifyText(
- sessionId, request, mCancellationSignal,
+ request.getText(), request.getStartIndex(), request.getEndIndex(),
+ TextClassification.Options.from(sessionId, request), mCancellationSignal,
new Callback<TextClassification>() {
@Override
public void onSuccess(TextClassification result) {
@@ -161,7 +164,8 @@
Preconditions.checkNotNull(request);
Preconditions.checkNotNull(callback);
TextClassifierService.this.onGenerateLinks(
- sessionId, request, mCancellationSignal,
+ request.getText(), TextLinks.Options.from(sessionId, request),
+ mCancellationSignal,
new Callback<TextLinks>() {
@Override
public void onSuccess(TextLinks result) {
@@ -234,6 +238,25 @@
@NonNull CancellationSignal cancellationSignal,
@NonNull Callback<TextSelection> callback);
+ // TODO: Remove once apps can build against the latest sdk.
+ /** @hide */
+ public void onSuggestSelection(
+ @NonNull CharSequence text,
+ @IntRange(from = 0) int selectionStartIndex,
+ @IntRange(from = 0) int selectionEndIndex,
+ @Nullable TextSelection.Options options,
+ @NonNull CancellationSignal cancellationSignal,
+ @NonNull Callback<TextSelection> callback) {
+ final TextClassificationSessionId sessionId = options.getSessionId();
+ final TextSelection.Request request = options.getRequest() != null
+ ? options.getRequest()
+ : new TextSelection.Request.Builder(
+ text, selectionStartIndex, selectionEndIndex)
+ .setDefaultLocales(options.getDefaultLocales())
+ .build();
+ onSuggestSelection(sessionId, request, cancellationSignal, callback);
+ }
+
/**
* Classifies the specified text and returns a {@link TextClassification} object that can be
* used to generate a widget for handling the classified text.
@@ -249,6 +272,26 @@
@NonNull CancellationSignal cancellationSignal,
@NonNull Callback<TextClassification> callback);
+ // TODO: Remove once apps can build against the latest sdk.
+ /** @hide */
+ public void onClassifyText(
+ @NonNull CharSequence text,
+ @IntRange(from = 0) int startIndex,
+ @IntRange(from = 0) int endIndex,
+ @Nullable TextClassification.Options options,
+ @NonNull CancellationSignal cancellationSignal,
+ @NonNull Callback<TextClassification> callback) {
+ final TextClassificationSessionId sessionId = options.getSessionId();
+ final TextClassification.Request request = options.getRequest() != null
+ ? options.getRequest()
+ : new TextClassification.Request.Builder(
+ text, startIndex, endIndex)
+ .setDefaultLocales(options.getDefaultLocales())
+ .setReferenceTime(options.getReferenceTime())
+ .build();
+ onClassifyText(sessionId, request, cancellationSignal, callback);
+ }
+
/**
* Generates and returns a {@link TextLinks} that may be applied to the text to annotate it with
* links information.
@@ -264,6 +307,23 @@
@NonNull CancellationSignal cancellationSignal,
@NonNull Callback<TextLinks> callback);
+ // TODO: Remove once apps can build against the latest sdk.
+ /** @hide */
+ public void onGenerateLinks(
+ @NonNull CharSequence text,
+ @Nullable TextLinks.Options options,
+ @NonNull CancellationSignal cancellationSignal,
+ @NonNull Callback<TextLinks> callback) {
+ final TextClassificationSessionId sessionId = options.getSessionId();
+ final TextLinks.Request request = options.getRequest() != null
+ ? options.getRequest()
+ : new TextLinks.Request.Builder(text)
+ .setDefaultLocales(options.getDefaultLocales())
+ .setEntityConfig(options.getEntityConfig())
+ .build();
+ onGenerateLinks(sessionId, request, cancellationSignal, callback);
+ }
+
/**
* Writes the selection event.
* This is called when a selection event occurs. e.g. user changed selection; or smart selection
@@ -283,17 +343,17 @@
* @param context the text classification context
* @param sessionId the session's Id
*/
- public abstract void onCreateTextClassificationSession(
+ public void onCreateTextClassificationSession(
@NonNull TextClassificationContext context,
- @NonNull TextClassificationSessionId sessionId);
+ @NonNull TextClassificationSessionId sessionId) {}
/**
* Destroys the text classification session identified by the specified sessionId.
*
* @param sessionId the id of the session to destroy
*/
- public abstract void onDestroyTextClassificationSession(
- @NonNull TextClassificationSessionId sessionId);
+ public void onDestroyTextClassificationSession(
+ @NonNull TextClassificationSessionId sessionId) {}
/**
* Returns a TextClassifier that runs in this service's process.
diff --git a/core/java/android/view/WindowManagerGlobal.java b/core/java/android/view/WindowManagerGlobal.java
index cca66d6..08c2d0b 100644
--- a/core/java/android/view/WindowManagerGlobal.java
+++ b/core/java/android/view/WindowManagerGlobal.java
@@ -610,6 +610,10 @@
ViewRootImpl root = mRoots.get(i);
// Client might remove the view by "stopped" event.
root.setWindowStopped(stopped);
+ // Recursively forward stopped state to View's attached
+ // to this Window rather than the root application token,
+ // e.g. PopupWindow's.
+ setStoppedState(root.mAttachInfo.mWindowToken, stopped);
}
}
}
diff --git a/core/java/android/view/autofill/AutofillPopupWindow.java b/core/java/android/view/autofill/AutofillPopupWindow.java
index 1da998d..9b49248 100644
--- a/core/java/android/view/autofill/AutofillPopupWindow.java
+++ b/core/java/android/view/autofill/AutofillPopupWindow.java
@@ -79,6 +79,12 @@
public AutofillPopupWindow(@NonNull IAutofillWindowPresenter presenter) {
mWindowPresenter = new WindowPresenter(presenter);
+ // Here is a bit of voodoo - we want to show the window as system
+ // controlled one so it covers app windows, but at the same time it has to be
+ // an application type (so it's contained inside the application area).
+ // Hence, we set it to the application type with the highest z-order, which currently
+ // is TYPE_APPLICATION_ABOVE_SUB_PANEL.
+ setWindowLayoutType(WindowManager.LayoutParams.TYPE_APPLICATION_ABOVE_SUB_PANEL);
setTouchModal(false);
setOutsideTouchable(true);
setInputMethodMode(INPUT_METHOD_NOT_NEEDED);
diff --git a/core/java/android/view/textclassifier/TextClassification.java b/core/java/android/view/textclassifier/TextClassification.java
index 37a5d9a..f80625f 100644
--- a/core/java/android/view/textclassifier/TextClassification.java
+++ b/core/java/android/view/textclassifier/TextClassification.java
@@ -721,4 +721,67 @@
mEntityConfidence = EntityConfidence.CREATOR.createFromParcel(in);
mId = in.readString();
}
+
+ // TODO: Remove once apps can build against the latest sdk.
+ /**
+ * Optional input parameters for generating TextClassification.
+ * @hide
+ */
+ public static final class Options {
+
+ @Nullable private final TextClassificationSessionId mSessionId;
+ @Nullable private final Request mRequest;
+ @Nullable private LocaleList mDefaultLocales;
+ @Nullable private ZonedDateTime mReferenceTime;
+
+ public Options() {
+ this(null, null);
+ }
+
+ private Options(
+ @Nullable TextClassificationSessionId sessionId, @Nullable Request request) {
+ mSessionId = sessionId;
+ mRequest = request;
+ }
+
+ /** Helper to create Options from a Request. */
+ public static Options from(TextClassificationSessionId sessionId, Request request) {
+ final Options options = new Options(sessionId, request);
+ options.setDefaultLocales(request.getDefaultLocales());
+ options.setReferenceTime(request.getReferenceTime());
+ return options;
+ }
+
+ /** @param defaultLocales ordered list of locale preferences. */
+ public Options setDefaultLocales(@Nullable LocaleList defaultLocales) {
+ mDefaultLocales = defaultLocales;
+ return this;
+ }
+
+ /** @param referenceTime refrence time used for interpreting relatives dates */
+ public Options setReferenceTime(@Nullable ZonedDateTime referenceTime) {
+ mReferenceTime = referenceTime;
+ return this;
+ }
+
+ @Nullable
+ public LocaleList getDefaultLocales() {
+ return mDefaultLocales;
+ }
+
+ @Nullable
+ public ZonedDateTime getReferenceTime() {
+ return mReferenceTime;
+ }
+
+ @Nullable
+ public Request getRequest() {
+ return mRequest;
+ }
+
+ @Nullable
+ public TextClassificationSessionId getSessionId() {
+ return mSessionId;
+ }
+ }
}
diff --git a/core/java/android/view/textclassifier/TextClassifier.java b/core/java/android/view/textclassifier/TextClassifier.java
index 54261be..f048d29 100644
--- a/core/java/android/view/textclassifier/TextClassifier.java
+++ b/core/java/android/view/textclassifier/TextClassifier.java
@@ -41,8 +41,9 @@
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
-import java.util.List;
+import java.util.HashSet;
import java.util.Map;
+import java.util.Set;
/**
* Interface for providing text classification related features.
@@ -208,6 +209,26 @@
return suggestSelection(request);
}
+ // TODO: Remove once apps can build against the latest sdk.
+ /** @hide */
+ default TextSelection suggestSelection(
+ @NonNull CharSequence text,
+ @IntRange(from = 0) int selectionStartIndex,
+ @IntRange(from = 0) int selectionEndIndex,
+ @Nullable TextSelection.Options options) {
+ if (options == null) {
+ return suggestSelection(new TextSelection.Request.Builder(
+ text, selectionStartIndex, selectionEndIndex).build());
+ } else if (options.getRequest() != null) {
+ return suggestSelection(options.getRequest());
+ } else {
+ return suggestSelection(
+ new TextSelection.Request.Builder(text, selectionStartIndex, selectionEndIndex)
+ .setDefaultLocales(options.getDefaultLocales())
+ .build());
+ }
+ }
+
/**
* Classifies the specified text and returns a {@link TextClassification} object that can be
* used to generate a widget for handling the classified text.
@@ -267,6 +288,26 @@
return classifyText(request);
}
+ // TODO: Remove once apps can build against the latest sdk.
+ /** @hide */
+ default TextClassification classifyText(
+ @NonNull CharSequence text,
+ @IntRange(from = 0) int startIndex,
+ @IntRange(from = 0) int endIndex,
+ @Nullable TextClassification.Options options) {
+ if (options == null) {
+ return classifyText(
+ new TextClassification.Request.Builder(text, startIndex, endIndex).build());
+ } else if (options.getRequest() != null) {
+ return classifyText(options.getRequest());
+ } else {
+ return classifyText(new TextClassification.Request.Builder(text, startIndex, endIndex)
+ .setDefaultLocales(options.getDefaultLocales())
+ .setReferenceTime(options.getReferenceTime())
+ .build());
+ }
+ }
+
/**
* Generates and returns a {@link TextLinks} that may be applied to the text to annotate it with
* links information.
@@ -288,6 +329,22 @@
return new TextLinks.Builder(request.getText().toString()).build();
}
+ // TODO: Remove once apps can build against the latest sdk.
+ /** @hide */
+ default TextLinks generateLinks(
+ @NonNull CharSequence text, @Nullable TextLinks.Options options) {
+ if (options == null) {
+ return generateLinks(new TextLinks.Request.Builder(text).build());
+ } else if (options.getRequest() != null) {
+ return generateLinks(options.getRequest());
+ } else {
+ return generateLinks(new TextLinks.Request.Builder(text)
+ .setDefaultLocales(options.getDefaultLocales())
+ .setEntityConfig(options.getEntityConfig())
+ .build());
+ }
+ }
+
/**
* Returns the maximal length of text that can be processed by generateLinks.
*
@@ -377,6 +434,12 @@
/* includedEntityTypes */null, /* excludedEntityTypes */ null);
}
+ // TODO: Remove once apps can build against the latest sdk.
+ /** @hide */
+ public static EntityConfig create(@Nullable Collection<String> hints) {
+ return createWithHints(hints);
+ }
+
/**
* Creates an EntityConfig.
*
@@ -406,6 +469,12 @@
/* includedEntityTypes */ entityTypes, /* excludedEntityTypes */ null);
}
+ // TODO: Remove once apps can build against the latest sdk.
+ /** @hide */
+ public static EntityConfig createWithEntityList(@Nullable Collection<String> entityTypes) {
+ return createWithExplicitEntityList(entityTypes);
+ }
+
/**
* Returns a list of the final set of entities to find.
*
@@ -413,21 +482,15 @@
*
* This method is intended for use by TextClassifier implementations.
*/
- public List<String> resolveEntityListModifications(@NonNull Collection<String> entities) {
- final ArrayList<String> finalList = new ArrayList<>();
+ public Collection<String> resolveEntityListModifications(
+ @NonNull Collection<String> entities) {
+ final Set<String> finalSet = new HashSet();
if (mUseHints) {
- for (String entity : entities) {
- if (!mExcludedEntityTypes.contains(entity)) {
- finalList.add(entity);
- }
- }
+ finalSet.addAll(entities);
}
- for (String entity : mIncludedEntityTypes) {
- if (!mExcludedEntityTypes.contains(entity) && !finalList.contains(entity)) {
- finalList.add(entity);
- }
- }
- return finalList;
+ finalSet.addAll(mIncludedEntityTypes);
+ finalSet.removeAll(mExcludedEntityTypes);
+ return finalSet;
}
/**
@@ -508,7 +571,7 @@
final String string = request.getText().toString();
final TextLinks.Builder links = new TextLinks.Builder(string);
- final List<String> entities = request.getEntityConfig()
+ final Collection<String> entities = request.getEntityConfig()
.resolveEntityListModifications(Collections.emptyList());
if (entities.contains(TextClassifier.TYPE_URL)) {
addLinks(links, string, TextClassifier.TYPE_URL);
diff --git a/core/java/android/view/textclassifier/TextLinks.java b/core/java/android/view/textclassifier/TextLinks.java
index 17c7b13..3d503e2 100644
--- a/core/java/android/view/textclassifier/TextLinks.java
+++ b/core/java/android/view/textclassifier/TextLinks.java
@@ -28,6 +28,8 @@
import android.text.method.MovementMethod;
import android.text.style.ClickableSpan;
import android.text.style.URLSpan;
+import android.text.util.Linkify;
+import android.text.util.Linkify.LinkifyMask;
import android.view.View;
import android.view.textclassifier.TextClassifier.EntityType;
import android.widget.TextView;
@@ -607,4 +609,124 @@
return new TextLinks(mFullText, mLinks);
}
}
+
+ // TODO: Remove once apps can build against the latest sdk.
+ /**
+ * Optional input parameters for generating TextLinks.
+ * @hide
+ */
+ public static final class Options {
+
+ @Nullable private final TextClassificationSessionId mSessionId;
+ @Nullable private final Request mRequest;
+ @Nullable private LocaleList mDefaultLocales;
+ @Nullable private TextClassifier.EntityConfig mEntityConfig;
+ private boolean mLegacyFallback;
+
+ private @ApplyStrategy int mApplyStrategy;
+ private Function<TextLink, TextLinkSpan> mSpanFactory;
+
+ private String mCallingPackageName;
+
+ public Options() {
+ this(null, null);
+ }
+
+ private Options(
+ @Nullable TextClassificationSessionId sessionId, @Nullable Request request) {
+ mSessionId = sessionId;
+ mRequest = request;
+ }
+
+ /** Helper to create Options from a Request. */
+ public static Options from(TextClassificationSessionId sessionId, Request request) {
+ final Options options = new Options(sessionId, request);
+ options.setDefaultLocales(request.getDefaultLocales());
+ options.setEntityConfig(request.getEntityConfig());
+ return options;
+ }
+
+ /** Returns a new options object based on the specified link mask. */
+ public static Options fromLinkMask(@LinkifyMask int mask) {
+ final List<String> entitiesToFind = new ArrayList<>();
+
+ if ((mask & Linkify.WEB_URLS) != 0) {
+ entitiesToFind.add(TextClassifier.TYPE_URL);
+ }
+ if ((mask & Linkify.EMAIL_ADDRESSES) != 0) {
+ entitiesToFind.add(TextClassifier.TYPE_EMAIL);
+ }
+ if ((mask & Linkify.PHONE_NUMBERS) != 0) {
+ entitiesToFind.add(TextClassifier.TYPE_PHONE);
+ }
+ if ((mask & Linkify.MAP_ADDRESSES) != 0) {
+ entitiesToFind.add(TextClassifier.TYPE_ADDRESS);
+ }
+
+ return new Options().setEntityConfig(
+ TextClassifier.EntityConfig.createWithEntityList(entitiesToFind));
+ }
+
+ /** @param defaultLocales ordered list of locale preferences. */
+ public Options setDefaultLocales(@Nullable LocaleList defaultLocales) {
+ mDefaultLocales = defaultLocales;
+ return this;
+ }
+
+ /** @param entityConfig definition of which entity types to look for. */
+ public Options setEntityConfig(@Nullable TextClassifier.EntityConfig entityConfig) {
+ mEntityConfig = entityConfig;
+ return this;
+ }
+
+ /** @param applyStrategy strategy to use when resolving conflicts. */
+ public Options setApplyStrategy(@ApplyStrategy int applyStrategy) {
+ checkValidApplyStrategy(applyStrategy);
+ mApplyStrategy = applyStrategy;
+ return this;
+ }
+
+ /** @param spanFactory factory for converting TextLink to TextLinkSpan. */
+ public Options setSpanFactory(@Nullable Function<TextLink, TextLinkSpan> spanFactory) {
+ mSpanFactory = spanFactory;
+ return this;
+ }
+
+ @Nullable
+ public LocaleList getDefaultLocales() {
+ return mDefaultLocales;
+ }
+
+ @Nullable
+ public TextClassifier.EntityConfig getEntityConfig() {
+ return mEntityConfig;
+ }
+
+ @ApplyStrategy
+ public int getApplyStrategy() {
+ return mApplyStrategy;
+ }
+
+ @Nullable
+ public Function<TextLink, TextLinkSpan> getSpanFactory() {
+ return mSpanFactory;
+ }
+
+ @Nullable
+ public Request getRequest() {
+ return mRequest;
+ }
+
+ @Nullable
+ public TextClassificationSessionId getSessionId() {
+ return mSessionId;
+ }
+
+ private static void checkValidApplyStrategy(int applyStrategy) {
+ if (applyStrategy != APPLY_STRATEGY_IGNORE && applyStrategy != APPLY_STRATEGY_REPLACE) {
+ throw new IllegalArgumentException(
+ "Invalid apply strategy. See TextLinks.ApplyStrategy for options.");
+ }
+ }
+ }
}
diff --git a/core/java/android/view/textclassifier/TextSelection.java b/core/java/android/view/textclassifier/TextSelection.java
index 939e717..17687c9 100644
--- a/core/java/android/view/textclassifier/TextSelection.java
+++ b/core/java/android/view/textclassifier/TextSelection.java
@@ -375,4 +375,56 @@
mEntityConfidence = EntityConfidence.CREATOR.createFromParcel(in);
mId = in.readString();
}
+
+
+ // TODO: Remove once apps can build against the latest sdk.
+ /**
+ * Optional input parameters for generating TextSelection.
+ * @hide
+ */
+ public static final class Options {
+
+ @Nullable private final TextClassificationSessionId mSessionId;
+ @Nullable private final Request mRequest;
+ @Nullable private LocaleList mDefaultLocales;
+ private boolean mDarkLaunchAllowed;
+
+ public Options() {
+ this(null, null);
+ }
+
+ private Options(
+ @Nullable TextClassificationSessionId sessionId, @Nullable Request request) {
+ mSessionId = sessionId;
+ mRequest = request;
+ }
+
+ /** Helper to create Options from a Request. */
+ public static Options from(TextClassificationSessionId sessionId, Request request) {
+ final Options options = new Options(sessionId, request);
+ options.setDefaultLocales(request.getDefaultLocales());
+ return options;
+ }
+
+ /** @param defaultLocales ordered list of locale preferences. */
+ public Options setDefaultLocales(@Nullable LocaleList defaultLocales) {
+ mDefaultLocales = defaultLocales;
+ return this;
+ }
+
+ @Nullable
+ public LocaleList getDefaultLocales() {
+ return mDefaultLocales;
+ }
+
+ @Nullable
+ public Request getRequest() {
+ return mRequest;
+ }
+
+ @Nullable
+ public TextClassificationSessionId getSessionId() {
+ return mSessionId;
+ }
+ }
}
diff --git a/core/java/com/android/internal/app/SuspendedAppActivity.java b/core/java/com/android/internal/app/SuspendedAppActivity.java
new file mode 100644
index 0000000..322c876
--- /dev/null
+++ b/core/java/com/android/internal/app/SuspendedAppActivity.java
@@ -0,0 +1,82 @@
+/*
+ * 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.internal.app;
+
+import android.app.AlertDialog;
+import android.content.DialogInterface;
+import android.content.Intent;
+import android.os.Bundle;
+import android.os.UserHandle;
+import android.util.Slog;
+import android.view.Window;
+import android.view.WindowManager;
+
+import com.android.internal.R;
+
+public class SuspendedAppActivity extends AlertActivity
+ implements DialogInterface.OnClickListener {
+ private static final String TAG = "SuspendedAppActivity";
+
+ public static final String EXTRA_DIALOG_MESSAGE = "SuspendedAppActivity.extra.DIALOG_MESSAGE";
+ public static final String EXTRA_MORE_DETAILS_INTENT =
+ "SuspendedAppActivity.extra.MORE_DETAILS_INTENT";
+
+ private Intent mMoreDetailsIntent;
+ private int mUserId;
+
+ @Override
+ public void onCreate(Bundle icicle) {
+ Window window = getWindow();
+ window.setType(WindowManager.LayoutParams.TYPE_SYSTEM_DIALOG);
+ super.onCreate(icicle);
+
+ final Intent intent = getIntent();
+ mMoreDetailsIntent = intent.getParcelableExtra(EXTRA_MORE_DETAILS_INTENT);
+ mUserId = intent.getIntExtra(Intent.EXTRA_USER_ID, -1);
+ if (mUserId < 0) {
+ Slog.wtf(TAG, "Invalid user: " + mUserId);
+ finish();
+ return;
+ }
+ String dialogMessage = intent.getStringExtra(EXTRA_DIALOG_MESSAGE);
+ if (dialogMessage == null) {
+ dialogMessage = getString(R.string.app_suspended_default_message);
+ }
+
+ final AlertController.AlertParams ap = mAlertParams;
+ ap.mTitle = getString(R.string.app_suspended_title);
+ ap.mMessage = String.format(getResources().getConfiguration().getLocales().get(0),
+ dialogMessage, intent.getStringExtra(Intent.EXTRA_PACKAGE_NAME));
+ ap.mPositiveButtonText = getString(android.R.string.ok);
+ if (mMoreDetailsIntent != null) {
+ ap.mNeutralButtonText = getString(R.string.app_suspended_more_details);
+ }
+ ap.mPositiveButtonListener = ap.mNeutralButtonListener = this;
+ setupAlert();
+ }
+
+ @Override
+ public void onClick(DialogInterface dialog, int which) {
+ switch (which) {
+ case AlertDialog.BUTTON_NEUTRAL:
+ startActivityAsUser(mMoreDetailsIntent, UserHandle.of(mUserId));
+ Slog.i(TAG, "Started more details activity");
+ break;
+ }
+ finish();
+ }
+}
diff --git a/core/java/com/android/internal/statusbar/IStatusBar.aidl b/core/java/com/android/internal/statusbar/IStatusBar.aidl
index ad5743d..2790324 100644
--- a/core/java/com/android/internal/statusbar/IStatusBar.aidl
+++ b/core/java/com/android/internal/statusbar/IStatusBar.aidl
@@ -18,7 +18,7 @@
import android.content.ComponentName;
import android.graphics.Rect;
-import android.hardware.biometrics.IBiometricDialogReceiver;
+import android.hardware.biometrics.IBiometricPromptReceiver;
import android.os.Bundle;
import android.service.notification.StatusBarNotification;
@@ -141,7 +141,7 @@
void showShutdownUi(boolean isReboot, String reason);
// Used to show the dialog when FingerprintService starts authentication
- void showFingerprintDialog(in Bundle bundle, IBiometricDialogReceiver receiver);
+ void showFingerprintDialog(in Bundle bundle, IBiometricPromptReceiver receiver);
// Used to hide the dialog when a finger is authenticated
void onFingerprintAuthenticated();
// Used to set a temporary message, e.g. fingerprint not recognized, finger moved too fast, etc
diff --git a/core/java/com/android/internal/statusbar/IStatusBarService.aidl b/core/java/com/android/internal/statusbar/IStatusBarService.aidl
index 0c5efe2..24f2fbf 100644
--- a/core/java/com/android/internal/statusbar/IStatusBarService.aidl
+++ b/core/java/com/android/internal/statusbar/IStatusBarService.aidl
@@ -20,7 +20,7 @@
import android.graphics.Rect;
import android.os.Bundle;
import android.service.notification.StatusBarNotification;
-import android.hardware.biometrics.IBiometricDialogReceiver;
+import android.hardware.biometrics.IBiometricPromptReceiver;
import com.android.internal.statusbar.IStatusBar;
import com.android.internal.statusbar.StatusBarIcon;
@@ -88,7 +88,7 @@
void showPinningEscapeToast();
// Used to show the dialog when FingerprintService starts authentication
- void showFingerprintDialog(in Bundle bundle, IBiometricDialogReceiver receiver);
+ void showFingerprintDialog(in Bundle bundle, IBiometricPromptReceiver receiver);
// Used to hide the dialog when a finger is authenticated
void onFingerprintAuthenticated();
// Used to set a temporary message, e.g. fingerprint not recognized, finger moved too fast, etc
diff --git a/core/java/com/android/internal/widget/MessagingGroup.java b/core/java/com/android/internal/widget/MessagingGroup.java
index 239beaa..f73b607 100644
--- a/core/java/com/android/internal/widget/MessagingGroup.java
+++ b/core/java/com/android/internal/widget/MessagingGroup.java
@@ -64,7 +64,7 @@
private boolean mIsHidingAnimated;
private boolean mNeedsGeneratedAvatar;
private Notification.Person mSender;
- private boolean mAvatarsAtEnd;
+ private boolean mImagesAtEnd;
private ViewGroup mImageContainer;
private MessagingImageMessage mIsolatedMessage;
private boolean mTransformingImages;
@@ -342,7 +342,7 @@
mAddedMessages.add(message);
}
boolean isImage = message instanceof MessagingImageMessage;
- if (mAvatarsAtEnd && isImage) {
+ if (mImagesAtEnd && isImage) {
isolatedMessage = (MessagingImageMessage) message;
} else {
if (removeFromParentIfDifferent(message, mMessageContainer)) {
@@ -474,9 +474,9 @@
mTransformingImages = transformingImages;
}
- public void setDisplayAvatarsAtEnd(boolean atEnd) {
- if (mAvatarsAtEnd != atEnd) {
- mAvatarsAtEnd = atEnd;
+ public void setDisplayImagesAtEnd(boolean atEnd) {
+ if (mImagesAtEnd != atEnd) {
+ mImagesAtEnd = atEnd;
mImageContainer.setVisibility(atEnd ? View.VISIBLE : View.GONE);
}
}
diff --git a/core/java/com/android/internal/widget/MessagingLayout.java b/core/java/com/android/internal/widget/MessagingLayout.java
index 5279636..292df60 100644
--- a/core/java/com/android/internal/widget/MessagingLayout.java
+++ b/core/java/com/android/internal/widget/MessagingLayout.java
@@ -81,7 +81,7 @@
private ArrayList<MessagingGroup> mAddedGroups = new ArrayList<>();
private Notification.Person mUser;
private CharSequence mNameReplacement;
- private boolean mIsCollapsed;
+ private boolean mDisplayImagesAtEnd;
public MessagingLayout(@NonNull Context context) {
super(context);
@@ -128,8 +128,8 @@
}
@RemotableViewMethod
- public void setIsCollapsed(boolean isCollapsed) {
- mIsCollapsed = isCollapsed;
+ public void setDisplayImagesAtEnd(boolean atEnd) {
+ mDisplayImagesAtEnd = atEnd;
}
@RemotableViewMethod
@@ -337,7 +337,7 @@
newGroup = MessagingGroup.createGroup(mMessagingLinearLayout);
mAddedGroups.add(newGroup);
}
- newGroup.setDisplayAvatarsAtEnd(mIsCollapsed);
+ newGroup.setDisplayImagesAtEnd(mDisplayImagesAtEnd);
newGroup.setLayoutColor(mLayoutColor);
Notification.Person sender = senders.get(groupIndex);
CharSequence nameOverride = null;
diff --git a/core/java/com/android/internal/widget/MessagingMessage.java b/core/java/com/android/internal/widget/MessagingMessage.java
index bf1c5ca..a2cc7cf 100644
--- a/core/java/com/android/internal/widget/MessagingMessage.java
+++ b/core/java/com/android/internal/widget/MessagingMessage.java
@@ -16,6 +16,7 @@
package com.android.internal.widget;
+import android.app.ActivityManager;
import android.app.Notification;
import android.view.View;
@@ -33,7 +34,7 @@
static MessagingMessage createMessage(MessagingLayout layout,
Notification.MessagingStyle.Message m) {
- if (hasImage(m)) {
+ if (hasImage(m) && !ActivityManager.isLowRamDeviceStatic()) {
return MessagingImageMessage.createMessage(layout, m);
} else {
return MessagingTextMessage.createMessage(layout, m);
diff --git a/core/jni/android/graphics/ImageDecoder.cpp b/core/jni/android/graphics/ImageDecoder.cpp
index 825b7a0..3ea6049 100644
--- a/core/jni/android/graphics/ImageDecoder.cpp
+++ b/core/jni/android/graphics/ImageDecoder.cpp
@@ -116,9 +116,10 @@
const auto& info = decoder->mCodec->getInfo();
const int width = info.width();
const int height = info.height();
+ const bool isNinePatch = decoder->mPeeker->mPatch != nullptr;
return env->NewObject(gImageDecoder_class, gImageDecoder_constructorMethodID,
reinterpret_cast<jlong>(decoder.release()), width, height,
- animated);
+ animated, isNinePatch);
}
static jobject ImageDecoder_nCreateFd(JNIEnv* env, jobject /*clazz*/,
@@ -332,13 +333,6 @@
}
}
- float scaleX = 1.0f;
- float scaleY = 1.0f;
- if (scale) {
- scaleX = (float) desiredWidth / decodeInfo.width();
- scaleY = (float) desiredHeight / decodeInfo.height();
- }
-
jbyteArray ninePatchChunk = nullptr;
jobject ninePatchInsets = nullptr;
@@ -346,9 +340,6 @@
if (!jpostProcess) {
// FIXME: Share more code with BitmapFactory.cpp.
if (decoder->mPeeker->mPatch != nullptr) {
- if (scale) {
- decoder->mPeeker->scale(scaleX, scaleY, desiredWidth, desiredHeight);
- }
size_t ninePatchArraySize = decoder->mPeeker->mPatch->serializedSize();
ninePatchChunk = env->NewByteArray(ninePatchArraySize);
if (ninePatchChunk == nullptr) {
@@ -408,7 +399,12 @@
SkCanvas canvas(scaledBm, SkCanvas::ColorBehavior::kLegacy);
canvas.translate(translateX, translateY);
- canvas.scale(scaleX, scaleY);
+ if (scale) {
+ float scaleX = (float) desiredWidth / decodeInfo.width();
+ float scaleY = (float) desiredHeight / decodeInfo.height();
+ canvas.scale(scaleX, scaleY);
+ }
+
canvas.drawBitmap(bm, 0.0f, 0.0f, &paint);
bm.swap(scaledBm);
@@ -532,7 +528,7 @@
int register_android_graphics_ImageDecoder(JNIEnv* env) {
gImageDecoder_class = MakeGlobalRefOrDie(env, FindClassOrDie(env, "android/graphics/ImageDecoder"));
- gImageDecoder_constructorMethodID = GetMethodIDOrDie(env, gImageDecoder_class, "<init>", "(JIIZ)V");
+ gImageDecoder_constructorMethodID = GetMethodIDOrDie(env, gImageDecoder_class, "<init>", "(JIIZZ)V");
gImageDecoder_postProcessMethodID = GetMethodIDOrDie(env, gImageDecoder_class, "postProcessAndRelease", "(Landroid/graphics/Canvas;)I");
gSize_class = MakeGlobalRefOrDie(env, FindClassOrDie(env, "android/util/Size"));
diff --git a/core/proto/android/os/incident.proto b/core/proto/android/os/incident.proto
index 6467976..2a7c256 100644
--- a/core/proto/android/os/incident.proto
+++ b/core/proto/android/os/incident.proto
@@ -170,7 +170,7 @@
];
optional BatteryTypeProto battery_type = 2006 [
- (section).type = SECTION_FILE,
+ (section).type = SECTION_NONE, // disabled since the path is device specific!
(section).args = "/sys/class/power_supply/bms/battery_type"
];
diff --git a/core/proto/android/providers/settings/global.proto b/core/proto/android/providers/settings/global.proto
index b5303c8..05686a0 100644
--- a/core/proto/android/providers/settings/global.proto
+++ b/core/proto/android/providers/settings/global.proto
@@ -451,6 +451,7 @@
// If set to 1, {@link Secure#LOCATION_MODE} will be set to {@link
// Secure#LOCATION_MODE_OFF} temporarily for all users.
optional SettingProto global_kill_switch = 5 [ (android.privacy).dest = DEST_AUTOMATIC ];
+ optional SettingProto gnss_satellite_blacklist = 6 [ (android.privacy).dest = DEST_AUTOMATIC ];
}
optional Location location = 69;
diff --git a/core/proto/android/providers/settings/secure.proto b/core/proto/android/providers/settings/secure.proto
index 593747d..3de8c39 100644
--- a/core/proto/android/providers/settings/secure.proto
+++ b/core/proto/android/providers/settings/secure.proto
@@ -340,6 +340,11 @@
}
optional Rotation rotation = 46;
+ // User-selected RTT mode. When on, outgoing and incoming calls will be
+ // answered as RTT calls when supported by the device and carrier. Boolean
+ // value.
+ optional SettingProto rtt_calling_mode = 69 [ (android.privacy).dest = DEST_AUTOMATIC ];
+
message Screensaver {
option (android.msg_privacy).dest = DEST_EXPLICIT;
@@ -474,5 +479,5 @@
// Please insert fields in alphabetical order and group them into messages
// if possible (to avoid reaching the method limit).
- // Next tag = 69;
+ // Next tag = 70;
}
diff --git a/core/proto/android/providers/settings/system.proto b/core/proto/android/providers/settings/system.proto
index 6b6edd2..dfc4081 100644
--- a/core/proto/android/providers/settings/system.proto
+++ b/core/proto/android/providers/settings/system.proto
@@ -151,10 +151,7 @@
}
optional Rotation rotation = 20;
- // User-selected RTT mode. When on, outgoing and incoming calls will be
- // answered as RTT calls when supported by the device and carrier. Boolean
- // value.
- optional SettingProto rtt_calling_mode = 21 [ (android.privacy).dest = DEST_AUTOMATIC ];
+ reserved 21; // rtt_calling_mode moved to Settings.Secure
message Screen {
option (android.msg_privacy).dest = DEST_EXPLICIT;
diff --git a/core/proto/android/service/notification.proto b/core/proto/android/service/notification.proto
index cccd2fe..bcd7f29 100644
--- a/core/proto/android/service/notification.proto
+++ b/core/proto/android/service/notification.proto
@@ -65,7 +65,7 @@
optional bool can_vibrate = 7;
optional bool can_show_light = 8;
optional string group_key = 9 [ (.android.privacy).dest = DEST_EXPLICIT ];
- optional int32 importance = 10;
+ optional sint32 importance = 10;
}
message ListenersDisablingEffectsProto {
@@ -122,11 +122,11 @@
// Default value is UNKNOWN_UID = USER_NULL = -10000.
optional int32 uid = 2;
// Default is IMPORTANCE_UNSPECIFIED (-1000).
- optional int32 importance = 3;
+ optional sint32 importance = 3;
// Default is PRIORITY_DEFAULT (0).
optional int32 priority = 4;
// Default is VISIBILITY_NO_OVERRIDE (-1000).
- optional int32 visibility = 5;
+ optional sint32 visibility = 5;
// Default is true.
optional bool show_badge = 6;
repeated android.app.NotificationChannelProto channels = 7;
diff --git a/core/res/AndroidManifest.xml b/core/res/AndroidManifest.xml
index b7b5f23..da15506 100644
--- a/core/res/AndroidManifest.xml
+++ b/core/res/AndroidManifest.xml
@@ -2030,6 +2030,15 @@
<permission android:name="android.permission.START_ANY_ACTIVITY"
android:protectionLevel="signature" />
+ <!-- @SystemApi Must be required by activities that handle the intent action
+ {@link Intent#ACTION_SEND_SHOW_SUSPENDED_APP_DETAILS}. This is for use by apps that
+ hold {@link Manifest.permission#SUSPEND_APPS} to interact with the system.
+ <p>Not for use by third-party applications.
+ @hide -->
+ <permission android:name="android.permission.SEND_SHOW_SUSPENDED_APP_DETAILS"
+ android:protectionLevel="signature" />
+ <uses-permission android:name="android.permission.SEND_SHOW_SUSPENDED_APP_DETAILS" />
+
<!-- @deprecated The {@link android.app.ActivityManager#restartPackage}
API is no longer supported. -->
<permission android:name="android.permission.RESTART_PACKAGES"
@@ -4116,6 +4125,12 @@
</intent-filter>
</activity>
+ <activity android:name="com.android.internal.app.SuspendedAppActivity"
+ android:theme="@style/Theme.DeviceDefault.Light.Dialog.Alert"
+ android:excludeFromRecents="true"
+ android:process=":ui">
+ </activity>
+
<activity android:name="com.android.internal.app.UnlaunchableAppActivity"
android:theme="@style/Theme.DeviceDefault.Light.Dialog.Alert"
android:excludeFromRecents="true"
diff --git a/core/res/res/values-land/dimens.xml b/core/res/res/values-land/dimens.xml
index 265eaaf..351bd81 100644
--- a/core/res/res/values-land/dimens.xml
+++ b/core/res/res/values-land/dimens.xml
@@ -29,7 +29,10 @@
<!-- Height of the status bar -->
<dimen name="status_bar_height">@dimen/status_bar_height_landscape</dimen>
-
+ <!-- Height of area above QQS where battery/time go -->
+ <dimen name="quick_qs_offset_height">@dimen/status_bar_height_landscape</dimen>
+ <!-- Total height of QQS in landscape, this is effectively status_bar_height_landscape + 128 -->
+ <dimen name="quick_qs_total_height">152dp</dimen>
<!-- Default height of an action bar. -->
<dimen name="action_bar_default_height">40dip</dimen>
<!-- Vertical padding around action bar icons. -->
diff --git a/core/res/res/values/config.xml b/core/res/res/values/config.xml
index 3cd80f2..12e5dfe 100644
--- a/core/res/res/values/config.xml
+++ b/core/res/res/values/config.xml
@@ -2249,6 +2249,10 @@
mirror the content of the default display. -->
<bool name="config_localDisplaysMirrorContent">true</bool>
+ <!-- Indicates whether local non-default displays are private.
+ {@see android.view.Display#FLAG_PRIVATE} -->
+ <bool name="config_localDisplaysPrivate">false</bool>
+
<!-- The default mode for the default display. One of the following values (See Display.java):
0 - COLOR_MODE_DEFAULT
7 - COLOR_MODE_SRGB
diff --git a/core/res/res/values/strings.xml b/core/res/res/values/strings.xml
index 17b9d28..715be5b 100644
--- a/core/res/res/values/strings.xml
+++ b/core/res/res/values/strings.xml
@@ -4703,6 +4703,13 @@
<!-- Menu item in the locale menu [CHAR LIMIT=30] -->
<string name="locale_search_menu">Search</string>
+ <!-- Title of the dialog that is shown when the user tries to launch a suspended application [CHAR LIMIT=30] -->
+ <string name="app_suspended_title">Action not allowed</string>
+ <!-- Default message shown in the dialog that is shown when the user tries to launch a suspended application [CHAR LIMIT=NONE] -->
+ <string name="app_suspended_default_message">The application <xliff:g id="app_name" example="GMail">%1$s</xliff:g> is currently disabled.</string>
+ <!-- Title of the button to show users more details about why the app has been suspended [CHAR LIMIT=50]-->
+ <string name="app_suspended_more_details">More details</string>
+
<!-- Title of a dialog. The string is asking if the user wants to turn on their work profile, which contains work apps that are managed by their employer. "Work" is an adjective. [CHAR LIMIT=30] -->
<string name="work_mode_off_title">Turn on work profile?</string>
<!-- Text in a dialog. This string describes what will happen if a user decides to turn on their work profile. "Work profile" is used as an adjective. [CHAR LIMIT=NONE] -->
diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml
index 78a7286..5856648 100644
--- a/core/res/res/values/symbols.xml
+++ b/core/res/res/values/symbols.xml
@@ -352,6 +352,7 @@
<java-symbol type="bool" name="config_noHomeScreen" />
<java-symbol type="bool" name="config_guestUserEphemeral" />
<java-symbol type="bool" name="config_localDisplaysMirrorContent" />
+ <java-symbol type="bool" name="config_localDisplaysPrivate" />
<java-symbol type="integer" name="config_defaultDisplayDefaultColorMode" />
<java-symbol type="bool" name="config_enableAppWidgetService" />
<java-symbol type="string" name="config_defaultPictureInPictureScreenEdgeInsets" />
@@ -1670,6 +1671,7 @@
<java-symbol type="dimen" name="navigation_bar_height_landscape_car_mode" />
<java-symbol type="dimen" name="navigation_bar_width_car_mode" />
<java-symbol type="dimen" name="status_bar_height" />
+ <java-symbol type="dimen" name="quick_qs_offset_height" />
<java-symbol type="dimen" name="quick_qs_total_height" />
<java-symbol type="drawable" name="ic_jog_dial_sound_off" />
<java-symbol type="drawable" name="ic_jog_dial_sound_on" />
@@ -2876,6 +2878,10 @@
<java-symbol type="string" name="suspended_widget_accessibility" />
+ <java-symbol type="string" name="app_suspended_title" />
+ <java-symbol type="string" name="app_suspended_more_details" />
+ <java-symbol type="string" name="app_suspended_default_message" />
+
<!-- Used internally for assistant to launch activity transitions -->
<java-symbol type="id" name="cross_task_transition" />
diff --git a/core/tests/coretests/src/android/provider/SettingsBackupTest.java b/core/tests/coretests/src/android/provider/SettingsBackupTest.java
index 002c9e2..b1936b9 100644
--- a/core/tests/coretests/src/android/provider/SettingsBackupTest.java
+++ b/core/tests/coretests/src/android/provider/SettingsBackupTest.java
@@ -239,6 +239,7 @@
Settings.Global.GLOBAL_HTTP_PROXY_HOST,
Settings.Global.GLOBAL_HTTP_PROXY_PAC,
Settings.Global.GLOBAL_HTTP_PROXY_PORT,
+ Settings.Global.GNSS_SATELLITE_BLACKLIST,
Settings.Global.GPRS_REGISTER_CHECK_PERIOD_MS,
Settings.Global.HDMI_CONTROL_AUTO_DEVICE_OFF_ENABLED,
Settings.Global.HDMI_CONTROL_AUTO_WAKEUP_ENABLED,
diff --git a/core/tests/coretests/src/android/view/textclassifier/TextLinksTest.java b/core/tests/coretests/src/android/view/textclassifier/TextLinksTest.java
index fb09e3e..fff723f 100644
--- a/core/tests/coretests/src/android/view/textclassifier/TextLinksTest.java
+++ b/core/tests/coretests/src/android/view/textclassifier/TextLinksTest.java
@@ -30,6 +30,7 @@
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
+import java.util.HashSet;
import java.util.List;
import java.util.Locale;
import java.util.Map;
@@ -105,7 +106,7 @@
assertEquals("en-US,de-DE", result.getDefaultLocales().toLanguageTags());
assertEquals(new String[]{TextClassifier.HINT_TEXT_IS_EDITABLE},
result.getEntityConfig().getHints().toArray());
- assertEquals(Arrays.asList("a", "c"),
+ assertEquals(new HashSet<String>(Arrays.asList("a", "c")),
result.getEntityConfig().resolveEntityListModifications(Collections.emptyList()));
}
}
diff --git a/data/etc/hiddenapi-package-whitelist.xml b/data/etc/hiddenapi-package-whitelist.xml
index 95aff9a..4e09c69 100644
--- a/data/etc/hiddenapi-package-whitelist.xml
+++ b/data/etc/hiddenapi-package-whitelist.xml
@@ -17,66 +17,28 @@
<!--
This XML file declares which system apps should be exempted from the hidden API blacklisting, i.e.
-which apps should be allowed to access the entire private API.
+which apps should be allowed to access the entire private API. Only apps NOT signed with the
+platform cert need to be included, as apps signed with the platform cert are exempted by default.
-->
<config>
- <hidden-api-whitelisted-app package="android.car.cluster.loggingrenderer" />
- <hidden-api-whitelisted-app package="android.car.input.service" />
- <hidden-api-whitelisted-app package="android.car.usb.handler" />
<hidden-api-whitelisted-app package="android.ext.services" />
<hidden-api-whitelisted-app package="com.android.apps.tag" />
- <hidden-api-whitelisted-app package="com.android.backupconfirm" />
<hidden-api-whitelisted-app package="com.android.basicsmsreceiver" />
- <hidden-api-whitelisted-app package="com.android.bluetooth" />
- <hidden-api-whitelisted-app package="com.android.bluetoothdebug" />
- <hidden-api-whitelisted-app package="com.android.bluetoothmidiservice" />
<hidden-api-whitelisted-app package="com.android.bookmarkprovider" />
<hidden-api-whitelisted-app package="com.android.calllogbackup" />
<hidden-api-whitelisted-app package="com.android.camera" />
- <hidden-api-whitelisted-app package="com.android.captiveportallogin" />
- <hidden-api-whitelisted-app package="com.android.car" />
<hidden-api-whitelisted-app package="com.android.car.dialer" />
- <hidden-api-whitelisted-app package="com.android.car.hvac" />
- <hidden-api-whitelisted-app package="com.android.car.mapsplaceholder" />
- <hidden-api-whitelisted-app package="com.android.car.media" />
- <hidden-api-whitelisted-app package="com.android.car.media.localmediaplayer" />
<hidden-api-whitelisted-app package="com.android.car.messenger" />
<hidden-api-whitelisted-app package="com.android.car.overview" />
- <hidden-api-whitelisted-app package="com.android.car.radio" />
- <hidden-api-whitelisted-app package="com.android.car.settings" />
<hidden-api-whitelisted-app package="com.android.car.stream" />
- <hidden-api-whitelisted-app package="com.android.car.systemupdater" />
- <hidden-api-whitelisted-app package="com.android.car.trust" />
- <hidden-api-whitelisted-app package="com.android.carrierconfig" />
- <hidden-api-whitelisted-app package="com.android.carrierdefaultapp" />
- <hidden-api-whitelisted-app package="com.android.cellbroadcastreceiver" />
- <hidden-api-whitelisted-app package="com.android.certinstaller" />
<hidden-api-whitelisted-app package="com.android.companiondevicemanager" />
- <hidden-api-whitelisted-app package="com.android.customlocale2" />
- <hidden-api-whitelisted-app package="com.android.defcontainer" />
- <hidden-api-whitelisted-app package="com.android.development" />
- <hidden-api-whitelisted-app package="com.android.documentsui" />
<hidden-api-whitelisted-app package="com.android.dreams.basic" />
- <hidden-api-whitelisted-app package="com.android.egg" />
- <hidden-api-whitelisted-app package="com.android.emergency" />
- <hidden-api-whitelisted-app package="com.android.externalstorage" />
- <hidden-api-whitelisted-app package="com.android.fakeoemfeatures" />
<hidden-api-whitelisted-app package="com.android.gallery" />
- <hidden-api-whitelisted-app package="com.android.hotspot2" />
- <hidden-api-whitelisted-app package="com.android.keychain" />
<hidden-api-whitelisted-app package="com.android.launcher3" />
- <hidden-api-whitelisted-app package="com.android.location.fused" />
- <hidden-api-whitelisted-app package="com.android.managedprovisioning" />
- <hidden-api-whitelisted-app package="com.android.mms.service" />
<hidden-api-whitelisted-app package="com.android.mtp" />
<hidden-api-whitelisted-app package="com.android.musicfx" />
- <hidden-api-whitelisted-app package="com.android.nfc" />
- <hidden-api-whitelisted-app package="com.android.osu" />
<hidden-api-whitelisted-app package="com.android.packageinstaller" />
- <hidden-api-whitelisted-app package="com.android.pacprocessor" />
- <hidden-api-whitelisted-app package="com.android.phone" />
- <hidden-api-whitelisted-app package="com.android.pmc" />
<hidden-api-whitelisted-app package="com.android.printservice.recommendation" />
<hidden-api-whitelisted-app package="com.android.printspooler" />
<hidden-api-whitelisted-app package="com.android.providers.blockednumber" />
@@ -85,36 +47,13 @@
<hidden-api-whitelisted-app package="com.android.providers.downloads" />
<hidden-api-whitelisted-app package="com.android.providers.downloads.ui" />
<hidden-api-whitelisted-app package="com.android.providers.media" />
- <hidden-api-whitelisted-app package="com.android.providers.settings" />
- <hidden-api-whitelisted-app package="com.android.providers.telephony" />
<hidden-api-whitelisted-app package="com.android.providers.tv" />
<hidden-api-whitelisted-app package="com.android.providers.userdictionary" />
- <hidden-api-whitelisted-app package="com.android.provision" />
- <hidden-api-whitelisted-app package="com.android.proxyhandler" />
- <hidden-api-whitelisted-app package="com.android.sdksetup" />
- <hidden-api-whitelisted-app package="com.android.se" />
- <hidden-api-whitelisted-app package="com.android.server.telecom" />
- <hidden-api-whitelisted-app package="com.android.service.ims" />
- <hidden-api-whitelisted-app package="com.android.service.ims.presence" />
- <hidden-api-whitelisted-app package="com.android.settings" />
- <hidden-api-whitelisted-app package="com.android.sharedstoragebackup" />
- <hidden-api-whitelisted-app package="com.android.shell" />
<hidden-api-whitelisted-app package="com.android.smspush" />
<hidden-api-whitelisted-app package="com.android.spare_parts" />
<hidden-api-whitelisted-app package="com.android.statementservice" />
- <hidden-api-whitelisted-app package="com.android.stk" />
<hidden-api-whitelisted-app package="com.android.storagemanager" />
- <hidden-api-whitelisted-app package="com.android.support.car.lenspicker" />
- <hidden-api-whitelisted-app package="com.android.systemui" />
<hidden-api-whitelisted-app package="com.android.systemui.plugins" />
<hidden-api-whitelisted-app package="com.android.terminal" />
- <hidden-api-whitelisted-app package="com.android.timezone.updater" />
- <hidden-api-whitelisted-app package="com.android.traceur" />
- <hidden-api-whitelisted-app package="com.android.tv.settings" />
- <hidden-api-whitelisted-app package="com.android.vpndialogs" />
- <hidden-api-whitelisted-app package="com.android.wallpaper.livepicker" />
- <hidden-api-whitelisted-app package="com.android.wallpaperbackup" />
- <hidden-api-whitelisted-app package="com.android.wallpapercropper" />
- <hidden-api-whitelisted-app package="com.googlecode.android_scripting" />
<hidden-api-whitelisted-app package="jp.co.omronsoft.openwnn" />
</config>
diff --git a/graphics/java/android/graphics/ImageDecoder.java b/graphics/java/android/graphics/ImageDecoder.java
index 31abf92..098f100 100644
--- a/graphics/java/android/graphics/ImageDecoder.java
+++ b/graphics/java/android/graphics/ImageDecoder.java
@@ -23,8 +23,10 @@
import android.annotation.AnyThread;
import android.annotation.IntDef;
+import android.annotation.IntRange;
import android.annotation.NonNull;
import android.annotation.Nullable;
+import android.annotation.Px;
import android.annotation.TestApi;
import android.annotation.WorkerThread;
import android.content.ContentResolver;
@@ -579,7 +581,7 @@
/** @removed
* @deprecated Subsumed by {@link #DecodeException}.
*/
- @java.lang.Deprecated
+ @Deprecated
public static class IncompleteException extends IOException {};
/**
@@ -611,19 +613,19 @@
/** @removed
* @deprecated Replaced by {@link #DecodeException#SOURCE_EXCEPTION}.
*/
- @java.lang.Deprecated
+ @Deprecated
public static final int ERROR_SOURCE_EXCEPTION = 1;
/** @removed
* @deprecated Replaced by {@link #DecodeException#SOURCE_INCOMPLETE}.
*/
- @java.lang.Deprecated
+ @Deprecated
public static final int ERROR_SOURCE_INCOMPLETE = 2;
/** @removed
* @deprecated Replaced by {@link #DecodeException#SOURCE_MALFORMED_DATA}.
*/
- @java.lang.Deprecated
+ @Deprecated
public static final int ERROR_SOURCE_ERROR = 3;
/**
@@ -746,6 +748,7 @@
private final int mWidth;
private final int mHeight;
private final boolean mAnimated;
+ private final boolean mIsNinePatch;
private int mDesiredWidth;
private int mDesiredHeight;
@@ -776,13 +779,14 @@
*/
@SuppressWarnings("unused")
private ImageDecoder(long nativePtr, int width, int height,
- boolean animated) {
+ boolean animated, boolean isNinePatch) {
mNativePtr = nativePtr;
mWidth = width;
mHeight = height;
mDesiredWidth = width;
mDesiredHeight = height;
mAnimated = animated;
+ mIsNinePatch = isNinePatch;
mCloseGuard.open("close");
}
@@ -998,7 +1002,7 @@
/** @removed
* @deprecated Renamed to {@link #setTargetSize}.
*/
- @java.lang.Deprecated
+ @Deprecated
public ImageDecoder setResize(int width, int height) {
this.setTargetSize(width, height);
return this;
@@ -1020,10 +1024,11 @@
* <p>Like all setters on ImageDecoder, this must be called inside
* {@link OnHeaderDecodedListener#onHeaderDecoded onHeaderDecoded}.</p>
*
- * @param width must be greater than 0.
- * @param height must be greater than 0.
+ * @param width width in pixels of the output, must be greater than 0
+ * @param height height in pixels of the output, must be greater than 0
*/
- public void setTargetSize(int width, int height) {
+ public void setTargetSize(@Px @IntRange(from = 1) int width,
+ @Px @IntRange(from = 1) int height) {
if (width <= 0 || height <= 0) {
throw new IllegalArgumentException("Dimensions must be positive! "
+ "provided (" + width + ", " + height + ")");
@@ -1036,7 +1041,7 @@
/** @removed
* @deprecated Renamed to {@link #setTargetSampleSize}.
*/
- @java.lang.Deprecated
+ @Deprecated
public ImageDecoder setResize(int sampleSize) {
this.setTargetSampleSize(sampleSize);
return this;
@@ -1083,14 +1088,20 @@
*
* <p>Must be greater than or equal to 1.</p>
*
+ * <p>This has the same effect as calling {@link #setTargetSize} with
+ * dimensions based on the {@code sampleSize}. Unlike dividing the original
+ * width and height by the {@code sampleSize} manually, calling this method
+ * allows {@code ImageDecoder} to round in the direction that it can do most
+ * efficiently.</p>
+ *
* <p>Only the last call to this or {@link #setTargetSize} is respected.</p>
*
* <p>Like all setters on ImageDecoder, this must be called inside
* {@link OnHeaderDecodedListener#onHeaderDecoded onHeaderDecoded}.</p>
*
- * @param sampleSize Sampling rate of the encoded image.
+ * @param sampleSize sampling rate of the encoded image.
*/
- public void setTargetSampleSize(int sampleSize) {
+ public void setTargetSampleSize(@IntRange(from = 1) int sampleSize) {
Size size = this.getSampledSize(sampleSize);
int targetWidth = getTargetDimension(mWidth, sampleSize, size.getWidth());
int targetHeight = getTargetDimension(mHeight, sampleSize, size.getHeight());
@@ -1116,7 +1127,7 @@
/**
* Use a software allocation for the pixel memory.
*
- * Useful for drawing to a software {@link Canvas} or for
+ * <p>Useful for drawing to a software {@link Canvas} or for
* accessing the pixels on the final output.
*/
public static final int ALLOCATOR_SOFTWARE = 1;
@@ -1124,14 +1135,14 @@
/**
* Use shared memory for the pixel memory.
*
- * Useful for sharing across processes.
+ * <p>Useful for sharing across processes.
*/
public static final int ALLOCATOR_SHARED_MEMORY = 2;
/**
* Require a {@link Bitmap.Config#HARDWARE} {@link Bitmap}.
*
- * When this is combined with incompatible options, like
+ * <p>When this is combined with incompatible options, like
* {@link #setMutableRequired setMutableRequired(true)} or
* {@link #setDecodeAsAlphaMaskEnabled setDecodeAsAlphaMaskEnabled(true)},
* {@link #decodeDrawable decodeDrawable} or {@link #decodeBitmap decodeBitmap}
@@ -1194,7 +1205,7 @@
/** @removed
* @deprecated Renamed to {@link #setUnpremultipliedRequired}.
*/
- @java.lang.Deprecated
+ @Deprecated
public ImageDecoder setRequireUnpremultiplied(boolean unpremultipliedRequired) {
this.setUnpremultipliedRequired(unpremultipliedRequired);
return this;
@@ -1210,7 +1221,7 @@
/** @removed
* @deprecated Renamed to {@link #isUnpremultipliedRequired}.
*/
- @java.lang.Deprecated
+ @Deprecated
public boolean getRequireUnpremultiplied() {
return this.isUnpremultipliedRequired();
}
@@ -1339,7 +1350,7 @@
/** @removed
* @deprecated Renamed to {@link #setMutableRequired}.
*/
- @java.lang.Deprecated
+ @Deprecated
public ImageDecoder setMutable(boolean mutable) {
this.setMutableRequired(mutable);
return this;
@@ -1355,37 +1366,68 @@
/** @removed
* @deprecated Renamed to {@link #isMutableRequired}.
*/
- @java.lang.Deprecated
+ @Deprecated
public boolean getMutable() {
return this.isMutableRequired();
}
/**
- * Specify whether to potentially save RAM at the expense of quality.
+ * Save memory if possible by using a denser {@link Bitmap.Config} at the
+ * cost of some image quality.
*
- * <p>Setting this to {@code true} may result in a {@link Bitmap} with a
- * denser {@link Bitmap.Config}, depending on the image. For example, an
- * opaque {@link Bitmap} with 8 bits or precision for each of its red,
- * green and blue components would decode to
- * {@link Bitmap.Config#ARGB_8888} by default, but setting this to
- * {@code true} will result in decoding to {@link Bitmap.Config#RGB_565}.
- * This necessarily lowers the quality of the output, but saves half
- * the memory used.</p>
+ * <p>For example an opaque 8-bit image may be compressed into an
+ * {@link Bitmap.Config#RGB_565} configuration, sacrificing image
+ * quality to save memory.
+ */
+ public static final int MEMORY_POLICY_LOW_RAM = 0;
+
+ /**
+ * Use the most natural {@link Bitmap.Config} for the internal {@link Bitmap}.
+ *
+ * <p>This is the recommended default for most applications and usages. This
+ * will use the closest {@link Bitmap.Config} for the encoded source. If the
+ * encoded source does not exactly match any {@link Bitmap.Config}, the next
+ * highest quality {@link Bitmap.Config} will be used avoiding any loss in
+ * image quality.
+ */
+ public static final int MEMORY_POLICY_DEFAULT = 1;
+
+ /** @hide **/
+ @Retention(SOURCE)
+ @IntDef(value = { MEMORY_POLICY_DEFAULT, MEMORY_POLICY_LOW_RAM },
+ prefix = {"MEMORY_POLICY_"})
+ public @interface MemoryPolicy {};
+
+ /**
+ * Specify the memory policy for the decoded {@link Bitmap}.
*
* <p>Like all setters on ImageDecoder, this must be called inside
* {@link OnHeaderDecodedListener#onHeaderDecoded onHeaderDecoded}.</p>
*/
+ public void setMemorySizePolicy(@MemoryPolicy int policy) {
+ mConserveMemory = (policy == MEMORY_POLICY_LOW_RAM);
+ }
+
+ /**
+ * Retrieve the memory policy for the decoded {@link Bitmap}.
+ */
+ @MemoryPolicy
+ public int getMemorySizePolicy() {
+ return mConserveMemory ? MEMORY_POLICY_LOW_RAM : MEMORY_POLICY_DEFAULT;
+ }
+
+ /** @removed
+ * @deprecated Replaced by {@link #setMemorySizePolicy}.
+ */
+ @Deprecated
public void setConserveMemory(boolean conserveMemory) {
mConserveMemory = conserveMemory;
}
- /**
- * Return whether this object will try to save RAM at the expense of quality.
- *
- * <p>This returns whether {@link #setConserveMemory} was set to {@code true}.
- * It may still return {@code true} even if the {@code ImageDecoder} does not
- * have a way to save RAM at the expense of quality for this image.</p>
+ /** @removed
+ * @deprecated Replaced by {@link #getMemorySizePolicy}.
*/
+ @Deprecated
public boolean getConserveMemory() {
return mConserveMemory;
}
@@ -1412,7 +1454,7 @@
/** @removed
* @deprecated Renamed to {@link #setDecodeAsAlphaMaskEnabled}.
*/
- @java.lang.Deprecated
+ @Deprecated
public ImageDecoder setDecodeAsAlphaMask(boolean enabled) {
this.setDecodeAsAlphaMaskEnabled(enabled);
return this;
@@ -1421,7 +1463,7 @@
/** @removed
* @deprecated Renamed to {@link #setDecodeAsAlphaMaskEnabled}.
*/
- @java.lang.Deprecated
+ @Deprecated
public ImageDecoder setAsAlphaMask(boolean asAlphaMask) {
this.setDecodeAsAlphaMask(asAlphaMask);
return this;
@@ -1442,7 +1484,7 @@
/** @removed
* @deprecated Renamed to {@link #isDecodeAsAlphaMaskEnabled}.
*/
- @java.lang.Deprecated
+ @Deprecated
public boolean getDecodeAsAlphaMask() {
return mDecodeAsAlphaMask;
}
@@ -1450,7 +1492,7 @@
/** @removed
* @deprecated Renamed to {@link #isDecodeAsAlphaMaskEnabled}.
*/
- @java.lang.Deprecated
+ @Deprecated
public boolean getAsAlphaMask() {
return this.getDecodeAsAlphaMask();
}
@@ -1625,7 +1667,7 @@
// this call potentially manipulates the decoder so it must be performed prior to
// decoding the bitmap and after decode set the density on the resulting bitmap
- final int srcDensity = computeDensity(src, decoder);
+ final int srcDensity = decoder.computeDensity(src);
if (decoder.mAnimated) {
// AnimatedImageDrawable calls postProcessAndRelease only if
// mPostProcessor exists.
@@ -1715,7 +1757,7 @@
// this call potentially manipulates the decoder so it must be performed prior to
// decoding the bitmap
- final int srcDensity = computeDensity(src, decoder);
+ final int srcDensity = decoder.computeDensity(src);
Bitmap bm = decoder.decodeBitmapInternal();
bm.setDensity(srcDensity);
@@ -1732,12 +1774,26 @@
}
// This method may modify the decoder so it must be called prior to performing the decode
- private static int computeDensity(@NonNull Source src, @NonNull ImageDecoder decoder) {
+ private int computeDensity(@NonNull Source src) {
// if the caller changed the size then we treat the density as unknown
- if (decoder.requestedResize()) {
+ if (this.requestedResize()) {
return Bitmap.DENSITY_NONE;
}
+ final int srcDensity = src.getDensity();
+ if (srcDensity == Bitmap.DENSITY_NONE) {
+ return srcDensity;
+ }
+
+ // Scaling up nine-patch divs is imprecise and is better handled
+ // at draw time. An app won't be relying on the internal Bitmap's
+ // size, so it is safe to let NinePatchDrawable handle scaling.
+ // mPostProcessor disables nine-patching, so behave normally if
+ // it is present.
+ if (mIsNinePatch && mPostProcessor == null) {
+ return srcDensity;
+ }
+
// Special stuff for compatibility mode: if the target density is not
// the same as the display density, but the resource -is- the same as
// the display density, then don't scale it down to the target density.
@@ -1746,23 +1802,25 @@
// to the compatibility density only to have them scaled back up when
// drawn to the screen.
Resources res = src.getResources();
- final int srcDensity = src.getDensity();
if (res != null && res.getDisplayMetrics().noncompatDensityDpi == srcDensity) {
return srcDensity;
}
+ final int dstDensity = src.computeDstDensity();
+ if (srcDensity == dstDensity) {
+ return srcDensity;
+ }
+
// For P and above, only resize if it would be a downscale. Scale up prior
// to P in case the app relies on the Bitmap's size without considering density.
- final int dstDensity = src.computeDstDensity();
- if (srcDensity == Bitmap.DENSITY_NONE || srcDensity == dstDensity
- || (srcDensity < dstDensity && sApiLevel >= Build.VERSION_CODES.P)) {
+ if (srcDensity < dstDensity && sApiLevel >= Build.VERSION_CODES.P) {
return srcDensity;
}
float scale = (float) dstDensity / srcDensity;
- int scaledWidth = (int) (decoder.mWidth * scale + 0.5f);
- int scaledHeight = (int) (decoder.mHeight * scale + 0.5f);
- decoder.setTargetSize(scaledWidth, scaledHeight);
+ int scaledWidth = (int) (mWidth * scale + 0.5f);
+ int scaledHeight = (int) (mHeight * scale + 0.5f);
+ this.setTargetSize(scaledWidth, scaledHeight);
return dstDensity;
}
diff --git a/keystore/java/android/security/keystore/KeyProtection.java b/keystore/java/android/security/keystore/KeyProtection.java
index 4daf30c..41dc201 100644
--- a/keystore/java/android/security/keystore/KeyProtection.java
+++ b/keystore/java/android/security/keystore/KeyProtection.java
@@ -445,6 +445,9 @@
/**
* Returns {@code true} if the key is authorized to be used only if a test of user presence has
* been performed between the {@code Signature.initSign()} and {@code Signature.sign()} calls.
+ * It requires that the KeyStore implementation have a direct way to validate the user presence
+ * for example a KeyStore hardware backed strongbox can use a button press that is observable
+ * in hardware.
*/
public boolean isUserPresenceRequired() {
return mUserPresenceRequred;
diff --git a/keystore/java/android/security/keystore/UserPresenceUnavailableException.java b/keystore/java/android/security/keystore/UserPresenceUnavailableException.java
index cf4099e..1b053a5 100644
--- a/keystore/java/android/security/keystore/UserPresenceUnavailableException.java
+++ b/keystore/java/android/security/keystore/UserPresenceUnavailableException.java
@@ -16,13 +16,13 @@
package android.security.keystore;
-import java.security.InvalidAlgorithmParameterException;
+import java.security.InvalidKeyException;
/**
* Indicates the condition that a proof of user-presence was
* requested but this proof was not presented.
*/
-public class UserPresenceUnavailableException extends InvalidAlgorithmParameterException {
+public class UserPresenceUnavailableException extends InvalidKeyException {
/**
* Constructs a {@code UserPresenceUnavailableException} without a detail message or cause.
*/
diff --git a/libs/androidfw/AssetManager2.cpp b/libs/androidfw/AssetManager2.cpp
index d9f1293..5460b3b 100644
--- a/libs/androidfw/AssetManager2.cpp
+++ b/libs/androidfw/AssetManager2.cpp
@@ -596,7 +596,7 @@
const ResTable_map* const map_entry_end = map_entry + dtohl(map->count);
uint32_t parent_resid = dtohl(map->parent.ident);
- if (parent_resid == 0) {
+ if (parent_resid == 0 || parent_resid == resid) {
// There is no parent, meaning there is nothing to inherit and we can do a simple
// copy of the entries in the map.
const size_t entry_count = map_entry_end - map_entry;
diff --git a/libs/androidfw/ResourceTypes.cpp b/libs/androidfw/ResourceTypes.cpp
index 6268c40..985a756 100644
--- a/libs/androidfw/ResourceTypes.cpp
+++ b/libs/androidfw/ResourceTypes.cpp
@@ -727,11 +727,42 @@
if ((uint32_t)(u8str+u8len-strings) < mStringPoolSize) {
AutoMutex lock(mDecodeLock);
+ if (mCache != NULL && mCache[idx] != NULL) {
+ return mCache[idx];
+ }
+
+ // Retrieve the actual length of the utf8 string if the
+ // encoded length was truncated
+ if (stringDecodeAt(idx, u8str, u8len, &u8len) == NULL) {
+ return NULL;
+ }
+
+ // Since AAPT truncated lengths longer than 0x7FFF, check
+ // that the bits that remain after truncation at least match
+ // the bits of the actual length
+ ssize_t actualLen = utf8_to_utf16_length(u8str, u8len);
+ if (actualLen < 0 || ((size_t)actualLen & 0x7FFF) != *u16len) {
+ ALOGW("Bad string block: string #%lld decoded length is not correct "
+ "%lld vs %llu\n",
+ (long long)idx, (long long)actualLen, (long long)*u16len);
+ return NULL;
+ }
+
+ *u16len = (size_t) actualLen;
+ char16_t *u16str = (char16_t *)calloc(*u16len+1, sizeof(char16_t));
+ if (!u16str) {
+ ALOGW("No memory when trying to allocate decode cache for string #%d\n",
+ (int)idx);
+ return NULL;
+ }
+
+ utf8_to_utf16(u8str, u8len, u16str, *u16len + 1);
+
if (mCache == NULL) {
#ifndef __ANDROID__
if (kDebugStringPoolNoisy) {
ALOGI("CREATING STRING CACHE OF %zu bytes",
- mHeader->stringCount*sizeof(char16_t**));
+ mHeader->stringCount*sizeof(char16_t**));
}
#else
// We do not want to be in this case when actually running Android.
@@ -741,41 +772,15 @@
mCache = (char16_t**)calloc(mHeader->stringCount, sizeof(char16_t*));
if (mCache == NULL) {
ALOGW("No memory trying to allocate decode cache table of %d bytes\n",
- (int)(mHeader->stringCount*sizeof(char16_t**)));
+ (int)(mHeader->stringCount*sizeof(char16_t**)));
return NULL;
}
}
- if (mCache[idx] != NULL) {
- return mCache[idx];
- }
-
- ssize_t actualLen = utf8_to_utf16_length(u8str, u8len);
- if (actualLen < 0 || (size_t)actualLen != *u16len) {
- ALOGW("Bad string block: string #%lld decoded length is not correct "
- "%lld vs %llu\n",
- (long long)idx, (long long)actualLen, (long long)*u16len);
- return NULL;
- }
-
- // Reject malformed (non null-terminated) strings
- if (u8str[u8len] != 0x00) {
- ALOGW("Bad string block: string #%d is not null-terminated",
- (int)idx);
- return NULL;
- }
-
- char16_t *u16str = (char16_t *)calloc(*u16len+1, sizeof(char16_t));
- if (!u16str) {
- ALOGW("No memory when trying to allocate decode cache for string #%d\n",
- (int)idx);
- return NULL;
- }
-
if (kDebugStringPoolNoisy) {
- ALOGI("Caching UTF8 string: %s", u8str);
+ ALOGI("Caching UTF8 string: %s", u8str);
}
- utf8_to_utf16(u8str, u8len, u16str, *u16len + 1);
+
mCache[idx] = u16str;
return u16str;
} else {
@@ -812,13 +817,8 @@
*outLen = encLen;
if ((uint32_t)(str+encLen-strings) < mStringPoolSize) {
- // Reject malformed (non null-terminated) strings
- if (str[encLen] != 0x00) {
- ALOGW("Bad string block: string #%d is not null-terminated",
- (int)idx);
- return NULL;
- }
- return (const char*)str;
+ return stringDecodeAt(idx, str, encLen, outLen);
+
} else {
ALOGW("Bad string block: string #%d extends to %d, past end at %d\n",
(int)idx, (int)(str+encLen-strings), (int)mStringPoolSize);
@@ -832,6 +832,38 @@
return NULL;
}
+/**
+ * AAPT incorrectly writes a truncated string length when the string size
+ * exceeded the maximum possible encode length value (0x7FFF). To decode a
+ * truncated length, iterate through length values that end in the encode length
+ * bits. Strings that exceed the maximum encode length are not placed into
+ * StringPools in AAPT2.
+ **/
+const char* ResStringPool::stringDecodeAt(size_t idx, const uint8_t* str,
+ const size_t encLen, size_t* outLen) const {
+ const uint8_t* strings = (uint8_t*)mStrings;
+
+ size_t i = 0, end = encLen;
+ while ((uint32_t)(str+end-strings) < mStringPoolSize) {
+ if (str[end] == 0x00) {
+ if (i != 0) {
+ ALOGW("Bad string block: string #%d is truncated (actual length is %d)",
+ (int)idx, (int)end);
+ }
+
+ *outLen = end;
+ return (const char*)str;
+ }
+
+ end = (++i << (sizeof(uint8_t) * 8 * 2 - 1)) | encLen;
+ }
+
+ // Reject malformed (non null-terminated) strings
+ ALOGW("Bad string block: string #%d is not null-terminated",
+ (int)idx);
+ return NULL;
+}
+
const String8 ResStringPool::string8ObjectAt(size_t idx) const
{
size_t len;
diff --git a/libs/androidfw/include/androidfw/ResourceTypes.h b/libs/androidfw/include/androidfw/ResourceTypes.h
index a1f15f0..bc0a07a 100644
--- a/libs/androidfw/include/androidfw/ResourceTypes.h
+++ b/libs/androidfw/include/androidfw/ResourceTypes.h
@@ -538,6 +538,9 @@
uint32_t mStringPoolSize; // number of uint16_t
const uint32_t* mStyles;
uint32_t mStylePoolSize; // number of uint32_t
+
+ const char* stringDecodeAt(size_t idx, const uint8_t* str, const size_t encLen,
+ size_t* outLen) const;
};
/**
diff --git a/libs/androidfw/tests/ResTable_test.cpp b/libs/androidfw/tests/ResTable_test.cpp
index 2df4130..326474e 100644
--- a/libs/androidfw/tests/ResTable_test.cpp
+++ b/libs/androidfw/tests/ResTable_test.cpp
@@ -424,4 +424,56 @@
EXPECT_EQ(1, std::count(locales.begin(), locales.end(), String8("sv")));
}
+TEST(ResTableTest, TruncatedEncodeLength) {
+ std::string contents;
+ ASSERT_TRUE(ReadFileFromZipToString(GetTestDataPath() + "/length_decode/length_decode_valid.apk",
+ "resources.arsc", &contents));
+
+ ResTable table;
+ ASSERT_EQ(NO_ERROR, table.add(contents.data(), contents.size()));
+
+ Res_value val;
+ ssize_t block = table.getResource(0x7f010001, &val, MAY_NOT_BE_BAG);
+ ASSERT_GE(block, 0);
+ ASSERT_EQ(Res_value::TYPE_STRING, val.dataType);
+
+ const ResStringPool* pool = table.getTableStringBlock(block);
+ ASSERT_TRUE(pool != NULL);
+ ASSERT_LT(val.data, pool->size());
+
+ // Make sure a string with a truncated length is read to its correct length
+ size_t str_len;
+ const char* target_str8 = pool->string8At(val.data, &str_len);
+ ASSERT_TRUE(target_str8 != NULL);
+ ASSERT_EQ(size_t(40076), String8(target_str8, str_len).size());
+ ASSERT_EQ(target_str8[40075], ']');
+
+ const char16_t* target_str16 = pool->stringAt(val.data, &str_len);
+ ASSERT_TRUE(target_str16 != NULL);
+ ASSERT_EQ(size_t(40076), String16(target_str16, str_len).size());
+ ASSERT_EQ(target_str8[40075], (char16_t) ']');
+
+ // Load an edited apk with the null terminator removed from the end of the
+ // string
+ std::string invalid_contents;
+ ASSERT_TRUE(ReadFileFromZipToString(GetTestDataPath() + "/length_decode/length_decode_invalid.apk",
+ "resources.arsc", &invalid_contents));
+ ResTable invalid_table;
+ ASSERT_EQ(NO_ERROR, invalid_table.add(invalid_contents.data(), invalid_contents.size()));
+
+ Res_value invalid_val;
+ ssize_t invalid_block = invalid_table.getResource(0x7f010001, &invalid_val, MAY_NOT_BE_BAG);
+ ASSERT_GE(invalid_block, 0);
+ ASSERT_EQ(Res_value::TYPE_STRING, invalid_val.dataType);
+
+ const ResStringPool* invalid_pool = invalid_table.getTableStringBlock(invalid_block);
+ ASSERT_TRUE(invalid_pool != NULL);
+ ASSERT_LT(invalid_val.data, invalid_pool->size());
+
+ // Make sure a string with a truncated length that is not null terminated errors
+ // and does not return the string
+ ASSERT_TRUE(invalid_pool->string8At(invalid_val.data, &str_len) == NULL);
+ ASSERT_TRUE(invalid_pool->stringAt(invalid_val.data, &str_len) == NULL);
+}
+
} // namespace android
diff --git a/libs/androidfw/tests/data/length_decode/length_decode_invalid.apk b/libs/androidfw/tests/data/length_decode/length_decode_invalid.apk
new file mode 100644
index 0000000..b089651
--- /dev/null
+++ b/libs/androidfw/tests/data/length_decode/length_decode_invalid.apk
Binary files differ
diff --git a/libs/androidfw/tests/data/length_decode/length_decode_valid.apk b/libs/androidfw/tests/data/length_decode/length_decode_valid.apk
new file mode 100644
index 0000000..add23e1
--- /dev/null
+++ b/libs/androidfw/tests/data/length_decode/length_decode_valid.apk
Binary files differ
diff --git a/libs/protoutil/Android.bp b/libs/protoutil/Android.bp
index 4f1d2d5..7ad83ca 100644
--- a/libs/protoutil/Android.bp
+++ b/libs/protoutil/Android.bp
@@ -37,3 +37,20 @@
"liblog",
],
}
+
+cc_test {
+ name: "libprotoutil_test",
+
+ srcs: [
+ "tests/EncodedBuffer_test.cpp",
+ ],
+
+ shared_libs: [
+ "libcutils",
+ "libprotoutil",
+ ],
+
+ static_libs: [
+ "libgmock",
+ ],
+}
diff --git a/libs/protoutil/AndroidTest.xml b/libs/protoutil/AndroidTest.xml
new file mode 100644
index 0000000..46d418e
--- /dev/null
+++ b/libs/protoutil/AndroidTest.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.
+-->
+<configuration description="Config for libprotoutil_test">
+ <target_preparer class="com.android.tradefed.targetprep.PushFilePreparer">
+ <option name="cleanup" value="true" />
+ <option name="push" value="libprotoutil_test->/data/nativetest/libprotoutil_test" />
+ </target_preparer>
+ <option name="test-suite-tag" value="apct" />
+ <test class="com.android.tradefed.testtype.GTest" >
+ <option name="native-test-device-path" value="/data/nativetest" />
+ <option name="module-name" value="libprotoutil_test" />
+ </test>
+</configuration>
diff --git a/libs/protoutil/src/EncodedBuffer.cpp b/libs/protoutil/src/EncodedBuffer.cpp
index 3a5e2e9..c017851 100644
--- a/libs/protoutil/src/EncodedBuffer.cpp
+++ b/libs/protoutil/src/EncodedBuffer.cpp
@@ -13,11 +13,13 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
+#define LOG_TAG "libprotoutil"
+
+#include <stdlib.h>
#include <android/util/EncodedBuffer.h>
#include <android/util/protobuf.h>
-
-#include <stdlib.h>
+#include <cutils/log.h>
namespace android {
namespace util {
@@ -228,7 +230,7 @@
size_t start = mEp.pos();
while (true) {
uint8_t byte = readRawByte();
- val += (byte & 0x7F) << shift;
+ val |= (UINT64_C(0x7F) & byte) << shift;
if ((byte & 0x80) == 0) break;
shift += 7;
}
@@ -345,7 +347,7 @@
uint64_t val = 0, shift = 0;
while (true) {
uint8_t byte = next();
- val += (byte & 0x7F) << shift;
+ val |= (INT64_C(0x7F) & byte) << shift;
if ((byte & 0x80) == 0) break;
shift += 7;
}
diff --git a/libs/protoutil/tests/EncodedBuffer_test.cpp b/libs/protoutil/tests/EncodedBuffer_test.cpp
new file mode 100644
index 0000000..615ab4a
--- /dev/null
+++ b/libs/protoutil/tests/EncodedBuffer_test.cpp
@@ -0,0 +1,25 @@
+// 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 <android/util/EncodedBuffer.h>
+#include <gmock/gmock.h>
+#include <gtest/gtest.h>
+
+using namespace android::util;
+
+TEST(EncodedBufferTest, ReadVarint) {
+ EncodedBuffer buffer;
+ uint64_t val = UINT64_C(1522865904593);
+ buffer.writeRawVarint64(val);
+ EXPECT_EQ(val, buffer.begin().readRawVarint());
+}
diff --git a/media/java/android/media/ExifInterface.java b/media/java/android/media/ExifInterface.java
index bc0e43b..7888436 100644
--- a/media/java/android/media/ExifInterface.java
+++ b/media/java/android/media/ExifInterface.java
@@ -66,7 +66,7 @@
/**
* This is a class for reading and writing Exif tags in a JPEG file or a RAW image file.
* <p>
- * Supported formats are: JPEG, DNG, CR2, NEF, NRW, ARW, RW2, ORF, PEF, SRW and RAF.
+ * Supported formats are: JPEG, DNG, CR2, NEF, NRW, ARW, RW2, ORF, PEF, SRW, RAF and HEIF.
* <p>
* Attribute mutation is supported for JPEG image files.
*/
@@ -2524,46 +2524,46 @@
private void getHeifAttributes(ByteOrderedDataInputStream in) throws IOException {
MediaMetadataRetriever retriever = new MediaMetadataRetriever();
try {
- if (mSeekableFileDescriptor != null) {
- retriever.setDataSource(mSeekableFileDescriptor);
- } else {
- retriever.setDataSource(new MediaDataSource() {
- long mPosition;
+ retriever.setDataSource(new MediaDataSource() {
+ long mPosition;
- @Override
- public void close() throws IOException {}
+ @Override
+ public void close() throws IOException {}
- @Override
- public int readAt(long position, byte[] buffer, int offset, int size)
- throws IOException {
- if (size == 0) {
- return 0;
- }
- if (position < 0) {
- return -1;
- }
- if (mPosition != position) {
- in.seek(position);
- mPosition = position;
- }
-
- int bytesRead = in.read(buffer, offset, size);
- if (bytesRead < 0) {
- mPosition = -1; // need to seek on next read
- return -1;
- }
-
- mPosition += bytesRead;
- return bytesRead;
+ @Override
+ public int readAt(long position, byte[] buffer, int offset, int size)
+ throws IOException {
+ if (size == 0) {
+ return 0;
}
-
- @Override
- public long getSize() throws IOException {
+ if (position < 0) {
return -1;
}
- });
- }
+ if (mPosition != position) {
+ in.seek(position);
+ mPosition = position;
+ }
+ int bytesRead = in.read(buffer, offset, size);
+ if (bytesRead < 0) {
+ mPosition = -1; // need to seek on next read
+ return -1;
+ }
+
+ mPosition += bytesRead;
+ return bytesRead;
+ }
+
+ @Override
+ public long getSize() throws IOException {
+ return -1;
+ }
+ });
+
+ String exifOffsetStr = retriever.extractMetadata(
+ MediaMetadataRetriever.METADATA_KEY_EXIF_OFFSET);
+ String exifLengthStr = retriever.extractMetadata(
+ MediaMetadataRetriever.METADATA_KEY_EXIF_LENGTH);
String hasImage = retriever.extractMetadata(
MediaMetadataRetriever.METADATA_KEY_HAS_IMAGE);
String hasVideo = retriever.extractMetadata(
@@ -2622,6 +2622,30 @@
ExifAttribute.createUShort(orientation, mExifByteOrder));
}
+ if (exifOffsetStr != null && exifLengthStr != null) {
+ int offset = Integer.parseInt(exifOffsetStr);
+ int length = Integer.parseInt(exifLengthStr);
+ if (length <= 6) {
+ throw new IOException("Invalid exif length");
+ }
+ in.seek(offset);
+ byte[] identifier = new byte[6];
+ if (in.read(identifier) != 6) {
+ throw new IOException("Can't read identifier");
+ }
+ offset += 6;
+ length -= 6;
+ if (!Arrays.equals(identifier, IDENTIFIER_EXIF_APP1)) {
+ throw new IOException("Invalid identifier");
+ }
+
+ byte[] bytes = new byte[length];
+ if (in.read(bytes) != length) {
+ throw new IOException("Can't read exif");
+ }
+ readExifSegment(bytes, IFD_TYPE_PRIMARY);
+ }
+
if (DEBUG) {
Log.d(TAG, "Heif meta: " + width + "x" + height + ", rotation " + rotation);
}
diff --git a/media/java/android/media/MediaCodecInfo.java b/media/java/android/media/MediaCodecInfo.java
index 2a601f9..c29300d 100644
--- a/media/java/android/media/MediaCodecInfo.java
+++ b/media/java/android/media/MediaCodecInfo.java
@@ -2971,6 +2971,8 @@
public static final int AACObjectLD = 23;
public static final int AACObjectHE_PS = 29;
public static final int AACObjectELD = 39;
+ /** xHE-AAC (includes USAC) */
+ public static final int AACObjectXHE = 42;
// from OMX_VIDEO_VP8LEVELTYPE
public static final int VP8Level_Version0 = 0x01;
diff --git a/media/java/android/media/MediaMetadataRetriever.java b/media/java/android/media/MediaMetadataRetriever.java
index 0955dd6..8ab5ec4 100644
--- a/media/java/android/media/MediaMetadataRetriever.java
+++ b/media/java/android/media/MediaMetadataRetriever.java
@@ -890,5 +890,14 @@
*/
public static final int METADATA_KEY_VIDEO_FRAME_COUNT = 32;
+ /**
+ * @hide
+ */
+ public static final int METADATA_KEY_EXIF_OFFSET = 33;
+
+ /**
+ * @hide
+ */
+ public static final int METADATA_KEY_EXIF_LENGTH = 34;
// Add more here...
}
diff --git a/media/java/android/media/MediaPlayer.java b/media/java/android/media/MediaPlayer.java
index aef31b1..f9a1f8b 100644
--- a/media/java/android/media/MediaPlayer.java
+++ b/media/java/android/media/MediaPlayer.java
@@ -2128,7 +2128,13 @@
mTimeProvider.close();
mTimeProvider = null;
}
- mOnSubtitleDataListener = null;
+ synchronized(this) {
+ mSubtitleDataListenerDisabled = false;
+ mExtSubtitleDataListener = null;
+ mExtSubtitleDataHandler = null;
+ mOnMediaTimeDiscontinuityListener = null;
+ mOnMediaTimeDiscontinuityHandler = null;
+ }
// Modular DRM clean up
mOnDrmConfigHelper = null;
@@ -2699,7 +2705,7 @@
private int mSelectedSubtitleTrackIndex = -1;
private Vector<InputStream> mOpenSubtitleSources;
- private OnSubtitleDataListener mSubtitleDataListener = new OnSubtitleDataListener() {
+ private final OnSubtitleDataListener mIntSubtitleDataListener = new OnSubtitleDataListener() {
@Override
public void onSubtitleData(MediaPlayer mp, SubtitleData data) {
int index = data.getTrackIndex();
@@ -2725,7 +2731,9 @@
}
mSelectedSubtitleTrackIndex = -1;
}
- setOnSubtitleDataListener(null);
+ synchronized (this) {
+ mSubtitleDataListenerDisabled = true;
+ }
if (track == null) {
return;
}
@@ -2745,7 +2753,9 @@
selectOrDeselectInbandTrack(mSelectedSubtitleTrackIndex, true);
} catch (IllegalStateException e) {
}
- setOnSubtitleDataListener(mSubtitleDataListener);
+ synchronized (this) {
+ mSubtitleDataListenerDisabled = false;
+ }
}
// no need to select out-of-band tracks
}
@@ -3304,6 +3314,7 @@
private static final int MEDIA_SUBTITLE_DATA = 201;
private static final int MEDIA_META_DATA = 202;
private static final int MEDIA_DRM_INFO = 210;
+ private static final int MEDIA_TIME_DISCONTINUITY = 211;
private static final int MEDIA_AUDIO_ROUTING_CHANGED = 10000;
private TimeProvider mTimeProvider;
@@ -3514,15 +3525,34 @@
return;
case MEDIA_SUBTITLE_DATA:
- OnSubtitleDataListener onSubtitleDataListener = mOnSubtitleDataListener;
- if (onSubtitleDataListener == null) {
- return;
+ final OnSubtitleDataListener extSubtitleListener;
+ final Handler extSubtitleHandler;
+ synchronized(this) {
+ if (mSubtitleDataListenerDisabled) {
+ return;
+ }
+ extSubtitleListener = mExtSubtitleDataListener;
+ extSubtitleHandler = mExtSubtitleDataHandler;
}
if (msg.obj instanceof Parcel) {
Parcel parcel = (Parcel) msg.obj;
- SubtitleData data = new SubtitleData(parcel);
+ final SubtitleData data = new SubtitleData(parcel);
parcel.recycle();
- onSubtitleDataListener.onSubtitleData(mMediaPlayer, data);
+
+ mIntSubtitleDataListener.onSubtitleData(mMediaPlayer, data);
+
+ if (extSubtitleListener != null) {
+ if (extSubtitleHandler == null) {
+ extSubtitleListener.onSubtitleData(mMediaPlayer, data);
+ } else {
+ extSubtitleHandler.post(new Runnable() {
+ @Override
+ public void run() {
+ extSubtitleListener.onSubtitleData(mMediaPlayer, data);
+ }
+ });
+ }
+ }
}
return;
@@ -3553,6 +3583,43 @@
}
return;
+ case MEDIA_TIME_DISCONTINUITY:
+ final OnMediaTimeDiscontinuityListener mediaTimeListener;
+ final Handler mediaTimeHandler;
+ synchronized(this) {
+ mediaTimeListener = mOnMediaTimeDiscontinuityListener;
+ mediaTimeHandler = mOnMediaTimeDiscontinuityHandler;
+ }
+ if (mediaTimeListener == null) {
+ return;
+ }
+ if (msg.obj instanceof Parcel) {
+ Parcel parcel = (Parcel) msg.obj;
+ parcel.setDataPosition(0);
+ long anchorMediaUs = parcel.readLong();
+ long anchorRealUs = parcel.readLong();
+ float playbackRate = parcel.readFloat();
+ parcel.recycle();
+ final MediaTimestamp timestamp;
+ if (anchorMediaUs != -1 && anchorRealUs != -1) {
+ timestamp = new MediaTimestamp(
+ anchorMediaUs /*Us*/, anchorRealUs * 1000 /*Ns*/, playbackRate);
+ } else {
+ timestamp = MediaTimestamp.TIMESTAMP_UNKNOWN;
+ }
+ if (mediaTimeHandler == null) {
+ mediaTimeListener.onMediaTimeDiscontinuity(mMediaPlayer, timestamp);
+ } else {
+ mediaTimeHandler.post(new Runnable() {
+ @Override
+ public void run() {
+ mediaTimeListener.onMediaTimeDiscontinuity(mMediaPlayer, timestamp);
+ }
+ });
+ }
+ }
+ return;
+
default:
Log.e(TAG, "Unknown message type " + msg.what);
return;
@@ -3877,13 +3944,15 @@
private void setOnSubtitleDataListenerInt(
@Nullable OnSubtitleDataListener listener, @Nullable Handler handler) {
synchronized (this) {
- mOnSubtitleDataListener = listener;
- mOnSubtitleDataHandler = handler;
+ mExtSubtitleDataListener = listener;
+ mExtSubtitleDataHandler = handler;
}
}
- private OnSubtitleDataListener mOnSubtitleDataListener;
- private Handler mOnSubtitleDataHandler;
+ private boolean mSubtitleDataListenerDisabled;
+ /** External OnSubtitleDataListener, the one set by {@link #setOnSubtitleDataListener}. */
+ private OnSubtitleDataListener mExtSubtitleDataListener;
+ private Handler mExtSubtitleDataHandler;
/**
* Interface definition of a callback to be invoked when discontinuity in the normal progression
diff --git a/media/java/android/media/MediaTimestamp.java b/media/java/android/media/MediaTimestamp.java
index 938dd14..dd43b4e 100644
--- a/media/java/android/media/MediaTimestamp.java
+++ b/media/java/android/media/MediaTimestamp.java
@@ -98,4 +98,13 @@
&& (this.nanoTime == that.nanoTime)
&& (this.clockRate == that.clockRate);
}
+
+ @Override
+ public String toString() {
+ return getClass().getName()
+ + "{AnchorMediaTimeUs=" + mediaTimeUs
+ + " AnchorSystemNanoTime=" + nanoTime
+ + " clockRate=" + clockRate
+ + "}";
+ }
}
diff --git a/media/java/android/media/audiofx/AudioEffect.java b/media/java/android/media/audiofx/AudioEffect.java
index 21d6873..1cb4d67 100644
--- a/media/java/android/media/audiofx/AudioEffect.java
+++ b/media/java/android/media/audiofx/AudioEffect.java
@@ -18,6 +18,7 @@
import android.annotation.SdkConstant;
import android.annotation.SdkConstant.SdkConstantType;
+import android.annotation.TestApi;
import android.app.ActivityThread;
import android.os.Handler;
import android.os.Looper;
@@ -133,9 +134,10 @@
.fromString("7261676f-6d75-7369-6364-28e2fd3ac39e");
/**
- * Null effect UUID. Used when the UUID for effect type of
+ * Null effect UUID. See {@link AudioEffect(UUID, UUID, int, int)} for use.
* @hide
*/
+ @TestApi
public static final UUID EFFECT_TYPE_NULL = UUID
.fromString("ec7178ec-e5e1-4432-a3f4-4657e6795210");
diff --git a/media/java/android/media/session/MediaController.java b/media/java/android/media/session/MediaController.java
index f16804c..84f85e7 100644
--- a/media/java/android/media/session/MediaController.java
+++ b/media/java/android/media/session/MediaController.java
@@ -531,7 +531,7 @@
*
* @param state The new playback state of the session
*/
- public void onPlaybackStateChanged(@NonNull PlaybackState state) {
+ public void onPlaybackStateChanged(@Nullable PlaybackState state) {
}
/**
diff --git a/media/java/android/media/session/MediaSessionManager.java b/media/java/android/media/session/MediaSessionManager.java
index 519af1b..fbc1438 100644
--- a/media/java/android/media/session/MediaSessionManager.java
+++ b/media/java/android/media/session/MediaSessionManager.java
@@ -47,6 +47,7 @@
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
+import java.util.Objects;
import java.util.concurrent.Executor;
/**
@@ -342,12 +343,16 @@
}
/**
- * Returns whether the app is trusted.
+ * Checks whether the remote user is a trusted app.
* <p>
* An app is trusted if the app holds the android.Manifest.permission.MEDIA_CONTENT_CONTROL
* permission or has an enabled notification listener.
*
- * @param userInfo The remote user info
+ * @param userInfo The remote user info from either
+ * {@link MediaSession#getCurrentControllerInfo()} or
+ * {@link MediaBrowserService#getCurrentBrowserInfo()}.
+ * @return {@code true} if the remote user is trusted and its package name matches with the UID.
+ * {@code false} otherwise.
*/
public boolean isTrustedForMediaControl(RemoteUserInfo userInfo) {
if (userInfo.getPackageName() == null) {
@@ -814,6 +819,11 @@
&& mPid == otherUserInfo.mPid
&& mUid == otherUserInfo.mUid;
}
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(mPackageName, mPid, mUid);
+ }
}
private static final class SessionsChangedWrapper {
diff --git a/packages/SettingsLib/res/values-as/strings.xml b/packages/SettingsLib/res/values-as/strings.xml
index 763a0eb..0c617ba 100644
--- a/packages/SettingsLib/res/values-as/strings.xml
+++ b/packages/SettingsLib/res/values-as/strings.xml
@@ -206,8 +206,7 @@
<string name="keep_screen_on" msgid="1146389631208760344">"জাগ্ৰত কৰি ৰাখক"</string>
<string name="keep_screen_on_summary" msgid="2173114350754293009">"চ্চাৰ্জ হৈ থকাৰ সময়ত স্ক্ৰীণ কেতিয়াও সুপ্ত অৱস্থালৈ নাযায়"</string>
<string name="bt_hci_snoop_log" msgid="3340699311158865670">"ব্লুটুথ HCI স্নুপ ল’গ সক্ষম কৰক"</string>
- <!-- no translation found for bt_hci_snoop_log_summary (366083475849911315) -->
- <skip />
+ <string name="bt_hci_snoop_log_summary" msgid="366083475849911315">"সকলো ব্লুটুথ HCI পেকেটক কোনো ফাইলত অন্তৰ্ভুক্ত কৰক (এই ছেটিং সলনি কৰাৰ পিছত ব্লুটুথ ট\'গল কৰক)"</string>
<string name="oem_unlock_enable" msgid="6040763321967327691">"ঔইএম আনলক"</string>
<string name="oem_unlock_enable_summary" msgid="4720281828891618376">"বুটল\'ডাৰটো আনলক কৰিবলৈ অনুমতি দিয়ক"</string>
<string name="confirm_enable_oem_unlock_title" msgid="4802157344812385674">"ঔইএম আনলক কৰাৰ অনুমতি দিবনে?"</string>
diff --git a/packages/SettingsLib/res/values-be/strings.xml b/packages/SettingsLib/res/values-be/strings.xml
index ee54231..faa7eb0 100644
--- a/packages/SettingsLib/res/values-be/strings.xml
+++ b/packages/SettingsLib/res/values-be/strings.xml
@@ -40,10 +40,8 @@
<string name="connected_via_passpoint" msgid="2826205693803088747">"Падлучана праз %1$s"</string>
<string name="available_via_passpoint" msgid="1617440946846329613">"Даступна праз %1$s"</string>
<string name="wifi_connected_no_internet" msgid="8202906332837777829">"Падключана, без доступу да інтэрнэту"</string>
- <!-- no translation found for wifi_status_no_internet (5784710974669608361) -->
- <skip />
- <!-- no translation found for wifi_status_sign_in_required (123517180404752756) -->
- <skip />
+ <string name="wifi_status_no_internet" msgid="5784710974669608361">"Не падключана да інтэрнэту"</string>
+ <string name="wifi_status_sign_in_required" msgid="123517180404752756">"Трэба выканаць уваход"</string>
<string name="wifi_ap_unable_to_handle_new_sta" msgid="5348824313514404541">"Пункт доступу часова заняты"</string>
<string name="connected_via_carrier" msgid="7583780074526041912">"Падлучана праз %1$s"</string>
<string name="available_via_carrier" msgid="1469036129740799053">"Даступна праз %1$s"</string>
@@ -67,12 +65,9 @@
<string name="bluetooth_connected_no_headset_battery_level" msgid="1610296229139400266">"Падключана прылада <xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g> (без званкоў). Узровень зараду яе акумулятара: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
<string name="bluetooth_connected_no_a2dp_battery_level" msgid="3908466636369853652">"Падключана прылада <xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g> (без аўдыя). Узровень зараду яе акумулятара: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
<string name="bluetooth_connected_no_headset_no_a2dp_battery_level" msgid="1163440823807659316">"Падключана прылада <xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g> (без званкоў і аўдыя). Узровень зараду яе акумулятара: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
- <!-- no translation found for bluetooth_active_battery_level (3149689299296462009) -->
- <skip />
- <!-- no translation found for bluetooth_battery_level (1447164613319663655) -->
- <skip />
- <!-- no translation found for bluetooth_active_no_battery_level (8380223546730241956) -->
- <skip />
+ <string name="bluetooth_active_battery_level" msgid="3149689299296462009">"Уключана, зарад <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
+ <string name="bluetooth_battery_level" msgid="1447164613319663655">"Узровень зараду: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
+ <string name="bluetooth_active_no_battery_level" msgid="8380223546730241956">"Уключана"</string>
<string name="bluetooth_profile_a2dp" msgid="2031475486179830674">"Аўдыё медыяпрылады"</string>
<string name="bluetooth_profile_headset" msgid="7815495680863246034">"Тэлефонныя выклікі"</string>
<string name="bluetooth_profile_opp" msgid="9168139293654233697">"Перадача файлаў"</string>
@@ -119,14 +114,10 @@
<string name="bluetooth_talkback_headphone" msgid="26580326066627664">"Навушнікі"</string>
<string name="bluetooth_talkback_input_peripheral" msgid="5165842622743212268">"Перыферыйная прылада ўводу"</string>
<string name="bluetooth_talkback_bluetooth" msgid="5615463912185280812">"Bluetooth"</string>
- <!-- no translation found for bluetooth_hearingaid_left_pairing_message (7378813500862148102) -->
- <skip />
- <!-- no translation found for bluetooth_hearingaid_right_pairing_message (1550373802309160891) -->
- <skip />
- <!-- no translation found for bluetooth_hearingaid_left_battery_level (8797811465352097562) -->
- <skip />
- <!-- no translation found for bluetooth_hearingaid_right_battery_level (7309476148173459677) -->
- <skip />
+ <string name="bluetooth_hearingaid_left_pairing_message" msgid="7378813500862148102">"Спалучаецца левы навушнік…"</string>
+ <string name="bluetooth_hearingaid_right_pairing_message" msgid="1550373802309160891">"Спалучаецца правы навушнік…"</string>
+ <string name="bluetooth_hearingaid_left_battery_level" msgid="8797811465352097562">"Левы – узровень зараду <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
+ <string name="bluetooth_hearingaid_right_battery_level" msgid="7309476148173459677">"Правы – узровень зараду <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
<string name="accessibility_wifi_off" msgid="1166761729660614716">"Wi-Fi выключаны."</string>
<string name="accessibility_no_wifi" msgid="8834610636137374508">"Wi-Fi адлучаны."</string>
<string name="accessibility_wifi_one_bar" msgid="4869376278894301820">"Адзiн слупок Wi-Fi."</string>
@@ -246,15 +237,12 @@
<string name="private_dns_mode_opportunistic" msgid="8314986739896927399">"Аўтаматычна"</string>
<string name="private_dns_mode_provider" msgid="8354935160639360804">"Імя вузла аператара прыватнай DNS"</string>
<string name="private_dns_mode_provider_hostname_hint" msgid="2487492386970928143">"Увядзіце імя вузла аператара DNS"</string>
- <!-- no translation found for private_dns_mode_provider_failure (231837290365031223) -->
- <skip />
+ <string name="private_dns_mode_provider_failure" msgid="231837290365031223">"Не атрымалася падключыцца"</string>
<string name="wifi_display_certification_summary" msgid="1155182309166746973">"Паказаць опцыі сертыфікацыі бесправаднога дысплея"</string>
<string name="wifi_verbose_logging_summary" msgid="6615071616111731958">"Падвыс. узровень дэтал-цыі журнала Wi‑Fi у залежн. ад SSID RSSI у Wi‑Fi Picker"</string>
<string name="wifi_connected_mac_randomization_summary" msgid="1743059848752201485">"Генерыраваць выпадковы MAC-адрас пры падключэнні да сетак Wi‑Fi"</string>
- <!-- no translation found for wifi_metered_label (4514924227256839725) -->
- <skip />
- <!-- no translation found for wifi_unmetered_label (6124098729457992931) -->
- <skip />
+ <string name="wifi_metered_label" msgid="4514924227256839725">"З улікам трафіка"</string>
+ <string name="wifi_unmetered_label" msgid="6124098729457992931">"Без уліку трафіка"</string>
<string name="select_logd_size_title" msgid="7433137108348553508">"Памеры буфера для сродку вядзення журнала"</string>
<string name="select_logd_size_dialog_title" msgid="1206769310236476760">"Выберыце памеры сродку вядзення журнала для буфераў журнала"</string>
<string name="dev_logpersist_clear_warning_title" msgid="684806692440237967">"Ачысціць пастаяннае сховішча журнала?"</string>
diff --git a/packages/SettingsLib/res/values-bn/strings.xml b/packages/SettingsLib/res/values-bn/strings.xml
index 35f82e5..7f3c954 100644
--- a/packages/SettingsLib/res/values-bn/strings.xml
+++ b/packages/SettingsLib/res/values-bn/strings.xml
@@ -206,8 +206,7 @@
<string name="keep_screen_on" msgid="1146389631208760344">"জাগিয়ে রাখুন"</string>
<string name="keep_screen_on_summary" msgid="2173114350754293009">"চার্জ হওয়ার স্ক্রীন কখনই নিদ্রা মোডে যাবে না"</string>
<string name="bt_hci_snoop_log" msgid="3340699311158865670">"ব্লুটুথ HCI স্নুপ লগ সক্ষম করুন"</string>
- <!-- no translation found for bt_hci_snoop_log_summary (366083475849911315) -->
- <skip />
+ <string name="bt_hci_snoop_log_summary" msgid="366083475849911315">"সমস্ত ব্লুটুথ HCI প্যাকেট একটি ফাইলে ক্যাপচার করে রাখুন (এই সেটিং পরিবর্তন করার পরে ব্লুটুথ চালু অথবা বন্ধ করুন)"</string>
<string name="oem_unlock_enable" msgid="6040763321967327691">"OEM আনলক করা হচ্ছে"</string>
<string name="oem_unlock_enable_summary" msgid="4720281828891618376">"বুট-লোডার আনলক করার অনুমতি দিন"</string>
<string name="confirm_enable_oem_unlock_title" msgid="4802157344812385674">"OEM আনলক করার অনুমতি দিতে চান?"</string>
diff --git a/packages/SettingsLib/res/values-bs/strings.xml b/packages/SettingsLib/res/values-bs/strings.xml
index 3e51f16..db563b5 100644
--- a/packages/SettingsLib/res/values-bs/strings.xml
+++ b/packages/SettingsLib/res/values-bs/strings.xml
@@ -242,7 +242,7 @@
<string name="wifi_verbose_logging_summary" msgid="6615071616111731958">"Povećajte nivo Wi-Fi zapisivanja, pokazati po SSID RSSI Wi-Fi Picker"</string>
<string name="wifi_connected_mac_randomization_summary" msgid="1743059848752201485">"Nasumično odaberi MAC adresu prilikom povezivanja na Wi-Fi mreže"</string>
<string name="wifi_metered_label" msgid="4514924227256839725">"S naplatom"</string>
- <string name="wifi_unmetered_label" msgid="6124098729457992931">"Mreža bez ograničenja"</string>
+ <string name="wifi_unmetered_label" msgid="6124098729457992931">"Mreža bez ograničenja prometa"</string>
<string name="select_logd_size_title" msgid="7433137108348553508">"Veličine bafera za zapisnik"</string>
<string name="select_logd_size_dialog_title" msgid="1206769310236476760">"Odaberite veličine za Logger prema međumemoriji evidencije"</string>
<string name="dev_logpersist_clear_warning_title" msgid="684806692440237967">"Želite li izbrisati trajnu pohranu zapisivača?"</string>
diff --git a/packages/SettingsLib/res/values-da/strings.xml b/packages/SettingsLib/res/values-da/strings.xml
index 7a693b5..8c353f4 100644
--- a/packages/SettingsLib/res/values-da/strings.xml
+++ b/packages/SettingsLib/res/values-da/strings.xml
@@ -40,10 +40,8 @@
<string name="connected_via_passpoint" msgid="2826205693803088747">"Tilsluttet via %1$s"</string>
<string name="available_via_passpoint" msgid="1617440946846329613">"Tilgængelig via %1$s"</string>
<string name="wifi_connected_no_internet" msgid="8202906332837777829">"Tilsluttet – intet internet"</string>
- <!-- no translation found for wifi_status_no_internet (5784710974669608361) -->
- <skip />
- <!-- no translation found for wifi_status_sign_in_required (123517180404752756) -->
- <skip />
+ <string name="wifi_status_no_internet" msgid="5784710974669608361">"Intet internet"</string>
+ <string name="wifi_status_sign_in_required" msgid="123517180404752756">"Login er påkrævet"</string>
<string name="wifi_ap_unable_to_handle_new_sta" msgid="5348824313514404541">"Adgangspunktet er midlertidigt fuldt"</string>
<string name="connected_via_carrier" msgid="7583780074526041912">"Tilsluttet via %1$s"</string>
<string name="available_via_carrier" msgid="1469036129740799053">"Tilgængelig via %1$s"</string>
@@ -67,12 +65,9 @@
<string name="bluetooth_connected_no_headset_battery_level" msgid="1610296229139400266">"Tilsluttet <xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g> (ingen telefon) – batteriniveau <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
<string name="bluetooth_connected_no_a2dp_battery_level" msgid="3908466636369853652">"Tilsluttet <xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g> (ingen medier) – batteriniveau <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
<string name="bluetooth_connected_no_headset_no_a2dp_battery_level" msgid="1163440823807659316">"Tilsluttet <xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g> (ingen telefon eller medier) – batteriniveau <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
- <!-- no translation found for bluetooth_active_battery_level (3149689299296462009) -->
- <skip />
- <!-- no translation found for bluetooth_battery_level (1447164613319663655) -->
- <skip />
- <!-- no translation found for bluetooth_active_no_battery_level (8380223546730241956) -->
- <skip />
+ <string name="bluetooth_active_battery_level" msgid="3149689299296462009">"Aktiv, <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> batteri"</string>
+ <string name="bluetooth_battery_level" msgid="1447164613319663655">"<xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> batteri"</string>
+ <string name="bluetooth_active_no_battery_level" msgid="8380223546730241956">"Aktiv"</string>
<string name="bluetooth_profile_a2dp" msgid="2031475486179830674">"Medielyd"</string>
<string name="bluetooth_profile_headset" msgid="7815495680863246034">"Telefonopkald"</string>
<string name="bluetooth_profile_opp" msgid="9168139293654233697">"Filoverførsel"</string>
@@ -119,14 +114,10 @@
<string name="bluetooth_talkback_headphone" msgid="26580326066627664">"Hovedtelefoner"</string>
<string name="bluetooth_talkback_input_peripheral" msgid="5165842622743212268">"Eksterne inputenheder"</string>
<string name="bluetooth_talkback_bluetooth" msgid="5615463912185280812">"Bluetooth"</string>
- <!-- no translation found for bluetooth_hearingaid_left_pairing_message (7378813500862148102) -->
- <skip />
- <!-- no translation found for bluetooth_hearingaid_right_pairing_message (1550373802309160891) -->
- <skip />
- <!-- no translation found for bluetooth_hearingaid_left_battery_level (8797811465352097562) -->
- <skip />
- <!-- no translation found for bluetooth_hearingaid_right_battery_level (7309476148173459677) -->
- <skip />
+ <string name="bluetooth_hearingaid_left_pairing_message" msgid="7378813500862148102">"Parrer venstre høreapparat…"</string>
+ <string name="bluetooth_hearingaid_right_pairing_message" msgid="1550373802309160891">"Parrer højre høreapparat…"</string>
+ <string name="bluetooth_hearingaid_left_battery_level" msgid="8797811465352097562">"Venstre – <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> batteri"</string>
+ <string name="bluetooth_hearingaid_right_battery_level" msgid="7309476148173459677">"Højre – <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> batteri"</string>
<string name="accessibility_wifi_off" msgid="1166761729660614716">"Wi-Fi er slået fra."</string>
<string name="accessibility_no_wifi" msgid="8834610636137374508">"Wi-Fi er afbrudt."</string>
<string name="accessibility_wifi_one_bar" msgid="4869376278894301820">"Wi-Fi har én bjælke."</string>
@@ -246,15 +237,12 @@
<string name="private_dns_mode_opportunistic" msgid="8314986739896927399">"Automatisk"</string>
<string name="private_dns_mode_provider" msgid="8354935160639360804">"Hostname for privat DNS-udbyder"</string>
<string name="private_dns_mode_provider_hostname_hint" msgid="2487492386970928143">"Angiv hostname for DNS-udbyder"</string>
- <!-- no translation found for private_dns_mode_provider_failure (231837290365031223) -->
- <skip />
+ <string name="private_dns_mode_provider_failure" msgid="231837290365031223">"Der kunne ikke oprettes forbindelse"</string>
<string name="wifi_display_certification_summary" msgid="1155182309166746973">"Vis valgmuligheder for certificering af trådløs skærm"</string>
<string name="wifi_verbose_logging_summary" msgid="6615071616111731958">"Øg mængden af Wi‑Fi-logføring. Vis opdelt efter SSID RSSI i Wi‑Fi-vælgeren"</string>
<string name="wifi_connected_mac_randomization_summary" msgid="1743059848752201485">"Brug en tilfældig MAC-adresse, når der oprettes forbindelse til Wi‑Fi-netværk"</string>
- <!-- no translation found for wifi_metered_label (4514924227256839725) -->
- <skip />
- <!-- no translation found for wifi_unmetered_label (6124098729457992931) -->
- <skip />
+ <string name="wifi_metered_label" msgid="4514924227256839725">"Forbrugsafregnet"</string>
+ <string name="wifi_unmetered_label" msgid="6124098729457992931">"Ikke forbrugsafregnet"</string>
<string name="select_logd_size_title" msgid="7433137108348553508">"Størrelser for Logger-buffer"</string>
<string name="select_logd_size_dialog_title" msgid="1206769310236476760">"Vælg Logger-størrelser pr. logbuffer"</string>
<string name="dev_logpersist_clear_warning_title" msgid="684806692440237967">"Vil du rydde det permanente lager for logger?"</string>
diff --git a/packages/SettingsLib/res/values-de/strings.xml b/packages/SettingsLib/res/values-de/strings.xml
index b7eb02a..90a63d9 100644
--- a/packages/SettingsLib/res/values-de/strings.xml
+++ b/packages/SettingsLib/res/values-de/strings.xml
@@ -40,10 +40,8 @@
<string name="connected_via_passpoint" msgid="2826205693803088747">"Über %1$s verbunden"</string>
<string name="available_via_passpoint" msgid="1617440946846329613">"Verfügbar über %1$s"</string>
<string name="wifi_connected_no_internet" msgid="8202906332837777829">"Verbunden, kein Internet"</string>
- <!-- no translation found for wifi_status_no_internet (5784710974669608361) -->
- <skip />
- <!-- no translation found for wifi_status_sign_in_required (123517180404752756) -->
- <skip />
+ <string name="wifi_status_no_internet" msgid="5784710974669608361">"Kein Internet"</string>
+ <string name="wifi_status_sign_in_required" msgid="123517180404752756">"Anmeldung erforderlich"</string>
<string name="wifi_ap_unable_to_handle_new_sta" msgid="5348824313514404541">"Zugangspunkt vorübergehend voll belegt"</string>
<string name="connected_via_carrier" msgid="7583780074526041912">"Über %1$s verbunden"</string>
<string name="available_via_carrier" msgid="1469036129740799053">"Verfügbar über %1$s"</string>
@@ -67,12 +65,9 @@
<string name="bluetooth_connected_no_headset_battery_level" msgid="1610296229139400266">"Mit <xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g> verbunden (kein Telefon-Audio), Akkustand bei <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
<string name="bluetooth_connected_no_a2dp_battery_level" msgid="3908466636369853652">"Mit <xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g> verbunden (kein Medien-Audio), Akkustand bei <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
<string name="bluetooth_connected_no_headset_no_a2dp_battery_level" msgid="1163440823807659316">"Mit <xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g> verbunden (weder Telefon- noch Medien-Audio), Akkustand bei <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
- <!-- no translation found for bluetooth_active_battery_level (3149689299296462009) -->
- <skip />
- <!-- no translation found for bluetooth_battery_level (1447164613319663655) -->
- <skip />
- <!-- no translation found for bluetooth_active_no_battery_level (8380223546730241956) -->
- <skip />
+ <string name="bluetooth_active_battery_level" msgid="3149689299296462009">"Aktiv, Akkustand: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
+ <string name="bluetooth_battery_level" msgid="1447164613319663655">"Akkustand: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
+ <string name="bluetooth_active_no_battery_level" msgid="8380223546730241956">"Aktiv"</string>
<string name="bluetooth_profile_a2dp" msgid="2031475486179830674">"Medien-Audio"</string>
<string name="bluetooth_profile_headset" msgid="7815495680863246034">"Telefonanrufe"</string>
<string name="bluetooth_profile_opp" msgid="9168139293654233697">"Dateiübertragung"</string>
@@ -119,14 +114,10 @@
<string name="bluetooth_talkback_headphone" msgid="26580326066627664">"Kopfhörer"</string>
<string name="bluetooth_talkback_input_peripheral" msgid="5165842622743212268">"Eingabeperipherie"</string>
<string name="bluetooth_talkback_bluetooth" msgid="5615463912185280812">"Bluetooth"</string>
- <!-- no translation found for bluetooth_hearingaid_left_pairing_message (7378813500862148102) -->
- <skip />
- <!-- no translation found for bluetooth_hearingaid_right_pairing_message (1550373802309160891) -->
- <skip />
- <!-- no translation found for bluetooth_hearingaid_left_battery_level (8797811465352097562) -->
- <skip />
- <!-- no translation found for bluetooth_hearingaid_right_battery_level (7309476148173459677) -->
- <skip />
+ <string name="bluetooth_hearingaid_left_pairing_message" msgid="7378813500862148102">"Linke Hörhilfe wird gekoppelt…"</string>
+ <string name="bluetooth_hearingaid_right_pairing_message" msgid="1550373802309160891">"Rechte Hörhilfe wird gekoppelt…"</string>
+ <string name="bluetooth_hearingaid_left_battery_level" msgid="8797811465352097562">"Links, Akkustand: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
+ <string name="bluetooth_hearingaid_right_battery_level" msgid="7309476148173459677">"Rechts, Akkustand: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
<string name="accessibility_wifi_off" msgid="1166761729660614716">"WLAN: aus"</string>
<string name="accessibility_no_wifi" msgid="8834610636137374508">"WLAN getrennt"</string>
<string name="accessibility_wifi_one_bar" msgid="4869376278894301820">"WLAN: ein Balken"</string>
@@ -246,15 +237,12 @@
<string name="private_dns_mode_opportunistic" msgid="8314986739896927399">"Automatisch"</string>
<string name="private_dns_mode_provider" msgid="8354935160639360804">"Hostname des privaten DNS-Anbieters"</string>
<string name="private_dns_mode_provider_hostname_hint" msgid="2487492386970928143">"Hostname des DNS-Anbieters eingeben"</string>
- <!-- no translation found for private_dns_mode_provider_failure (231837290365031223) -->
- <skip />
+ <string name="private_dns_mode_provider_failure" msgid="231837290365031223">"Verbindung nicht möglich"</string>
<string name="wifi_display_certification_summary" msgid="1155182309166746973">"Optionen zur Zertifizierung für kabellose Übertragung anzeigen"</string>
<string name="wifi_verbose_logging_summary" msgid="6615071616111731958">"Level für WLAN-Protokollierung erhöhen, in WiFi Picker pro SSID-RSSI anzeigen"</string>
<string name="wifi_connected_mac_randomization_summary" msgid="1743059848752201485">"MAC-Adresse randomisieren, wenn WLAN-Verbindungen hergestellt werden"</string>
- <!-- no translation found for wifi_metered_label (4514924227256839725) -->
- <skip />
- <!-- no translation found for wifi_unmetered_label (6124098729457992931) -->
- <skip />
+ <string name="wifi_metered_label" msgid="4514924227256839725">"Kostenpflichtig"</string>
+ <string name="wifi_unmetered_label" msgid="6124098729457992931">"Nicht kostenpflichtig"</string>
<string name="select_logd_size_title" msgid="7433137108348553508">"Logger-Puffergrößen"</string>
<string name="select_logd_size_dialog_title" msgid="1206769310236476760">"Größe pro Protokollpuffer wählen"</string>
<string name="dev_logpersist_clear_warning_title" msgid="684806692440237967">"Speicher der dauerhaften Protokollierung löschen?"</string>
diff --git a/packages/SettingsLib/res/values-es-rUS/strings.xml b/packages/SettingsLib/res/values-es-rUS/strings.xml
index 662ecda..952e874 100644
--- a/packages/SettingsLib/res/values-es-rUS/strings.xml
+++ b/packages/SettingsLib/res/values-es-rUS/strings.xml
@@ -40,10 +40,8 @@
<string name="connected_via_passpoint" msgid="2826205693803088747">"Conexión a través de %1$s"</string>
<string name="available_via_passpoint" msgid="1617440946846329613">"Disponible a través de %1$s"</string>
<string name="wifi_connected_no_internet" msgid="8202906332837777829">"Conectado pero sin conexión a Internet"</string>
- <!-- no translation found for wifi_status_no_internet (5784710974669608361) -->
- <skip />
- <!-- no translation found for wifi_status_sign_in_required (123517180404752756) -->
- <skip />
+ <string name="wifi_status_no_internet" msgid="5784710974669608361">"Sin Internet"</string>
+ <string name="wifi_status_sign_in_required" msgid="123517180404752756">"Acceso obligatorio"</string>
<string name="wifi_ap_unable_to_handle_new_sta" msgid="5348824313514404541">"El punto de acceso está completo temporalmente"</string>
<string name="connected_via_carrier" msgid="7583780074526041912">"Conexión a través de %1$s"</string>
<string name="available_via_carrier" msgid="1469036129740799053">"Disponible a través de %1$s"</string>
@@ -67,12 +65,9 @@
<string name="bluetooth_connected_no_headset_battery_level" msgid="1610296229139400266">"Conectado (sin teléfono) a <xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g> (<xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> de batería)"</string>
<string name="bluetooth_connected_no_a2dp_battery_level" msgid="3908466636369853652">"Conectado (sin archivos multimedia) a <xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g> (<xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> de batería)"</string>
<string name="bluetooth_connected_no_headset_no_a2dp_battery_level" msgid="1163440823807659316">"Conectado (sin teléfono ni archivos multimedia) a <xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g> (<xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> de batería)"</string>
- <!-- no translation found for bluetooth_active_battery_level (3149689299296462009) -->
- <skip />
- <!-- no translation found for bluetooth_battery_level (1447164613319663655) -->
- <skip />
- <!-- no translation found for bluetooth_active_no_battery_level (8380223546730241956) -->
- <skip />
+ <string name="bluetooth_active_battery_level" msgid="3149689299296462009">"Activado (batería: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>)"</string>
+ <string name="bluetooth_battery_level" msgid="1447164613319663655">"<xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> de batería"</string>
+ <string name="bluetooth_active_no_battery_level" msgid="8380223546730241956">"Activado"</string>
<string name="bluetooth_profile_a2dp" msgid="2031475486179830674">"Audio multimedia"</string>
<string name="bluetooth_profile_headset" msgid="7815495680863246034">"Llamadas telefónicas"</string>
<string name="bluetooth_profile_opp" msgid="9168139293654233697">"Transferencia de archivos"</string>
@@ -119,14 +114,10 @@
<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>
- <!-- no translation found for bluetooth_hearingaid_left_pairing_message (7378813500862148102) -->
- <skip />
- <!-- no translation found for bluetooth_hearingaid_right_pairing_message (1550373802309160891) -->
- <skip />
- <!-- no translation found for bluetooth_hearingaid_left_battery_level (8797811465352097562) -->
- <skip />
- <!-- no translation found for bluetooth_hearingaid_right_battery_level (7309476148173459677) -->
- <skip />
+ <string name="bluetooth_hearingaid_left_pairing_message" msgid="7378813500862148102">"Sincronizando el audífono izquierdo…"</string>
+ <string name="bluetooth_hearingaid_right_pairing_message" msgid="1550373802309160891">"Sincronizando el audífono derecho…"</string>
+ <string name="bluetooth_hearingaid_left_battery_level" msgid="8797811465352097562">"Izquierdo (batería: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>)"</string>
+ <string name="bluetooth_hearingaid_right_battery_level" msgid="7309476148173459677">"Derecho (batería: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>)"</string>
<string name="accessibility_wifi_off" msgid="1166761729660614716">"Wi-Fi inhabilitado"</string>
<string name="accessibility_no_wifi" msgid="8834610636137374508">"Wi-Fi desconectado"</string>
<string name="accessibility_wifi_one_bar" msgid="4869376278894301820">"Una barra de Wi-Fi"</string>
@@ -246,15 +237,12 @@
<string name="private_dns_mode_opportunistic" msgid="8314986739896927399">"Automático"</string>
<string name="private_dns_mode_provider" msgid="8354935160639360804">"Nombre de host del proveedor de DNS privado"</string>
<string name="private_dns_mode_provider_hostname_hint" msgid="2487492386970928143">"Ingresa el nombre de host del proveedor de DNS"</string>
- <!-- no translation found for private_dns_mode_provider_failure (231837290365031223) -->
- <skip />
+ <string name="private_dns_mode_provider_failure" msgid="231837290365031223">"No se pudo establecer conexión"</string>
<string name="wifi_display_certification_summary" msgid="1155182309166746973">"Mostrar opciones de certificación de pantalla inalámbrica"</string>
<string name="wifi_verbose_logging_summary" msgid="6615071616111731958">"Aumentar nivel de registro Wi-Fi; mostrar por SSID RSSI en el selector de Wi-Fi"</string>
<string name="wifi_connected_mac_randomization_summary" msgid="1743059848752201485">"Seleccionar la dirección MAC de forma aleatoria cuando se establezca conexión con redes Wi-Fi"</string>
- <!-- no translation found for wifi_metered_label (4514924227256839725) -->
- <skip />
- <!-- no translation found for wifi_unmetered_label (6124098729457992931) -->
- <skip />
+ <string name="wifi_metered_label" msgid="4514924227256839725">"Con tarifa plana"</string>
+ <string name="wifi_unmetered_label" msgid="6124098729457992931">"Sin tarifa plana"</string>
<string name="select_logd_size_title" msgid="7433137108348553508">"Tamaños de búfer de Logger"</string>
<string name="select_logd_size_dialog_title" msgid="1206769310236476760">"Selecciona el tamaño del Logger por búfer"</string>
<string name="dev_logpersist_clear_warning_title" msgid="684806692440237967">"¿Borrar el almacenamiento persistente del registrador?"</string>
diff --git a/packages/SettingsLib/res/values-es/strings.xml b/packages/SettingsLib/res/values-es/strings.xml
index 3647f43..3d3c66e 100644
--- a/packages/SettingsLib/res/values-es/strings.xml
+++ b/packages/SettingsLib/res/values-es/strings.xml
@@ -40,10 +40,8 @@
<string name="connected_via_passpoint" msgid="2826205693803088747">"Conectado a través de %1$s"</string>
<string name="available_via_passpoint" msgid="1617440946846329613">"Disponible a través de %1$s"</string>
<string name="wifi_connected_no_internet" msgid="8202906332837777829">"Conexión sin Internet"</string>
- <!-- no translation found for wifi_status_no_internet (5784710974669608361) -->
- <skip />
- <!-- no translation found for wifi_status_sign_in_required (123517180404752756) -->
- <skip />
+ <string name="wifi_status_no_internet" msgid="5784710974669608361">"Sin Internet"</string>
+ <string name="wifi_status_sign_in_required" msgid="123517180404752756">"Debes iniciar sesión"</string>
<string name="wifi_ap_unable_to_handle_new_sta" msgid="5348824313514404541">"Punto de acceso temporalmente lleno"</string>
<string name="connected_via_carrier" msgid="7583780074526041912">"Conectado a través de %1$s"</string>
<string name="available_via_carrier" msgid="1469036129740799053">"Disponible a través de %1$s"</string>
@@ -67,12 +65,9 @@
<string name="bluetooth_connected_no_headset_battery_level" msgid="1610296229139400266">"Conectado (sin audio de teléfono) a <xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g> (<xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> de batería)"</string>
<string name="bluetooth_connected_no_a2dp_battery_level" msgid="3908466636369853652">"Conectado (sin audio multimedia) a <xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g> (<xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> de batería)"</string>
<string name="bluetooth_connected_no_headset_no_a2dp_battery_level" msgid="1163440823807659316">"Conectado (sin audio de teléfono ni multimedia) a <xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g> (<xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> de batería)"</string>
- <!-- no translation found for bluetooth_active_battery_level (3149689299296462009) -->
- <skip />
- <!-- no translation found for bluetooth_battery_level (1447164613319663655) -->
- <skip />
- <!-- no translation found for bluetooth_active_no_battery_level (8380223546730241956) -->
- <skip />
+ <string name="bluetooth_active_battery_level" msgid="3149689299296462009">"Activo, <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> de batería"</string>
+ <string name="bluetooth_battery_level" msgid="1447164613319663655">"<xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> de batería"</string>
+ <string name="bluetooth_active_no_battery_level" msgid="8380223546730241956">"Activo"</string>
<string name="bluetooth_profile_a2dp" msgid="2031475486179830674">"Audio multimedia"</string>
<string name="bluetooth_profile_headset" msgid="7815495680863246034">"Llamadas de teléfono"</string>
<string name="bluetooth_profile_opp" msgid="9168139293654233697">"Transferencia de archivos"</string>
@@ -119,14 +114,10 @@
<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>
- <!-- no translation found for bluetooth_hearingaid_left_pairing_message (7378813500862148102) -->
- <skip />
- <!-- no translation found for bluetooth_hearingaid_right_pairing_message (1550373802309160891) -->
- <skip />
- <!-- no translation found for bluetooth_hearingaid_left_battery_level (8797811465352097562) -->
- <skip />
- <!-- no translation found for bluetooth_hearingaid_right_battery_level (7309476148173459677) -->
- <skip />
+ <string name="bluetooth_hearingaid_left_pairing_message" msgid="7378813500862148102">"Vinculando el audífono izquierdo…"</string>
+ <string name="bluetooth_hearingaid_right_pairing_message" msgid="1550373802309160891">"Vinculando el audífono derecho…"</string>
+ <string name="bluetooth_hearingaid_left_battery_level" msgid="8797811465352097562">"Izquierdo: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> de batería"</string>
+ <string name="bluetooth_hearingaid_right_battery_level" msgid="7309476148173459677">"Derecho: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> de batería"</string>
<string name="accessibility_wifi_off" msgid="1166761729660614716">"Wi-Fi desactivado."</string>
<string name="accessibility_no_wifi" msgid="8834610636137374508">"Wi-Fi desconectado."</string>
<string name="accessibility_wifi_one_bar" msgid="4869376278894301820">"Una barra de Wi-Fi."</string>
@@ -246,15 +237,12 @@
<string name="private_dns_mode_opportunistic" msgid="8314986739896927399">"Automático"</string>
<string name="private_dns_mode_provider" msgid="8354935160639360804">"Nombre de host de proveedor de DNS privado"</string>
<string name="private_dns_mode_provider_hostname_hint" msgid="2487492386970928143">"Introduce el nombre de host del proveedor de DNS"</string>
- <!-- no translation found for private_dns_mode_provider_failure (231837290365031223) -->
- <skip />
+ <string name="private_dns_mode_provider_failure" msgid="231837290365031223">"No se ha podido establecer la conexión"</string>
<string name="wifi_display_certification_summary" msgid="1155182309166746973">"Mostrar opciones para la certificación de la pantalla inalámbrica"</string>
<string name="wifi_verbose_logging_summary" msgid="6615071616111731958">"Aumentar el nivel de registro de Wi-Fi, mostrar por SSID RSSI en el selector Wi-Fi"</string>
<string name="wifi_connected_mac_randomization_summary" msgid="1743059848752201485">"Ordenar las direcciones MAC de forma aleatoria al conectarse a redes Wi‑Fi"</string>
- <!-- no translation found for wifi_metered_label (4514924227256839725) -->
- <skip />
- <!-- no translation found for wifi_unmetered_label (6124098729457992931) -->
- <skip />
+ <string name="wifi_metered_label" msgid="4514924227256839725">"Medido"</string>
+ <string name="wifi_unmetered_label" msgid="6124098729457992931">"No medido"</string>
<string name="select_logd_size_title" msgid="7433137108348553508">"Tamaños de búfer de registrador"</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>
diff --git a/packages/SettingsLib/res/values-et/strings.xml b/packages/SettingsLib/res/values-et/strings.xml
index 0998679..7a1a216 100644
--- a/packages/SettingsLib/res/values-et/strings.xml
+++ b/packages/SettingsLib/res/values-et/strings.xml
@@ -40,10 +40,8 @@
<string name="connected_via_passpoint" msgid="2826205693803088747">"Ühendatud üksuse %1$s kaudu"</string>
<string name="available_via_passpoint" msgid="1617440946846329613">"Saadaval üksuse %1$s kaudu"</string>
<string name="wifi_connected_no_internet" msgid="8202906332837777829">"Ühendatud, Interneti-ühendus puudub"</string>
- <!-- no translation found for wifi_status_no_internet (5784710974669608361) -->
- <skip />
- <!-- no translation found for wifi_status_sign_in_required (123517180404752756) -->
- <skip />
+ <string name="wifi_status_no_internet" msgid="5784710974669608361">"Interneti-ühendus puudub"</string>
+ <string name="wifi_status_sign_in_required" msgid="123517180404752756">"Nõutav on sisselogimine"</string>
<string name="wifi_ap_unable_to_handle_new_sta" msgid="5348824313514404541">"Pääsupunkt on ajutiselt täis"</string>
<string name="connected_via_carrier" msgid="7583780074526041912">"Ühendatud operaatori %1$s kaudu"</string>
<string name="available_via_carrier" msgid="1469036129740799053">"Saadaval operaatori %1$s kaudu"</string>
@@ -67,12 +65,9 @@
<string name="bluetooth_connected_no_headset_battery_level" msgid="1610296229139400266">"Ühendatud (telefoni pole), aku <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g><xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g>"</string>
<string name="bluetooth_connected_no_a2dp_battery_level" msgid="3908466636369853652">"Ühendatud (meediat pole), aku <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g><xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g>"</string>
<string name="bluetooth_connected_no_headset_no_a2dp_battery_level" msgid="1163440823807659316">"Ühendatud (telefoni ega meediat pole), aku <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g><xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g>"</string>
- <!-- no translation found for bluetooth_active_battery_level (3149689299296462009) -->
- <skip />
- <!-- no translation found for bluetooth_battery_level (1447164613319663655) -->
- <skip />
- <!-- no translation found for bluetooth_active_no_battery_level (8380223546730241956) -->
- <skip />
+ <string name="bluetooth_active_battery_level" msgid="3149689299296462009">"Aktiivne, <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> akut"</string>
+ <string name="bluetooth_battery_level" msgid="1447164613319663655">"<xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> akut"</string>
+ <string name="bluetooth_active_no_battery_level" msgid="8380223546730241956">"Aktiivne"</string>
<string name="bluetooth_profile_a2dp" msgid="2031475486179830674">"Meedia heli"</string>
<string name="bluetooth_profile_headset" msgid="7815495680863246034">"Telefonikõned"</string>
<string name="bluetooth_profile_opp" msgid="9168139293654233697">"Failiedastus"</string>
@@ -119,14 +114,10 @@
<string name="bluetooth_talkback_headphone" msgid="26580326066627664">"Kõrvaklapid"</string>
<string name="bluetooth_talkback_input_peripheral" msgid="5165842622743212268">"Sisestatud välisseade"</string>
<string name="bluetooth_talkback_bluetooth" msgid="5615463912185280812">"Bluetooth"</string>
- <!-- no translation found for bluetooth_hearingaid_left_pairing_message (7378813500862148102) -->
- <skip />
- <!-- no translation found for bluetooth_hearingaid_right_pairing_message (1550373802309160891) -->
- <skip />
- <!-- no translation found for bluetooth_hearingaid_left_battery_level (8797811465352097562) -->
- <skip />
- <!-- no translation found for bluetooth_hearingaid_right_battery_level (7309476148173459677) -->
- <skip />
+ <string name="bluetooth_hearingaid_left_pairing_message" msgid="7378813500862148102">"Vasakpoolse kuuldeaparaadi sidumine …"</string>
+ <string name="bluetooth_hearingaid_right_pairing_message" msgid="1550373802309160891">"Parempoolse kuuldeaparaadi sidumine …"</string>
+ <string name="bluetooth_hearingaid_left_battery_level" msgid="8797811465352097562">"Vasakpoolne – <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> akut"</string>
+ <string name="bluetooth_hearingaid_right_battery_level" msgid="7309476148173459677">"Parempoolne – <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> akut"</string>
<string name="accessibility_wifi_off" msgid="1166761729660614716">"WiFi on välja lülitatud."</string>
<string name="accessibility_no_wifi" msgid="8834610636137374508">"WiFi-ühendus on katkestatud."</string>
<string name="accessibility_wifi_one_bar" msgid="4869376278894301820">"WiFi: üks pulk."</string>
@@ -246,15 +237,12 @@
<string name="private_dns_mode_opportunistic" msgid="8314986739896927399">"Automaatne"</string>
<string name="private_dns_mode_provider" msgid="8354935160639360804">"Privaatse DNS-i teenusepakkuja hostinimi"</string>
<string name="private_dns_mode_provider_hostname_hint" msgid="2487492386970928143">"Sisestage DNS-i teenusepakkuja hostinimi"</string>
- <!-- no translation found for private_dns_mode_provider_failure (231837290365031223) -->
- <skip />
+ <string name="private_dns_mode_provider_failure" msgid="231837290365031223">"Ühendamine ebaõnnestus"</string>
<string name="wifi_display_certification_summary" msgid="1155182309166746973">"Juhtmeta ekraaniühenduse sertifitseerimisvalikute kuvamine"</string>
<string name="wifi_verbose_logging_summary" msgid="6615071616111731958">"Suurenda WiFi logimistaset, kuva WiFi valijas SSID RSSI järgi"</string>
<string name="wifi_connected_mac_randomization_summary" msgid="1743059848752201485">"Määra WiFi-võrkudega ühenduse loomisel juhuslik MAC-aadress"</string>
- <!-- no translation found for wifi_metered_label (4514924227256839725) -->
- <skip />
- <!-- no translation found for wifi_unmetered_label (6124098729457992931) -->
- <skip />
+ <string name="wifi_metered_label" msgid="4514924227256839725">"Mahupõhine"</string>
+ <string name="wifi_unmetered_label" msgid="6124098729457992931">"Mittemahupõhine"</string>
<string name="select_logd_size_title" msgid="7433137108348553508">"Logija puhvri suurused"</string>
<string name="select_logd_size_dialog_title" msgid="1206769310236476760">"Vali logija suur. logipuhvri kohta"</string>
<string name="dev_logpersist_clear_warning_title" msgid="684806692440237967">"Kas kustutada logija püsivalt salvestatud andmed?"</string>
diff --git a/packages/SettingsLib/res/values-eu/strings.xml b/packages/SettingsLib/res/values-eu/strings.xml
index 2c98966..7f1b105 100644
--- a/packages/SettingsLib/res/values-eu/strings.xml
+++ b/packages/SettingsLib/res/values-eu/strings.xml
@@ -40,10 +40,8 @@
<string name="connected_via_passpoint" msgid="2826205693803088747">"%1$s bidez konektatuta"</string>
<string name="available_via_passpoint" msgid="1617440946846329613">"%1$s bidez erabilgarri"</string>
<string name="wifi_connected_no_internet" msgid="8202906332837777829">"Konektatuta; ezin da atzitu Internet"</string>
- <!-- no translation found for wifi_status_no_internet (5784710974669608361) -->
- <skip />
- <!-- no translation found for wifi_status_sign_in_required (123517180404752756) -->
- <skip />
+ <string name="wifi_status_no_internet" msgid="5784710974669608361">"Ez dago Interneteko konexiorik"</string>
+ <string name="wifi_status_sign_in_required" msgid="123517180404752756">"Saioa hasi behar da"</string>
<string name="wifi_ap_unable_to_handle_new_sta" msgid="5348824313514404541">"Sarbide-puntua beteta dago aldi baterako"</string>
<string name="connected_via_carrier" msgid="7583780074526041912">"%1$s bidez konektatuta"</string>
<string name="available_via_carrier" msgid="1469036129740799053">"%1$s bidez erabilgarri"</string>
@@ -67,12 +65,9 @@
<string name="bluetooth_connected_no_headset_battery_level" msgid="1610296229139400266">"Konektatuta (telefonoaren audiorik gabe). Bateria: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g><xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g>."</string>
<string name="bluetooth_connected_no_a2dp_battery_level" msgid="3908466636369853652">"Konektatuta (gailuaren audiorik gabe). Bateria: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g><xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g>."</string>
<string name="bluetooth_connected_no_headset_no_a2dp_battery_level" msgid="1163440823807659316">"Konektatuta (telefonoaren edo gailuaren audiorik gabe). Bateria: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g><xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g>."</string>
- <!-- no translation found for bluetooth_active_battery_level (3149689299296462009) -->
- <skip />
- <!-- no translation found for bluetooth_battery_level (1447164613319663655) -->
- <skip />
- <!-- no translation found for bluetooth_active_no_battery_level (8380223546730241956) -->
- <skip />
+ <string name="bluetooth_active_battery_level" msgid="3149689299296462009">"Aktibo. Bateria: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
+ <string name="bluetooth_battery_level" msgid="1447164613319663655">"Bateria: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
+ <string name="bluetooth_active_no_battery_level" msgid="8380223546730241956">"Aktibo"</string>
<string name="bluetooth_profile_a2dp" msgid="2031475486179830674">"Euskarriaren audioa"</string>
<string name="bluetooth_profile_headset" msgid="7815495680863246034">"Telefono-deiak"</string>
<string name="bluetooth_profile_opp" msgid="9168139293654233697">"Fitxategi-transferentzia"</string>
@@ -119,14 +114,10 @@
<string name="bluetooth_talkback_headphone" msgid="26580326066627664">"Aurikularra"</string>
<string name="bluetooth_talkback_input_peripheral" msgid="5165842622743212268">"Idazteko gailua"</string>
<string name="bluetooth_talkback_bluetooth" msgid="5615463912185280812">"Bluetooth gailua"</string>
- <!-- no translation found for bluetooth_hearingaid_left_pairing_message (7378813500862148102) -->
- <skip />
- <!-- no translation found for bluetooth_hearingaid_right_pairing_message (1550373802309160891) -->
- <skip />
- <!-- no translation found for bluetooth_hearingaid_left_battery_level (8797811465352097562) -->
- <skip />
- <!-- no translation found for bluetooth_hearingaid_right_battery_level (7309476148173459677) -->
- <skip />
+ <string name="bluetooth_hearingaid_left_pairing_message" msgid="7378813500862148102">"Ezkerreko audiofonoa parekatzen…"</string>
+ <string name="bluetooth_hearingaid_right_pairing_message" msgid="1550373802309160891">"Eskuineko audiofonoa parekatzen…"</string>
+ <string name="bluetooth_hearingaid_left_battery_level" msgid="8797811465352097562">"Ezkerrekoa. Bateria: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
+ <string name="bluetooth_hearingaid_right_battery_level" msgid="7309476148173459677">"Eskuinekoa. Bateria: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
<string name="accessibility_wifi_off" msgid="1166761729660614716">"Desaktibatuta dago Wi-Fi konexioa."</string>
<string name="accessibility_no_wifi" msgid="8834610636137374508">"Deskonektatu egin da Wi-Fi konexioa."</string>
<string name="accessibility_wifi_one_bar" msgid="4869376278894301820">"Wi-Fi sarearen barra bat."</string>
@@ -246,15 +237,12 @@
<string name="private_dns_mode_opportunistic" msgid="8314986739896927399">"Automatikoa"</string>
<string name="private_dns_mode_provider" msgid="8354935160639360804">"DNS hornitzaile pribatuaren ostalari-izena"</string>
<string name="private_dns_mode_provider_hostname_hint" msgid="2487492386970928143">"Idatzi DNS hornitzailearen ostalari-izena"</string>
- <!-- no translation found for private_dns_mode_provider_failure (231837290365031223) -->
- <skip />
+ <string name="private_dns_mode_provider_failure" msgid="231837290365031223">"Ezin izan da konektatu"</string>
<string name="wifi_display_certification_summary" msgid="1155182309166746973">"Erakutsi hari gabeko bistaratze-egiaztapenaren aukerak"</string>
<string name="wifi_verbose_logging_summary" msgid="6615071616111731958">"Erakutsi datu gehiago Wi-Fi sareetan saioa hasterakoan. Erakutsi sarearen identifikatzailea eta seinalearen indarra Wi‑Fi sareen hautagailuan."</string>
<string name="wifi_connected_mac_randomization_summary" msgid="1743059848752201485">"Aukeratu ausaz MAC helbideak Wi‑Fi sareetara konektatzean"</string>
- <!-- no translation found for wifi_metered_label (4514924227256839725) -->
- <skip />
- <!-- no translation found for wifi_unmetered_label (6124098729457992931) -->
- <skip />
+ <string name="wifi_metered_label" msgid="4514924227256839725">"Sare mugatua"</string>
+ <string name="wifi_unmetered_label" msgid="6124098729457992931">"Sare ez-mugatua"</string>
<string name="select_logd_size_title" msgid="7433137108348553508">"Erregistroen buffer-tamainak"</string>
<string name="select_logd_size_dialog_title" msgid="1206769310236476760">"Hautatu erregistroen buffer-tamainak"</string>
<string name="dev_logpersist_clear_warning_title" msgid="684806692440237967">"Erregistro iraunkorraren biltegia garbitu nahi duzu?"</string>
diff --git a/packages/SettingsLib/res/values-fi/strings.xml b/packages/SettingsLib/res/values-fi/strings.xml
index fe85a6c..1690fda 100644
--- a/packages/SettingsLib/res/values-fi/strings.xml
+++ b/packages/SettingsLib/res/values-fi/strings.xml
@@ -40,10 +40,8 @@
<string name="connected_via_passpoint" msgid="2826205693803088747">"Yhdistetty seuraavan kautta: %1$s"</string>
<string name="available_via_passpoint" msgid="1617440946846329613">"Käytettävissä seuraavan kautta: %1$s"</string>
<string name="wifi_connected_no_internet" msgid="8202906332837777829">"Yhdistetty, ei internetyhteyttä"</string>
- <!-- no translation found for wifi_status_no_internet (5784710974669608361) -->
- <skip />
- <!-- no translation found for wifi_status_sign_in_required (123517180404752756) -->
- <skip />
+ <string name="wifi_status_no_internet" msgid="5784710974669608361">"Ei internetyhteyttä"</string>
+ <string name="wifi_status_sign_in_required" msgid="123517180404752756">"Sisäänkirjautuminen vaaditaan"</string>
<string name="wifi_ap_unable_to_handle_new_sta" msgid="5348824313514404541">"Yhteyspiste tilapäisesti täynnä"</string>
<string name="connected_via_carrier" msgid="7583780074526041912">"Yhdistetty, verkko: %1$s"</string>
<string name="available_via_carrier" msgid="1469036129740799053">"Käytettävissä, verkko: %1$s"</string>
@@ -67,12 +65,9 @@
<string name="bluetooth_connected_no_headset_battery_level" msgid="1610296229139400266">"Yhdistetty (ei puhelimen ääntä), akun varaus <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> <xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g>"</string>
<string name="bluetooth_connected_no_a2dp_battery_level" msgid="3908466636369853652">"Yhdistetty (ei median ääntä), akun varaus <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> <xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g>"</string>
<string name="bluetooth_connected_no_headset_no_a2dp_battery_level" msgid="1163440823807659316">"Yhdistetty (ei puhelimen tai median ääntä), akun varaustaso <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> <xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g>"</string>
- <!-- no translation found for bluetooth_active_battery_level (3149689299296462009) -->
- <skip />
- <!-- no translation found for bluetooth_battery_level (1447164613319663655) -->
- <skip />
- <!-- no translation found for bluetooth_active_no_battery_level (8380223546730241956) -->
- <skip />
+ <string name="bluetooth_active_battery_level" msgid="3149689299296462009">"Aktiivinen, akun taso <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
+ <string name="bluetooth_battery_level" msgid="1447164613319663655">"Akun taso <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
+ <string name="bluetooth_active_no_battery_level" msgid="8380223546730241956">"Aktiivinen"</string>
<string name="bluetooth_profile_a2dp" msgid="2031475486179830674">"Median ääni"</string>
<string name="bluetooth_profile_headset" msgid="7815495680863246034">"Puhelut"</string>
<string name="bluetooth_profile_opp" msgid="9168139293654233697">"Tiedostonsiirto"</string>
@@ -119,14 +114,10 @@
<string name="bluetooth_talkback_headphone" msgid="26580326066627664">"Kuulokkeet"</string>
<string name="bluetooth_talkback_input_peripheral" msgid="5165842622743212268">"Syöttölisälaite"</string>
<string name="bluetooth_talkback_bluetooth" msgid="5615463912185280812">"Bluetooth"</string>
- <!-- no translation found for bluetooth_hearingaid_left_pairing_message (7378813500862148102) -->
- <skip />
- <!-- no translation found for bluetooth_hearingaid_right_pairing_message (1550373802309160891) -->
- <skip />
- <!-- no translation found for bluetooth_hearingaid_left_battery_level (8797811465352097562) -->
- <skip />
- <!-- no translation found for bluetooth_hearingaid_right_battery_level (7309476148173459677) -->
- <skip />
+ <string name="bluetooth_hearingaid_left_pairing_message" msgid="7378813500862148102">"Muodostetaan paria vasemmanpuoleisen kuulolaitteen kanssa…"</string>
+ <string name="bluetooth_hearingaid_right_pairing_message" msgid="1550373802309160891">"Muodostetaan paria oikeanpuoleisen kuulolaitteen kanssa…"</string>
+ <string name="bluetooth_hearingaid_left_battery_level" msgid="8797811465352097562">"Vasen – akun taso <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
+ <string name="bluetooth_hearingaid_right_battery_level" msgid="7309476148173459677">"Oikea – akun taso <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
<string name="accessibility_wifi_off" msgid="1166761729660614716">"Wi-Fi pois käytöstä"</string>
<string name="accessibility_no_wifi" msgid="8834610636137374508">"Ei Wi-Fi-yhteyttä"</string>
<string name="accessibility_wifi_one_bar" msgid="4869376278894301820">"Wi-Fi-signaali – yksi palkki"</string>
@@ -246,15 +237,12 @@
<string name="private_dns_mode_opportunistic" msgid="8314986739896927399">"Automaattinen"</string>
<string name="private_dns_mode_provider" msgid="8354935160639360804">"Yksityisen DNS-tarjoajan isäntänimi"</string>
<string name="private_dns_mode_provider_hostname_hint" msgid="2487492386970928143">"Anna isäntänimi tai DNS-tarjoaja."</string>
- <!-- no translation found for private_dns_mode_provider_failure (231837290365031223) -->
- <skip />
+ <string name="private_dns_mode_provider_failure" msgid="231837290365031223">"Ei yhteyttä"</string>
<string name="wifi_display_certification_summary" msgid="1155182309166746973">"Näytä langattoman näytön sertifiointiin liittyvät asetukset"</string>
<string name="wifi_verbose_logging_summary" msgid="6615071616111731958">"Lisää Wi‑Fin lokikirjaustasoa, näytä SSID RSSI -kohtaisesti Wi‑Fi-valitsimessa."</string>
<string name="wifi_connected_mac_randomization_summary" msgid="1743059848752201485">"Käytä satunnaista MAC-osoitetta, kun yhdistät Wi-Fi-verkkoon"</string>
- <!-- no translation found for wifi_metered_label (4514924227256839725) -->
- <skip />
- <!-- no translation found for wifi_unmetered_label (6124098729457992931) -->
- <skip />
+ <string name="wifi_metered_label" msgid="4514924227256839725">"Maksullinen"</string>
+ <string name="wifi_unmetered_label" msgid="6124098729457992931">"Maksuton"</string>
<string name="select_logd_size_title" msgid="7433137108348553508">"Lokipuskurien koot"</string>
<string name="select_logd_size_dialog_title" msgid="1206769310236476760">"Valitse puskurikohtaiset lokikoot"</string>
<string name="dev_logpersist_clear_warning_title" msgid="684806692440237967">"Tyhjennetäänkö lokityökalun pysyvä tallennustila?"</string>
diff --git a/packages/SettingsLib/res/values-fr-rCA/strings.xml b/packages/SettingsLib/res/values-fr-rCA/strings.xml
index 270a868..d658187 100644
--- a/packages/SettingsLib/res/values-fr-rCA/strings.xml
+++ b/packages/SettingsLib/res/values-fr-rCA/strings.xml
@@ -40,10 +40,8 @@
<string name="connected_via_passpoint" msgid="2826205693803088747">"Connecté par %1$s"</string>
<string name="available_via_passpoint" msgid="1617440946846329613">"Accessible par %1$s"</string>
<string name="wifi_connected_no_internet" msgid="8202906332837777829">"Connecté, aucun accès à Internet"</string>
- <!-- no translation found for wifi_status_no_internet (5784710974669608361) -->
- <skip />
- <!-- no translation found for wifi_status_sign_in_required (123517180404752756) -->
- <skip />
+ <string name="wifi_status_no_internet" msgid="5784710974669608361">"Aucune connexion Internet"</string>
+ <string name="wifi_status_sign_in_required" msgid="123517180404752756">"Connexion requise"</string>
<string name="wifi_ap_unable_to_handle_new_sta" msgid="5348824313514404541">"Le point d\'accès est temporairement plein"</string>
<string name="connected_via_carrier" msgid="7583780074526041912">"Connecté par %1$s"</string>
<string name="available_via_carrier" msgid="1469036129740799053">"Accessible par %1$s"</string>
@@ -67,12 +65,9 @@
<string name="bluetooth_connected_no_headset_battery_level" msgid="1610296229139400266">"Connecté (aucun téléphone), pile chargée à <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> <xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g>"</string>
<string name="bluetooth_connected_no_a2dp_battery_level" msgid="3908466636369853652">"Connecté (aucun média), pile chargée à <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> <xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g>"</string>
<string name="bluetooth_connected_no_headset_no_a2dp_battery_level" msgid="1163440823807659316">"Connecté (aucun téléphone ni média), pile chargée à <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> <xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g>"</string>
- <!-- no translation found for bluetooth_active_battery_level (3149689299296462009) -->
- <skip />
- <!-- no translation found for bluetooth_battery_level (1447164613319663655) -->
- <skip />
- <!-- no translation found for bluetooth_active_no_battery_level (8380223546730241956) -->
- <skip />
+ <string name="bluetooth_active_battery_level" msgid="3149689299296462009">"Actif, pile : <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
+ <string name="bluetooth_battery_level" msgid="1447164613319663655">"Pile : <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
+ <string name="bluetooth_active_no_battery_level" msgid="8380223546730241956">"Actif"</string>
<string name="bluetooth_profile_a2dp" msgid="2031475486179830674">"Paramètres audio du support"</string>
<string name="bluetooth_profile_headset" msgid="7815495680863246034">"Appels téléphoniques"</string>
<string name="bluetooth_profile_opp" msgid="9168139293654233697">"Transfert de fichier"</string>
@@ -119,14 +114,10 @@
<string name="bluetooth_talkback_headphone" msgid="26580326066627664">"Écouteurs"</string>
<string name="bluetooth_talkback_input_peripheral" msgid="5165842622743212268">"Périphérique d\'entrée"</string>
<string name="bluetooth_talkback_bluetooth" msgid="5615463912185280812">"Bluetooth"</string>
- <!-- no translation found for bluetooth_hearingaid_left_pairing_message (7378813500862148102) -->
- <skip />
- <!-- no translation found for bluetooth_hearingaid_right_pairing_message (1550373802309160891) -->
- <skip />
- <!-- no translation found for bluetooth_hearingaid_left_battery_level (8797811465352097562) -->
- <skip />
- <!-- no translation found for bluetooth_hearingaid_right_battery_level (7309476148173459677) -->
- <skip />
+ <string name="bluetooth_hearingaid_left_pairing_message" msgid="7378813500862148102">"Association de la prothèse auditive gauche en cours…"</string>
+ <string name="bluetooth_hearingaid_right_pairing_message" msgid="1550373802309160891">"Association de la prothèse auditive droite en cours…"</string>
+ <string name="bluetooth_hearingaid_left_battery_level" msgid="8797811465352097562">"Gauche, pile : <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
+ <string name="bluetooth_hearingaid_right_battery_level" msgid="7309476148173459677">"Droite, pile : <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
<string name="accessibility_wifi_off" msgid="1166761729660614716">"Wi-Fi désactivé."</string>
<string name="accessibility_no_wifi" msgid="8834610636137374508">"Wi-Fi déconnecté."</string>
<string name="accessibility_wifi_one_bar" msgid="4869376278894301820">"Wi-Fi : une barre."</string>
@@ -206,8 +197,7 @@
<string name="keep_screen_on" msgid="1146389631208760344">"Rester activé"</string>
<string name="keep_screen_on_summary" msgid="2173114350754293009">"L\'écran ne se met jamais en veille lors du chargement"</string>
<string name="bt_hci_snoop_log" msgid="3340699311158865670">"Activer le journal HCI Snoop Bluetooth"</string>
- <!-- no translation found for bt_hci_snoop_log_summary (366083475849911315) -->
- <skip />
+ <string name="bt_hci_snoop_log_summary" msgid="366083475849911315">"Capturer tous les paquets HCI Bluetooth dans un fichier. (Faites basculer Bluetooth après le changement de ce paramètre.)"</string>
<string name="oem_unlock_enable" msgid="6040763321967327691">"Déverrouillage par le fabricant"</string>
<string name="oem_unlock_enable_summary" msgid="4720281828891618376">"Autoriser le déverrouillage du fichier d\'amorce"</string>
<string name="confirm_enable_oem_unlock_title" msgid="4802157344812385674">"Permettre le déverrouillage par le fabricant?"</string>
@@ -247,15 +237,12 @@
<string name="private_dns_mode_opportunistic" msgid="8314986739896927399">"Automatique"</string>
<string name="private_dns_mode_provider" msgid="8354935160639360804">"Nom d\'hôte du fournisseur DNS privé"</string>
<string name="private_dns_mode_provider_hostname_hint" msgid="2487492386970928143">"Entrez le nom d\'hôte du fournisseur DNS"</string>
- <!-- no translation found for private_dns_mode_provider_failure (231837290365031223) -->
- <skip />
+ <string name="private_dns_mode_provider_failure" msgid="231837290365031223">"Impossible de se connecter"</string>
<string name="wifi_display_certification_summary" msgid="1155182309166746973">"Afficher les options pour la certification d\'affichage sans fil"</string>
<string name="wifi_verbose_logging_summary" msgid="6615071616111731958">"Détailler davantage les données Wi-Fi, afficher par SSID RSSI dans sélect. Wi-Fi"</string>
<string name="wifi_connected_mac_randomization_summary" msgid="1743059848752201485">"Sélectionner l\'adresse MAC de manière aléatoire lors de la connexion aux réseaux Wi-Fi"</string>
- <!-- no translation found for wifi_metered_label (4514924227256839725) -->
- <skip />
- <!-- no translation found for wifi_unmetered_label (6124098729457992931) -->
- <skip />
+ <string name="wifi_metered_label" msgid="4514924227256839725">"Mesuré"</string>
+ <string name="wifi_unmetered_label" msgid="6124098729457992931">"Non mesuré"</string>
<string name="select_logd_size_title" msgid="7433137108348553508">"Tailles des mémoires tampons d\'enregistreur"</string>
<string name="select_logd_size_dialog_title" msgid="1206769310236476760">"Tailles enreg. par tampon journal"</string>
<string name="dev_logpersist_clear_warning_title" msgid="684806692440237967">"Supprimer les données de l\'enregistreur?"</string>
diff --git a/packages/SettingsLib/res/values-fr/strings.xml b/packages/SettingsLib/res/values-fr/strings.xml
index 6712813..903c98c 100644
--- a/packages/SettingsLib/res/values-fr/strings.xml
+++ b/packages/SettingsLib/res/values-fr/strings.xml
@@ -40,10 +40,8 @@
<string name="connected_via_passpoint" msgid="2826205693803088747">"Connecté via %1$s"</string>
<string name="available_via_passpoint" msgid="1617440946846329613">"Disponible via %1$s"</string>
<string name="wifi_connected_no_internet" msgid="8202906332837777829">"Connecté, aucun accès à Internet"</string>
- <!-- no translation found for wifi_status_no_internet (5784710974669608361) -->
- <skip />
- <!-- no translation found for wifi_status_sign_in_required (123517180404752756) -->
- <skip />
+ <string name="wifi_status_no_internet" msgid="5784710974669608361">"Aucun accès à Internet"</string>
+ <string name="wifi_status_sign_in_required" msgid="123517180404752756">"Connexion requise"</string>
<string name="wifi_ap_unable_to_handle_new_sta" msgid="5348824313514404541">"Point d\'accès temporairement plein"</string>
<string name="connected_via_carrier" msgid="7583780074526041912">"Connecté via %1$s"</string>
<string name="available_via_carrier" msgid="1469036129740799053">"Disponible via %1$s"</string>
@@ -67,12 +65,9 @@
<string name="bluetooth_connected_no_headset_battery_level" msgid="1610296229139400266">"Connecté (aucun téléphone), batterie à <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g><xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g>"</string>
<string name="bluetooth_connected_no_a2dp_battery_level" msgid="3908466636369853652">"Connecté (aucun contenu multimédia), batterie à <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g><xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g>"</string>
<string name="bluetooth_connected_no_headset_no_a2dp_battery_level" msgid="1163440823807659316">"Connecté (aucun téléphone ni contenu multimédia), batterie à <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g><xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g>"</string>
- <!-- no translation found for bluetooth_active_battery_level (3149689299296462009) -->
- <skip />
- <!-- no translation found for bluetooth_battery_level (1447164613319663655) -->
- <skip />
- <!-- no translation found for bluetooth_active_no_battery_level (8380223546730241956) -->
- <skip />
+ <string name="bluetooth_active_battery_level" msgid="3149689299296462009">"Actif, <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> de batterie"</string>
+ <string name="bluetooth_battery_level" msgid="1447164613319663655">"<xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> de batterie"</string>
+ <string name="bluetooth_active_no_battery_level" msgid="8380223546730241956">"Actif"</string>
<string name="bluetooth_profile_a2dp" msgid="2031475486179830674">"Multimédia"</string>
<string name="bluetooth_profile_headset" msgid="7815495680863246034">"Appels téléphoniques"</string>
<string name="bluetooth_profile_opp" msgid="9168139293654233697">"Transfert de fichier"</string>
@@ -119,14 +114,10 @@
<string name="bluetooth_talkback_headphone" msgid="26580326066627664">"Casque audio"</string>
<string name="bluetooth_talkback_input_peripheral" msgid="5165842622743212268">"Périphérique d\'entrée"</string>
<string name="bluetooth_talkback_bluetooth" msgid="5615463912185280812">"Bluetooth"</string>
- <!-- no translation found for bluetooth_hearingaid_left_pairing_message (7378813500862148102) -->
- <skip />
- <!-- no translation found for bluetooth_hearingaid_right_pairing_message (1550373802309160891) -->
- <skip />
- <!-- no translation found for bluetooth_hearingaid_left_battery_level (8797811465352097562) -->
- <skip />
- <!-- no translation found for bluetooth_hearingaid_right_battery_level (7309476148173459677) -->
- <skip />
+ <string name="bluetooth_hearingaid_left_pairing_message" msgid="7378813500862148102">"Association de l\'appareil auditif gauche…"</string>
+ <string name="bluetooth_hearingaid_right_pairing_message" msgid="1550373802309160891">"Association de l\'appareil auditif droit…"</string>
+ <string name="bluetooth_hearingaid_left_battery_level" msgid="8797811465352097562">"Gauche – <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> de batterie"</string>
+ <string name="bluetooth_hearingaid_right_battery_level" msgid="7309476148173459677">"Droit – <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> de batterie"</string>
<string name="accessibility_wifi_off" msgid="1166761729660614716">"Wi-Fi désactivé"</string>
<string name="accessibility_no_wifi" msgid="8834610636137374508">"Wi-Fi déconnecté"</string>
<string name="accessibility_wifi_one_bar" msgid="4869376278894301820">"Signal Wi-Fi faible"</string>
@@ -246,15 +237,12 @@
<string name="private_dns_mode_opportunistic" msgid="8314986739896927399">"Automatique"</string>
<string name="private_dns_mode_provider" msgid="8354935160639360804">"Nom d\'hôte du fournisseur DNS privé"</string>
<string name="private_dns_mode_provider_hostname_hint" msgid="2487492386970928143">"Saisissez le nom d\'hôte du fournisseur DNS"</string>
- <!-- no translation found for private_dns_mode_provider_failure (231837290365031223) -->
- <skip />
+ <string name="private_dns_mode_provider_failure" msgid="231837290365031223">"Impossible de se connecter"</string>
<string name="wifi_display_certification_summary" msgid="1155182309166746973">"Afficher les options de la certification de l\'affichage sans fil"</string>
<string name="wifi_verbose_logging_summary" msgid="6615071616111731958">"Détailler plus infos Wi-Fi, afficher par RSSI de SSID dans outil sélection Wi-Fi"</string>
<string name="wifi_connected_mac_randomization_summary" msgid="1743059848752201485">"Sélectionner l\'adresse MAC de manière aléatoire lors de la connexion aux réseaux Wi-Fi"</string>
- <!-- no translation found for wifi_metered_label (4514924227256839725) -->
- <skip />
- <!-- no translation found for wifi_unmetered_label (6124098729457992931) -->
- <skip />
+ <string name="wifi_metered_label" msgid="4514924227256839725">"Facturé à l\'usage"</string>
+ <string name="wifi_unmetered_label" msgid="6124098729457992931">"Non facturé à l\'usage"</string>
<string name="select_logd_size_title" msgid="7433137108348553508">"Tailles mémoires tampons enregistr."</string>
<string name="select_logd_size_dialog_title" msgid="1206769310236476760">"Tailles enreg. par tampon journal"</string>
<string name="dev_logpersist_clear_warning_title" msgid="684806692440237967">"Effacer l\'espace de stockage persistant de l\'enregistreur ?"</string>
diff --git a/packages/SettingsLib/res/values-gu/strings.xml b/packages/SettingsLib/res/values-gu/strings.xml
index 8972930..6acd2ca 100644
--- a/packages/SettingsLib/res/values-gu/strings.xml
+++ b/packages/SettingsLib/res/values-gu/strings.xml
@@ -206,8 +206,7 @@
<string name="keep_screen_on" msgid="1146389631208760344">"સક્રિય રાખો"</string>
<string name="keep_screen_on_summary" msgid="2173114350754293009">"ચાર્જિંગ દરમિયાન સ્ક્રીન ક્યારેય નિષ્ક્રિય થશે નહીં"</string>
<string name="bt_hci_snoop_log" msgid="3340699311158865670">"બ્લૂટૂથ HCI સ્નૂપ લૉગ સક્ષમ કરો"</string>
- <!-- no translation found for bt_hci_snoop_log_summary (366083475849911315) -->
- <skip />
+ <string name="bt_hci_snoop_log_summary" msgid="366083475849911315">"ફાઇલમાં બધા બ્લૂટૂથ HCI પૅકેટને કૅપ્ચર કરો (આ સેટિંગ બદલ્યા પછી બ્લૂટૂથને ટૉગલ કરો)"</string>
<string name="oem_unlock_enable" msgid="6040763321967327691">"OEM અનલૉકિંગ"</string>
<string name="oem_unlock_enable_summary" msgid="4720281828891618376">"બુટલોડર અનલૉક કરવાની મંજૂરી આપો"</string>
<string name="confirm_enable_oem_unlock_title" msgid="4802157344812385674">"OEM ને અનલૉક કરવાની મંજૂરી આપીએ?"</string>
diff --git a/packages/SettingsLib/res/values-hi/strings.xml b/packages/SettingsLib/res/values-hi/strings.xml
index 296da2d..9b5c572 100644
--- a/packages/SettingsLib/res/values-hi/strings.xml
+++ b/packages/SettingsLib/res/values-hi/strings.xml
@@ -206,8 +206,7 @@
<string name="keep_screen_on" msgid="1146389631208760344">"स्क्रीन को चालू रखें"</string>
<string name="keep_screen_on_summary" msgid="2173114350754293009">"चार्ज करते समय स्क्रीन कभी भी कम बैटरी मोड में नहीं जाएगी"</string>
<string name="bt_hci_snoop_log" msgid="3340699311158865670">"ब्लूटूथ HCI स्नूप लॉग चालू करें"</string>
- <!-- no translation found for bt_hci_snoop_log_summary (366083475849911315) -->
- <skip />
+ <string name="bt_hci_snoop_log_summary" msgid="366083475849911315">"सभी ब्लूटूथ एचसीआई पैकेट एक फ़ाइल में कैप्चर करें (यह सेटिंग बदलने के बाद ब्लूटूथ टॉगल करें)"</string>
<string name="oem_unlock_enable" msgid="6040763321967327691">"OEM अनलॉक करना"</string>
<string name="oem_unlock_enable_summary" msgid="4720281828891618376">"बूटलोडर को अनलाॅक किए जाने की अनुमति दें"</string>
<string name="confirm_enable_oem_unlock_title" msgid="4802157344812385674">"OEM अनलॉक करने की अनुमति दें?"</string>
diff --git a/packages/SettingsLib/res/values-hr/strings.xml b/packages/SettingsLib/res/values-hr/strings.xml
index 8f4cff8..ae14171 100644
--- a/packages/SettingsLib/res/values-hr/strings.xml
+++ b/packages/SettingsLib/res/values-hr/strings.xml
@@ -40,10 +40,8 @@
<string name="connected_via_passpoint" msgid="2826205693803088747">"Povezano putem %1$s"</string>
<string name="available_via_passpoint" msgid="1617440946846329613">"Dostupno putem %1$s"</string>
<string name="wifi_connected_no_internet" msgid="8202906332837777829">"Povezano, bez interneta"</string>
- <!-- no translation found for wifi_status_no_internet (5784710974669608361) -->
- <skip />
- <!-- no translation found for wifi_status_sign_in_required (123517180404752756) -->
- <skip />
+ <string name="wifi_status_no_internet" msgid="5784710974669608361">"Nema interneta"</string>
+ <string name="wifi_status_sign_in_required" msgid="123517180404752756">"Obavezna prijava"</string>
<string name="wifi_ap_unable_to_handle_new_sta" msgid="5348824313514404541">"Pristupna je točka privremeno puna"</string>
<string name="connected_via_carrier" msgid="7583780074526041912">"Povezano putem mreže %1$s"</string>
<string name="available_via_carrier" msgid="1469036129740799053">"Dostupno putem mreže %1$s"</string>
@@ -67,12 +65,9 @@
<string name="bluetooth_connected_no_headset_battery_level" msgid="1610296229139400266">"Povezano (bez telefona), baterija <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g><xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g>"</string>
<string name="bluetooth_connected_no_a2dp_battery_level" msgid="3908466636369853652">"Povezano (bez medija), baterija <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g><xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g>"</string>
<string name="bluetooth_connected_no_headset_no_a2dp_battery_level" msgid="1163440823807659316">"Povezano (bez telefona i medija), baterija <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g><xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g>"</string>
- <!-- no translation found for bluetooth_active_battery_level (3149689299296462009) -->
- <skip />
- <!-- no translation found for bluetooth_battery_level (1447164613319663655) -->
- <skip />
- <!-- no translation found for bluetooth_active_no_battery_level (8380223546730241956) -->
- <skip />
+ <string name="bluetooth_active_battery_level" msgid="3149689299296462009">"Aktivan, <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> baterije"</string>
+ <string name="bluetooth_battery_level" msgid="1447164613319663655">"<xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> baterije"</string>
+ <string name="bluetooth_active_no_battery_level" msgid="8380223546730241956">"Aktivan"</string>
<string name="bluetooth_profile_a2dp" msgid="2031475486179830674">"Medijski zvuk"</string>
<string name="bluetooth_profile_headset" msgid="7815495680863246034">"Telefonski pozivi"</string>
<string name="bluetooth_profile_opp" msgid="9168139293654233697">"Prijenos datoteke"</string>
@@ -119,14 +114,10 @@
<string name="bluetooth_talkback_headphone" msgid="26580326066627664">"Slušalice"</string>
<string name="bluetooth_talkback_input_peripheral" msgid="5165842622743212268">"Periferni uređaj za unos"</string>
<string name="bluetooth_talkback_bluetooth" msgid="5615463912185280812">"Bluetooth"</string>
- <!-- no translation found for bluetooth_hearingaid_left_pairing_message (7378813500862148102) -->
- <skip />
- <!-- no translation found for bluetooth_hearingaid_right_pairing_message (1550373802309160891) -->
- <skip />
- <!-- no translation found for bluetooth_hearingaid_left_battery_level (8797811465352097562) -->
- <skip />
- <!-- no translation found for bluetooth_hearingaid_right_battery_level (7309476148173459677) -->
- <skip />
+ <string name="bluetooth_hearingaid_left_pairing_message" msgid="7378813500862148102">"Uparivanje lijevog slušnog aparata…"</string>
+ <string name="bluetooth_hearingaid_right_pairing_message" msgid="1550373802309160891">"Uparivanje desnog slušnog aparata…"</string>
+ <string name="bluetooth_hearingaid_left_battery_level" msgid="8797811465352097562">"Lijeva strana – <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> baterije"</string>
+ <string name="bluetooth_hearingaid_right_battery_level" msgid="7309476148173459677">"Desna strana – <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> baterije"</string>
<string name="accessibility_wifi_off" msgid="1166761729660614716">"Wi-Fi je isključen."</string>
<string name="accessibility_no_wifi" msgid="8834610636137374508">"Wi-Fi je isključen."</string>
<string name="accessibility_wifi_one_bar" msgid="4869376278894301820">"Wi-Fi signal ima jedan stupac."</string>
@@ -246,15 +237,12 @@
<string name="private_dns_mode_opportunistic" msgid="8314986739896927399">"Automatski"</string>
<string name="private_dns_mode_provider" msgid="8354935160639360804">"Naziv hosta davatelja usluge privatnog DNS-a"</string>
<string name="private_dns_mode_provider_hostname_hint" msgid="2487492386970928143">"Unesite naziv hosta davatelja usluge DNS-a"</string>
- <!-- no translation found for private_dns_mode_provider_failure (231837290365031223) -->
- <skip />
+ <string name="private_dns_mode_provider_failure" msgid="231837290365031223">"Povezivanje nije moguće"</string>
<string name="wifi_display_certification_summary" msgid="1155182309166746973">"Prikaži opcije za certifikaciju bežičnog prikaza"</string>
<string name="wifi_verbose_logging_summary" msgid="6615071616111731958">"Povećana razina prijave na Wi‑Fi, prikaz po SSID RSSI-ju u Biraču Wi‑Fi-ja"</string>
<string name="wifi_connected_mac_randomization_summary" msgid="1743059848752201485">"Nasumično odaberi MAC adresu pri povezivanju s Wi-Fi mrežama"</string>
- <!-- no translation found for wifi_metered_label (4514924227256839725) -->
- <skip />
- <!-- no translation found for wifi_unmetered_label (6124098729457992931) -->
- <skip />
+ <string name="wifi_metered_label" msgid="4514924227256839725">"S ograničenim prometom"</string>
+ <string name="wifi_unmetered_label" msgid="6124098729457992931">"Bez ograničenja prometa"</string>
<string name="select_logd_size_title" msgid="7433137108348553508">"Veličine međuspremnika zapisnika"</string>
<string name="select_logd_size_dialog_title" msgid="1206769310236476760">"Odaberite veličinu međuspremnika zapisnika"</string>
<string name="dev_logpersist_clear_warning_title" msgid="684806692440237967">"Želite li izbrisati trajnu pohranu zapisivača?"</string>
diff --git a/packages/SettingsLib/res/values-hu/strings.xml b/packages/SettingsLib/res/values-hu/strings.xml
index 2c31478..6a659be 100644
--- a/packages/SettingsLib/res/values-hu/strings.xml
+++ b/packages/SettingsLib/res/values-hu/strings.xml
@@ -40,10 +40,8 @@
<string name="connected_via_passpoint" msgid="2826205693803088747">"Csatlakozva a következőn keresztül: %1$s"</string>
<string name="available_via_passpoint" msgid="1617440946846329613">"Elérhető a következőn keresztül: %1$s"</string>
<string name="wifi_connected_no_internet" msgid="8202906332837777829">"Csatlakozva, nincs internet-hozzáférés"</string>
- <!-- no translation found for wifi_status_no_internet (5784710974669608361) -->
- <skip />
- <!-- no translation found for wifi_status_sign_in_required (123517180404752756) -->
- <skip />
+ <string name="wifi_status_no_internet" msgid="5784710974669608361">"Nincs internetkapcsolat"</string>
+ <string name="wifi_status_sign_in_required" msgid="123517180404752756">"Bejelentkezést igényel"</string>
<string name="wifi_ap_unable_to_handle_new_sta" msgid="5348824313514404541">"A hozzáférési pont átmenetileg megtelt"</string>
<string name="connected_via_carrier" msgid="7583780074526041912">"Csatlakozva a következőn keresztül: %1$s"</string>
<string name="available_via_carrier" msgid="1469036129740799053">"Elérhető a következőn keresztül: %1$s"</string>
@@ -67,12 +65,9 @@
<string name="bluetooth_connected_no_headset_battery_level" msgid="1610296229139400266">"Csatlakoztatva (telefonhang nélkül); az akkumulátor töltöttségi szintje: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g><xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g>"</string>
<string name="bluetooth_connected_no_a2dp_battery_level" msgid="3908466636369853652">"Csatlakoztatva (médiahang nélkül); az akkumulátor töltöttségi szintje: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g><xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g>"</string>
<string name="bluetooth_connected_no_headset_no_a2dp_battery_level" msgid="1163440823807659316">"Csatlakoztatva (nincs telefon- és médiahang); az akkumulátor töltöttségi szintje: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g><xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g>"</string>
- <!-- no translation found for bluetooth_active_battery_level (3149689299296462009) -->
- <skip />
- <!-- no translation found for bluetooth_battery_level (1447164613319663655) -->
- <skip />
- <!-- no translation found for bluetooth_active_no_battery_level (8380223546730241956) -->
- <skip />
+ <string name="bluetooth_active_battery_level" msgid="3149689299296462009">"Aktív, <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>-os töltöttség"</string>
+ <string name="bluetooth_battery_level" msgid="1447164613319663655">"Akkumulátor: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
+ <string name="bluetooth_active_no_battery_level" msgid="8380223546730241956">"Aktív"</string>
<string name="bluetooth_profile_a2dp" msgid="2031475486179830674">"Média audió"</string>
<string name="bluetooth_profile_headset" msgid="7815495680863246034">"Telefonhívások"</string>
<string name="bluetooth_profile_opp" msgid="9168139293654233697">"Fájlátvitel"</string>
@@ -119,14 +114,10 @@
<string name="bluetooth_talkback_headphone" msgid="26580326066627664">"Fejhallgató"</string>
<string name="bluetooth_talkback_input_peripheral" msgid="5165842622743212268">"Beviteli periféria"</string>
<string name="bluetooth_talkback_bluetooth" msgid="5615463912185280812">"Bluetooth"</string>
- <!-- no translation found for bluetooth_hearingaid_left_pairing_message (7378813500862148102) -->
- <skip />
- <!-- no translation found for bluetooth_hearingaid_right_pairing_message (1550373802309160891) -->
- <skip />
- <!-- no translation found for bluetooth_hearingaid_left_battery_level (8797811465352097562) -->
- <skip />
- <!-- no translation found for bluetooth_hearingaid_right_battery_level (7309476148173459677) -->
- <skip />
+ <string name="bluetooth_hearingaid_left_pairing_message" msgid="7378813500862148102">"Bal oldali hallókészülék párosítása…"</string>
+ <string name="bluetooth_hearingaid_right_pairing_message" msgid="1550373802309160891">"Jobb oldali hallókészülék párosítása…"</string>
+ <string name="bluetooth_hearingaid_left_battery_level" msgid="8797811465352097562">"Bal oldali – <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>-os töltöttség"</string>
+ <string name="bluetooth_hearingaid_right_battery_level" msgid="7309476148173459677">"Jobb oldali – <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>-os töltöttség"</string>
<string name="accessibility_wifi_off" msgid="1166761729660614716">"Wi-Fi kikapcsolva."</string>
<string name="accessibility_no_wifi" msgid="8834610636137374508">"Nincs Wi-Fi-kapcsolat."</string>
<string name="accessibility_wifi_one_bar" msgid="4869376278894301820">"Wi-Fi-jel: egy sáv."</string>
@@ -246,15 +237,12 @@
<string name="private_dns_mode_opportunistic" msgid="8314986739896927399">"Automatikus"</string>
<string name="private_dns_mode_provider" msgid="8354935160639360804">"Privát DNS-szolgáltató gazdagépneve"</string>
<string name="private_dns_mode_provider_hostname_hint" msgid="2487492386970928143">"Adja meg a DNS-szolgáltató gazdagépnevét"</string>
- <!-- no translation found for private_dns_mode_provider_failure (231837290365031223) -->
- <skip />
+ <string name="private_dns_mode_provider_failure" msgid="231837290365031223">"Nem sikerült kapcsolódni"</string>
<string name="wifi_display_certification_summary" msgid="1155182309166746973">"Vezeték nélküli kijelző tanúsítványával kapcsolatos lehetőségek megjelenítése"</string>
<string name="wifi_verbose_logging_summary" msgid="6615071616111731958">"Wi‑Fi-naplózási szint növelése, RSSI/SSID megjelenítése a Wi‑Fi-választóban"</string>
<string name="wifi_connected_mac_randomization_summary" msgid="1743059848752201485">"MAC-cím véletlenszerű generálása Wi‑Fi-hálózatra való csatlakozáskor"</string>
- <!-- no translation found for wifi_metered_label (4514924227256839725) -->
- <skip />
- <!-- no translation found for wifi_unmetered_label (6124098729457992931) -->
- <skip />
+ <string name="wifi_metered_label" msgid="4514924227256839725">"Forgalomkorlátos"</string>
+ <string name="wifi_unmetered_label" msgid="6124098729457992931">"Nem forgalomkorlátos"</string>
<string name="select_logd_size_title" msgid="7433137108348553508">"Naplózási puffer mérete"</string>
<string name="select_logd_size_dialog_title" msgid="1206769310236476760">"Naplózási pufferméret kiválasztása"</string>
<string name="dev_logpersist_clear_warning_title" msgid="684806692440237967">"Törli a naplózó program állandó tárhelyét?"</string>
diff --git a/packages/SettingsLib/res/values-hy/strings.xml b/packages/SettingsLib/res/values-hy/strings.xml
index de2cfc9..0b821ed 100644
--- a/packages/SettingsLib/res/values-hy/strings.xml
+++ b/packages/SettingsLib/res/values-hy/strings.xml
@@ -40,10 +40,8 @@
<string name="connected_via_passpoint" msgid="2826205693803088747">"Կապակցված է %1$s-ի միջոցով"</string>
<string name="available_via_passpoint" msgid="1617440946846329613">"Հասանելի է %1$s-ի միջոցով"</string>
<string name="wifi_connected_no_internet" msgid="8202906332837777829">"Միացված է, սակայն ինտերնետ կապ չկա"</string>
- <!-- no translation found for wifi_status_no_internet (5784710974669608361) -->
- <skip />
- <!-- no translation found for wifi_status_sign_in_required (123517180404752756) -->
- <skip />
+ <string name="wifi_status_no_internet" msgid="5784710974669608361">"Ինտերնետ կապ չկա"</string>
+ <string name="wifi_status_sign_in_required" msgid="123517180404752756">"Անհրաժեշտ է մուտք գործել"</string>
<string name="wifi_ap_unable_to_handle_new_sta" msgid="5348824313514404541">"Հասանելիության կետը ժամանակավորապես լիքն է"</string>
<string name="connected_via_carrier" msgid="7583780074526041912">"Միացված է %1$s-ի միջոցով"</string>
<string name="available_via_carrier" msgid="1469036129740799053">"Հասանելի է %1$s-ի միջոցով"</string>
@@ -67,12 +65,9 @@
<string name="bluetooth_connected_no_headset_battery_level" msgid="1610296229139400266">"Միացված է (հեռախոս չկա), մարտկոցի լիցքը՝ <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g><xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g>"</string>
<string name="bluetooth_connected_no_a2dp_battery_level" msgid="3908466636369853652">"Միացված է (մեդիա չկա), մարտկոցի լիցքը՝ <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g><xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g>"</string>
<string name="bluetooth_connected_no_headset_no_a2dp_battery_level" msgid="1163440823807659316">"Միացված է (հեռախոս կամ մեդիա չկա), մարտկոցի լիցքը՝ <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g><xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g>"</string>
- <!-- no translation found for bluetooth_active_battery_level (3149689299296462009) -->
- <skip />
- <!-- no translation found for bluetooth_battery_level (1447164613319663655) -->
- <skip />
- <!-- no translation found for bluetooth_active_no_battery_level (8380223546730241956) -->
- <skip />
+ <string name="bluetooth_active_battery_level" msgid="3149689299296462009">"Ակտիվ է։ Մարտկոցի լիցքը՝ <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
+ <string name="bluetooth_battery_level" msgid="1447164613319663655">"Մարտկոցի լիցքը՝ <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
+ <string name="bluetooth_active_no_battery_level" msgid="8380223546730241956">"Ակտիվ է"</string>
<string name="bluetooth_profile_a2dp" msgid="2031475486179830674">"Մեդիա աուդիո"</string>
<string name="bluetooth_profile_headset" msgid="7815495680863246034">"Հեռախոսազանգեր"</string>
<string name="bluetooth_profile_opp" msgid="9168139293654233697">"Ֆայլերի փոխանցում"</string>
@@ -119,14 +114,10 @@
<string name="bluetooth_talkback_headphone" msgid="26580326066627664">"Ականջակալ"</string>
<string name="bluetooth_talkback_input_peripheral" msgid="5165842622743212268">"Մուտքի արտաքին սարքեր"</string>
<string name="bluetooth_talkback_bluetooth" msgid="5615463912185280812">"Bluetooth"</string>
- <!-- no translation found for bluetooth_hearingaid_left_pairing_message (7378813500862148102) -->
- <skip />
- <!-- no translation found for bluetooth_hearingaid_right_pairing_message (1550373802309160891) -->
- <skip />
- <!-- no translation found for bluetooth_hearingaid_left_battery_level (8797811465352097562) -->
- <skip />
- <!-- no translation found for bluetooth_hearingaid_right_battery_level (7309476148173459677) -->
- <skip />
+ <string name="bluetooth_hearingaid_left_pairing_message" msgid="7378813500862148102">"Զուգակցվում է ձախ լսողական ապարատի հետ…"</string>
+ <string name="bluetooth_hearingaid_right_pairing_message" msgid="1550373802309160891">"Զուգակցվում է աջ լսողական ապարատի հետ…"</string>
+ <string name="bluetooth_hearingaid_left_battery_level" msgid="8797811465352097562">"Ձախ լսողական ապարատ – մարտկոցի լիցքը՝ <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
+ <string name="bluetooth_hearingaid_right_battery_level" msgid="7309476148173459677">"Աջ լսողական ապարատ – մարտկոցի լիցքը՝ <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
<string name="accessibility_wifi_off" msgid="1166761729660614716">"Wi-Fi-ն անջատված է:"</string>
<string name="accessibility_no_wifi" msgid="8834610636137374508">"Wi-Fi-ը կապակցված չէ:"</string>
<string name="accessibility_wifi_one_bar" msgid="4869376278894301820">"Wi-Fi-ի ուժգնությունը՝ մեկ գիծ:"</string>
@@ -246,15 +237,12 @@
<string name="private_dns_mode_opportunistic" msgid="8314986739896927399">"Ավտոմատ"</string>
<string name="private_dns_mode_provider" msgid="8354935160639360804">"Անհատական DNS ծառայության մատակարարի խնամորդի անունը"</string>
<string name="private_dns_mode_provider_hostname_hint" msgid="2487492386970928143">"Մուտքագրեք DNS ծառայության մատակարարի խնամորդի անունը"</string>
- <!-- no translation found for private_dns_mode_provider_failure (231837290365031223) -->
- <skip />
+ <string name="private_dns_mode_provider_failure" msgid="231837290365031223">"Չհաջողվեց միանալ"</string>
<string name="wifi_display_certification_summary" msgid="1155182309166746973">"Ցույց տալ անլար էկրանի հավաստագրման ընտրանքները"</string>
<string name="wifi_verbose_logging_summary" msgid="6615071616111731958">"Բարձրացնել մակարդակը, Wi‑Fi ընտրիչում ամեն մի SSID-ի համար ցույց տալ RSSI"</string>
<string name="wifi_connected_mac_randomization_summary" msgid="1743059848752201485">"Պատահականորեն ընտրել MAC հասցեն Wi-Fi ցանցերին միանալիս"</string>
- <!-- no translation found for wifi_metered_label (4514924227256839725) -->
- <skip />
- <!-- no translation found for wifi_unmetered_label (6124098729457992931) -->
- <skip />
+ <string name="wifi_metered_label" msgid="4514924227256839725">"Վճարովի թրաֆիկ"</string>
+ <string name="wifi_unmetered_label" msgid="6124098729457992931">"Անսահմանափակ թրաֆիկ"</string>
<string name="select_logd_size_title" msgid="7433137108348553508">"Տեղեկամատյանի պահնակի չափերը"</string>
<string name="select_logd_size_dialog_title" msgid="1206769310236476760">"Ընտրեք տեղեկամատյանի չափը մեկ պահնակի համար"</string>
<string name="dev_logpersist_clear_warning_title" msgid="684806692440237967">"Ջնջե՞լ մատյանի մշտական հիշողությունը:"</string>
diff --git a/packages/SettingsLib/res/values-it/strings.xml b/packages/SettingsLib/res/values-it/strings.xml
index d2f5ff1..38251b3 100644
--- a/packages/SettingsLib/res/values-it/strings.xml
+++ b/packages/SettingsLib/res/values-it/strings.xml
@@ -40,10 +40,8 @@
<string name="connected_via_passpoint" msgid="2826205693803088747">"Collegato tramite %1$s"</string>
<string name="available_via_passpoint" msgid="1617440946846329613">"Disponibile tramite %1$s"</string>
<string name="wifi_connected_no_internet" msgid="8202906332837777829">"Connesso, senza Internet"</string>
- <!-- no translation found for wifi_status_no_internet (5784710974669608361) -->
- <skip />
- <!-- no translation found for wifi_status_sign_in_required (123517180404752756) -->
- <skip />
+ <string name="wifi_status_no_internet" msgid="5784710974669608361">"Nessuna connessione a Internet"</string>
+ <string name="wifi_status_sign_in_required" msgid="123517180404752756">"Accesso richiesto"</string>
<string name="wifi_ap_unable_to_handle_new_sta" msgid="5348824313514404541">"Punto di accesso momentaneamente al completo"</string>
<string name="connected_via_carrier" msgid="7583780074526041912">"Connesso tramite %1$s"</string>
<string name="available_via_carrier" msgid="1469036129740799053">"Disponibile tramite %1$s"</string>
@@ -67,12 +65,9 @@
<string name="bluetooth_connected_no_headset_battery_level" msgid="1610296229139400266">"<xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g> connesso (telefono escluso), batteria al <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
<string name="bluetooth_connected_no_a2dp_battery_level" msgid="3908466636369853652">"<xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g> connesso (contenuti multimediali esclusi), batteria al <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
<string name="bluetooth_connected_no_headset_no_a2dp_battery_level" msgid="1163440823807659316">"<xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g> connesso (telefono o contenuti multimediali esclusi), batteria al <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
- <!-- no translation found for bluetooth_active_battery_level (3149689299296462009) -->
- <skip />
- <!-- no translation found for bluetooth_battery_level (1447164613319663655) -->
- <skip />
- <!-- no translation found for bluetooth_active_no_battery_level (8380223546730241956) -->
- <skip />
+ <string name="bluetooth_active_battery_level" msgid="3149689299296462009">"Attivo, <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> di batteria"</string>
+ <string name="bluetooth_battery_level" msgid="1447164613319663655">"Batteria: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
+ <string name="bluetooth_active_no_battery_level" msgid="8380223546730241956">"Attivo"</string>
<string name="bluetooth_profile_a2dp" msgid="2031475486179830674">"Audio multimediale"</string>
<string name="bluetooth_profile_headset" msgid="7815495680863246034">"Telefonate"</string>
<string name="bluetooth_profile_opp" msgid="9168139293654233697">"Trasferimento file"</string>
@@ -119,14 +114,10 @@
<string name="bluetooth_talkback_headphone" msgid="26580326066627664">"Cuffie"</string>
<string name="bluetooth_talkback_input_peripheral" msgid="5165842622743212268">"Periferica di immissione"</string>
<string name="bluetooth_talkback_bluetooth" msgid="5615463912185280812">"Bluetooth"</string>
- <!-- no translation found for bluetooth_hearingaid_left_pairing_message (7378813500862148102) -->
- <skip />
- <!-- no translation found for bluetooth_hearingaid_right_pairing_message (1550373802309160891) -->
- <skip />
- <!-- no translation found for bluetooth_hearingaid_left_battery_level (8797811465352097562) -->
- <skip />
- <!-- no translation found for bluetooth_hearingaid_right_battery_level (7309476148173459677) -->
- <skip />
+ <string name="bluetooth_hearingaid_left_pairing_message" msgid="7378813500862148102">"Accoppiamento dell\'apparecchio acustico sinistro…"</string>
+ <string name="bluetooth_hearingaid_right_pairing_message" msgid="1550373802309160891">"Accoppiamento dell\'apparecchio acustico destro…"</string>
+ <string name="bluetooth_hearingaid_left_battery_level" msgid="8797811465352097562">"Sinistro - Batteria: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
+ <string name="bluetooth_hearingaid_right_battery_level" msgid="7309476148173459677">"Destro - Batteria: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
<string name="accessibility_wifi_off" msgid="1166761729660614716">"Wi-Fi non attivo."</string>
<string name="accessibility_no_wifi" msgid="8834610636137374508">"Rete Wi-Fi scollegata."</string>
<string name="accessibility_wifi_one_bar" msgid="4869376278894301820">"Wi-Fi: una barra."</string>
@@ -246,15 +237,12 @@
<string name="private_dns_mode_opportunistic" msgid="8314986739896927399">"Automatico"</string>
<string name="private_dns_mode_provider" msgid="8354935160639360804">"Nome host del provider DNS privato"</string>
<string name="private_dns_mode_provider_hostname_hint" msgid="2487492386970928143">"Inserisci il nome host del provider DNS"</string>
- <!-- no translation found for private_dns_mode_provider_failure (231837290365031223) -->
- <skip />
+ <string name="private_dns_mode_provider_failure" msgid="231837290365031223">"Impossibile collegarsi"</string>
<string name="wifi_display_certification_summary" msgid="1155182309166746973">"Mostra opzioni per la certificazione display wireless"</string>
<string name="wifi_verbose_logging_summary" msgid="6615071616111731958">"Aumenta il livello di registrazione Wi-Fi, mostrando il SSID RSSI nel selettore Wi-Fi"</string>
<string name="wifi_connected_mac_randomization_summary" msgid="1743059848752201485">"Seleziona indirizzo MAC casuale con reti Wi-Fi collegate"</string>
- <!-- no translation found for wifi_metered_label (4514924227256839725) -->
- <skip />
- <!-- no translation found for wifi_unmetered_label (6124098729457992931) -->
- <skip />
+ <string name="wifi_metered_label" msgid="4514924227256839725">"A consumo"</string>
+ <string name="wifi_unmetered_label" msgid="6124098729457992931">"Non a consumo"</string>
<string name="select_logd_size_title" msgid="7433137108348553508">"Dimensioni buffer Logger"</string>
<string name="select_logd_size_dialog_title" msgid="1206769310236476760">"Seleziona dimensioni Logger per buffer log"</string>
<string name="dev_logpersist_clear_warning_title" msgid="684806692440237967">"Cancellare i dati nello spazio di archiviazione permanente del logger?"</string>
diff --git a/packages/SettingsLib/res/values-iw/strings.xml b/packages/SettingsLib/res/values-iw/strings.xml
index 666ca76..48b037f 100644
--- a/packages/SettingsLib/res/values-iw/strings.xml
+++ b/packages/SettingsLib/res/values-iw/strings.xml
@@ -40,10 +40,8 @@
<string name="connected_via_passpoint" msgid="2826205693803088747">"מחובר דרך %1$s"</string>
<string name="available_via_passpoint" msgid="1617440946846329613">"זמינה דרך %1$s"</string>
<string name="wifi_connected_no_internet" msgid="8202906332837777829">"מחובר. אין אינטרנט"</string>
- <!-- no translation found for wifi_status_no_internet (5784710974669608361) -->
- <skip />
- <!-- no translation found for wifi_status_sign_in_required (123517180404752756) -->
- <skip />
+ <string name="wifi_status_no_internet" msgid="5784710974669608361">"אין אינטרנט"</string>
+ <string name="wifi_status_sign_in_required" msgid="123517180404752756">"נדרשת כניסה"</string>
<string name="wifi_ap_unable_to_handle_new_sta" msgid="5348824313514404541">"נקודת הגישה מלאה באופן זמני"</string>
<string name="connected_via_carrier" msgid="7583780074526041912">"מחובר לרשת של %1$s"</string>
<string name="available_via_carrier" msgid="1469036129740799053">"זמינה דרך %1$s"</string>
@@ -67,12 +65,9 @@
<string name="bluetooth_connected_no_headset_battery_level" msgid="1610296229139400266">"מחובר (ללא טלפון), שיעור הסוללה <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g><xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g>"</string>
<string name="bluetooth_connected_no_a2dp_battery_level" msgid="3908466636369853652">"מחובר (ללא מדיה), שיעור הסוללה <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g><xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g>"</string>
<string name="bluetooth_connected_no_headset_no_a2dp_battery_level" msgid="1163440823807659316">"מחובר (ללא טלפון או מדיה), שיעור הסוללה <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g><xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g>"</string>
- <!-- no translation found for bluetooth_active_battery_level (3149689299296462009) -->
- <skip />
- <!-- no translation found for bluetooth_battery_level (1447164613319663655) -->
- <skip />
- <!-- no translation found for bluetooth_active_no_battery_level (8380223546730241956) -->
- <skip />
+ <string name="bluetooth_active_battery_level" msgid="3149689299296462009">"פעיל, טעינת הסוללה: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
+ <string name="bluetooth_battery_level" msgid="1447164613319663655">"טעינת הסוללה: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
+ <string name="bluetooth_active_no_battery_level" msgid="8380223546730241956">"פעיל"</string>
<string name="bluetooth_profile_a2dp" msgid="2031475486179830674">"אודיו של מדיה"</string>
<string name="bluetooth_profile_headset" msgid="7815495680863246034">"שיחות טלפון"</string>
<string name="bluetooth_profile_opp" msgid="9168139293654233697">"העברת קבצים"</string>
@@ -119,14 +114,10 @@
<string name="bluetooth_talkback_headphone" msgid="26580326066627664">"אוזנייה"</string>
<string name="bluetooth_talkback_input_peripheral" msgid="5165842622743212268">"ציוד קלט היקפי"</string>
<string name="bluetooth_talkback_bluetooth" msgid="5615463912185280812">"Bluetooth"</string>
- <!-- no translation found for bluetooth_hearingaid_left_pairing_message (7378813500862148102) -->
- <skip />
- <!-- no translation found for bluetooth_hearingaid_right_pairing_message (1550373802309160891) -->
- <skip />
- <!-- no translation found for bluetooth_hearingaid_left_battery_level (8797811465352097562) -->
- <skip />
- <!-- no translation found for bluetooth_hearingaid_right_battery_level (7309476148173459677) -->
- <skip />
+ <string name="bluetooth_hearingaid_left_pairing_message" msgid="7378813500862148102">"מתבצעת התאמה של מכשיר שמיעה שמאלי…"</string>
+ <string name="bluetooth_hearingaid_right_pairing_message" msgid="1550373802309160891">"מתבצעת התאמה של מכשיר שמיעה ימני…"</string>
+ <string name="bluetooth_hearingaid_left_battery_level" msgid="8797811465352097562">"שמאלי - טעינת הסוללה: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
+ <string name="bluetooth_hearingaid_right_battery_level" msgid="7309476148173459677">"ימני - טעינת הסוללה: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
<string name="accessibility_wifi_off" msgid="1166761729660614716">"Wi-Fi כבוי."</string>
<string name="accessibility_no_wifi" msgid="8834610636137374508">"Wi-Fi מנותק."</string>
<string name="accessibility_wifi_one_bar" msgid="4869376278894301820">"פס אחד של Wi-Fi."</string>
@@ -206,8 +197,7 @@
<string name="keep_screen_on" msgid="1146389631208760344">"השאר פועל"</string>
<string name="keep_screen_on_summary" msgid="2173114350754293009">"המסך לעולם לא יהיה במצב שינה במהלך טעינה"</string>
<string name="bt_hci_snoop_log" msgid="3340699311158865670">"הפעלת Snoop Log של Bluetooth HCI"</string>
- <!-- no translation found for bt_hci_snoop_log_summary (366083475849911315) -->
- <skip />
+ <string name="bt_hci_snoop_log_summary" msgid="366083475849911315">"איחוד של כל חבילות Bluetooth HCI בקובץ (יש להחליף מצב Bluetooth לאחר שינוי הגדרה זו)"</string>
<string name="oem_unlock_enable" msgid="6040763321967327691">"ביטול נעילה של OEM"</string>
<string name="oem_unlock_enable_summary" msgid="4720281828891618376">"אפשר ביטול של נעילת מנהל האתחול"</string>
<string name="confirm_enable_oem_unlock_title" msgid="4802157344812385674">"האם לאפשר ביטול נעילה של OEM (יצרן ציוד מקורי)?"</string>
@@ -247,15 +237,12 @@
<string name="private_dns_mode_opportunistic" msgid="8314986739896927399">"באופן אוטומטי"</string>
<string name="private_dns_mode_provider" msgid="8354935160639360804">"שם מארח של ספק DNS פרטי"</string>
<string name="private_dns_mode_provider_hostname_hint" msgid="2487492386970928143">"צריך להזין את שם המארח של ספק DNS"</string>
- <!-- no translation found for private_dns_mode_provider_failure (231837290365031223) -->
- <skip />
+ <string name="private_dns_mode_provider_failure" msgid="231837290365031223">"לא ניתן היה להתחבר"</string>
<string name="wifi_display_certification_summary" msgid="1155182309166746973">"הצג אפשרויות עבור אישור של תצוגת WiFi"</string>
<string name="wifi_verbose_logging_summary" msgid="6615071616111731958">"העלה את רמת הרישום של Wi‑Fi ביומן, הצג לכל SSID RSSI ב-Wi‑Fi Picker"</string>
<string name="wifi_connected_mac_randomization_summary" msgid="1743059848752201485">"יצירת כתובת MAC אקראית בהתחברות לרשתות Wi-Fi"</string>
- <!-- no translation found for wifi_metered_label (4514924227256839725) -->
- <skip />
- <!-- no translation found for wifi_unmetered_label (6124098729457992931) -->
- <skip />
+ <string name="wifi_metered_label" msgid="4514924227256839725">"נמדדת"</string>
+ <string name="wifi_unmetered_label" msgid="6124098729457992931">"לא נמדדת"</string>
<string name="select_logd_size_title" msgid="7433137108348553508">"גדלי מאגר של יומן רישום"</string>
<string name="select_logd_size_dialog_title" msgid="1206769310236476760">"בחר גדלים של יוצר יומן לכל מאגר יומן"</string>
<string name="dev_logpersist_clear_warning_title" msgid="684806692440237967">"האם למחוק את אחסון המתעד המתמיד?"</string>
diff --git a/packages/SettingsLib/res/values-ja/strings.xml b/packages/SettingsLib/res/values-ja/strings.xml
index 6422103..dae07e2 100644
--- a/packages/SettingsLib/res/values-ja/strings.xml
+++ b/packages/SettingsLib/res/values-ja/strings.xml
@@ -40,10 +40,8 @@
<string name="connected_via_passpoint" msgid="2826205693803088747">"%1$s経由で接続"</string>
<string name="available_via_passpoint" msgid="1617440946846329613">"%1$s経由で使用可能"</string>
<string name="wifi_connected_no_internet" msgid="8202906332837777829">"接続済み、インターネット接続なし"</string>
- <!-- no translation found for wifi_status_no_internet (5784710974669608361) -->
- <skip />
- <!-- no translation found for wifi_status_sign_in_required (123517180404752756) -->
- <skip />
+ <string name="wifi_status_no_internet" msgid="5784710974669608361">"インターネット未接続"</string>
+ <string name="wifi_status_sign_in_required" msgid="123517180404752756">"ログインが必要"</string>
<string name="wifi_ap_unable_to_handle_new_sta" msgid="5348824313514404541">"アクセス ポイントが一時的にいっぱいです"</string>
<string name="connected_via_carrier" msgid="7583780074526041912">"%1$s 経由で接続済み"</string>
<string name="available_via_carrier" msgid="1469036129740799053">"%1$s 経由で使用可能"</string>
@@ -67,12 +65,9 @@
<string name="bluetooth_connected_no_headset_battery_level" msgid="1610296229139400266">"接続済み(電話なし)、電池残量 <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>: <xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g>"</string>
<string name="bluetooth_connected_no_a2dp_battery_level" msgid="3908466636369853652">"接続済み(メディアなし)、電池残量 <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>: <xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g>"</string>
<string name="bluetooth_connected_no_headset_no_a2dp_battery_level" msgid="1163440823807659316">"接続済み(電話、メディアなし)、電池残量 <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>: <xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g>"</string>
- <!-- no translation found for bluetooth_active_battery_level (3149689299296462009) -->
- <skip />
- <!-- no translation found for bluetooth_battery_level (1447164613319663655) -->
- <skip />
- <!-- no translation found for bluetooth_active_no_battery_level (8380223546730241956) -->
- <skip />
+ <string name="bluetooth_active_battery_level" msgid="3149689299296462009">"有効、電池 <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
+ <string name="bluetooth_battery_level" msgid="1447164613319663655">"電池 <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
+ <string name="bluetooth_active_no_battery_level" msgid="8380223546730241956">"有効"</string>
<string name="bluetooth_profile_a2dp" msgid="2031475486179830674">"メディアの音声"</string>
<string name="bluetooth_profile_headset" msgid="7815495680863246034">"電話"</string>
<string name="bluetooth_profile_opp" msgid="9168139293654233697">"ファイル転送"</string>
@@ -119,14 +114,10 @@
<string name="bluetooth_talkback_headphone" msgid="26580326066627664">"ヘッドフォン"</string>
<string name="bluetooth_talkback_input_peripheral" msgid="5165842622743212268">"入力用周辺機器"</string>
<string name="bluetooth_talkback_bluetooth" msgid="5615463912185280812">"Bluetooth"</string>
- <!-- no translation found for bluetooth_hearingaid_left_pairing_message (7378813500862148102) -->
- <skip />
- <!-- no translation found for bluetooth_hearingaid_right_pairing_message (1550373802309160891) -->
- <skip />
- <!-- no translation found for bluetooth_hearingaid_left_battery_level (8797811465352097562) -->
- <skip />
- <!-- no translation found for bluetooth_hearingaid_right_battery_level (7309476148173459677) -->
- <skip />
+ <string name="bluetooth_hearingaid_left_pairing_message" msgid="7378813500862148102">"左側の補聴器とペア設定しています…"</string>
+ <string name="bluetooth_hearingaid_right_pairing_message" msgid="1550373802309160891">"右側の補聴器とペア設定しています…"</string>
+ <string name="bluetooth_hearingaid_left_battery_level" msgid="8797811465352097562">"左側 - 電池 <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
+ <string name="bluetooth_hearingaid_right_battery_level" msgid="7309476148173459677">"右側 - 電池 <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
<string name="accessibility_wifi_off" msgid="1166761729660614716">"Wi-FiはOFFです。"</string>
<string name="accessibility_no_wifi" msgid="8834610636137374508">"Wi-Fiが切断されました。"</string>
<string name="accessibility_wifi_one_bar" msgid="4869376278894301820">"Wi-Fiはレベル1です。"</string>
@@ -246,15 +237,12 @@
<string name="private_dns_mode_opportunistic" msgid="8314986739896927399">"自動"</string>
<string name="private_dns_mode_provider" msgid="8354935160639360804">"プライベート DNS プロバイダのホスト名"</string>
<string name="private_dns_mode_provider_hostname_hint" msgid="2487492386970928143">"DNS プロバイダのホスト名を入力"</string>
- <!-- no translation found for private_dns_mode_provider_failure (231837290365031223) -->
- <skip />
+ <string name="private_dns_mode_provider_failure" msgid="231837290365031223">"接続できませんでした"</string>
<string name="wifi_display_certification_summary" msgid="1155182309166746973">"ワイヤレスディスプレイ認証のオプションを表示"</string>
<string name="wifi_verbose_logging_summary" msgid="6615071616111731958">"Wi-Fiログレベルを上げて、Wi-Fi選択ツールでSSID RSSIごとに表示します"</string>
<string name="wifi_connected_mac_randomization_summary" msgid="1743059848752201485">"Wi-Fi ネットワーク接続時の MAC アドレスのランダム化"</string>
- <!-- no translation found for wifi_metered_label (4514924227256839725) -->
- <skip />
- <!-- no translation found for wifi_unmetered_label (6124098729457992931) -->
- <skip />
+ <string name="wifi_metered_label" msgid="4514924227256839725">"従量制"</string>
+ <string name="wifi_unmetered_label" msgid="6124098729457992931">"定額制"</string>
<string name="select_logd_size_title" msgid="7433137108348553508">"ログバッファのサイズ"</string>
<string name="select_logd_size_dialog_title" msgid="1206769310236476760">"各ログバッファのログサイズを選択"</string>
<string name="dev_logpersist_clear_warning_title" msgid="684806692440237967">"ログの永続ストレージを消去しますか?"</string>
diff --git a/packages/SettingsLib/res/values-ka/strings.xml b/packages/SettingsLib/res/values-ka/strings.xml
index d6271f0..84fd1e1a 100644
--- a/packages/SettingsLib/res/values-ka/strings.xml
+++ b/packages/SettingsLib/res/values-ka/strings.xml
@@ -40,10 +40,8 @@
<string name="connected_via_passpoint" msgid="2826205693803088747">"%1$s-ით დაკავშირებული"</string>
<string name="available_via_passpoint" msgid="1617440946846329613">"ხელმისაწვდომია %1$s-ით"</string>
<string name="wifi_connected_no_internet" msgid="8202906332837777829">"დაკავშირებულია, ინტერნეტის გარეშე"</string>
- <!-- no translation found for wifi_status_no_internet (5784710974669608361) -->
- <skip />
- <!-- no translation found for wifi_status_sign_in_required (123517180404752756) -->
- <skip />
+ <string name="wifi_status_no_internet" msgid="5784710974669608361">"ინტერნეტ-კავშირი არ არის"</string>
+ <string name="wifi_status_sign_in_required" msgid="123517180404752756">"აუცილებელია სისტემაში შესვლა"</string>
<string name="wifi_ap_unable_to_handle_new_sta" msgid="5348824313514404541">"წვდომის წერტილი დროებით გადატვირთულია"</string>
<string name="connected_via_carrier" msgid="7583780074526041912">"%1$s-ით დაკავშირებული"</string>
<string name="available_via_carrier" msgid="1469036129740799053">"ხელმისაწვდომია %1$s-ით"</string>
@@ -67,12 +65,9 @@
<string name="bluetooth_connected_no_headset_battery_level" msgid="1610296229139400266">"დაკავშირებულია (ტელეფონი არ არის). ბატარეის დონე: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g><xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g>"</string>
<string name="bluetooth_connected_no_a2dp_battery_level" msgid="3908466636369853652">"დაკავშირებულია (მედია არ არის). ბატარეა: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g><xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g>"</string>
<string name="bluetooth_connected_no_headset_no_a2dp_battery_level" msgid="1163440823807659316">"დაკავშირებულია (ტელეფონი ან მედია არ არის). ბატარეის დონე: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g><xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g>"</string>
- <!-- no translation found for bluetooth_active_battery_level (3149689299296462009) -->
- <skip />
- <!-- no translation found for bluetooth_battery_level (1447164613319663655) -->
- <skip />
- <!-- no translation found for bluetooth_active_no_battery_level (8380223546730241956) -->
- <skip />
+ <string name="bluetooth_active_battery_level" msgid="3149689299296462009">"აქტიურია, ბატარეა <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>-ს შეადგენს"</string>
+ <string name="bluetooth_battery_level" msgid="1447164613319663655">"<xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> ბატარეა"</string>
+ <string name="bluetooth_active_no_battery_level" msgid="8380223546730241956">"აქტიური"</string>
<string name="bluetooth_profile_a2dp" msgid="2031475486179830674">"მედია აუდიო"</string>
<string name="bluetooth_profile_headset" msgid="7815495680863246034">"სატელეფონო ზარები"</string>
<string name="bluetooth_profile_opp" msgid="9168139293654233697">"ფაილების გადაცემა"</string>
@@ -119,14 +114,10 @@
<string name="bluetooth_talkback_headphone" msgid="26580326066627664">"ყურსასმენი"</string>
<string name="bluetooth_talkback_input_peripheral" msgid="5165842622743212268">"შეყვანის პერიფერიული მოწყობილობა"</string>
<string name="bluetooth_talkback_bluetooth" msgid="5615463912185280812">"Bluetooth"</string>
- <!-- no translation found for bluetooth_hearingaid_left_pairing_message (7378813500862148102) -->
- <skip />
- <!-- no translation found for bluetooth_hearingaid_right_pairing_message (1550373802309160891) -->
- <skip />
- <!-- no translation found for bluetooth_hearingaid_left_battery_level (8797811465352097562) -->
- <skip />
- <!-- no translation found for bluetooth_hearingaid_right_battery_level (7309476148173459677) -->
- <skip />
+ <string name="bluetooth_hearingaid_left_pairing_message" msgid="7378813500862148102">"მიმდინარეობს მარცხენა სმენის აპარატის დაწყვილება…"</string>
+ <string name="bluetooth_hearingaid_right_pairing_message" msgid="1550373802309160891">"მიმდინარეობს მარჯვენა სმენის აპარატის დაწყვილება…"</string>
+ <string name="bluetooth_hearingaid_left_battery_level" msgid="8797811465352097562">"მარცხენა — <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> ბატარეა"</string>
+ <string name="bluetooth_hearingaid_right_battery_level" msgid="7309476148173459677">"მარჯვენა — <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> ბატარეა"</string>
<string name="accessibility_wifi_off" msgid="1166761729660614716">"WiFi გამორთულია."</string>
<string name="accessibility_no_wifi" msgid="8834610636137374508">"WiFi არ არის დაკავშირებული."</string>
<string name="accessibility_wifi_one_bar" msgid="4869376278894301820">"WiFi სიგნალი ერთ ზოლზეა."</string>
@@ -246,15 +237,12 @@
<string name="private_dns_mode_opportunistic" msgid="8314986739896927399">"ავტომატური"</string>
<string name="private_dns_mode_provider" msgid="8354935160639360804">"პირადი DNS პროვაიდერის სერვერის სახელი"</string>
<string name="private_dns_mode_provider_hostname_hint" msgid="2487492386970928143">"შეიყვანეთ DNS პროვაიდერის სერვერის სახელი"</string>
- <!-- no translation found for private_dns_mode_provider_failure (231837290365031223) -->
- <skip />
+ <string name="private_dns_mode_provider_failure" msgid="231837290365031223">"დაკავშირება ვერ მოხერხდა"</string>
<string name="wifi_display_certification_summary" msgid="1155182309166746973">"უსადენო ეკრანის სერტიფიცირების ვარიანტების ჩვენება"</string>
<string name="wifi_verbose_logging_summary" msgid="6615071616111731958">"Wi‑Fi-ს აღრიცხვის დონის გაზრდა, Wi‑Fi ამომრჩეველში ყოველ SSID RSSI-ზე ჩვენება"</string>
<string name="wifi_connected_mac_randomization_summary" msgid="1743059848752201485">"MAC მისამართის შემთხვევითობა ჩაირთოს, როცა Wi‑Fi-ქსელებთან დაკავშირება ხდება"</string>
- <!-- no translation found for wifi_metered_label (4514924227256839725) -->
- <skip />
- <!-- no translation found for wifi_unmetered_label (6124098729457992931) -->
- <skip />
+ <string name="wifi_metered_label" msgid="4514924227256839725">"ლიმიტირებული"</string>
+ <string name="wifi_unmetered_label" msgid="6124098729457992931">"არალიმიტირებული"</string>
<string name="select_logd_size_title" msgid="7433137108348553508">"ჟურნალიზაციის ბუფერის ზომები"</string>
<string name="select_logd_size_dialog_title" msgid="1206769310236476760">"აირჩიეთ ჟურნ. ზომა / ჟურნ. ბუფერზე"</string>
<string name="dev_logpersist_clear_warning_title" msgid="684806692440237967">"გსურთ მუდმივი ჟურნალირების მეხსიერების გასუფთავება?"</string>
diff --git a/packages/SettingsLib/res/values-kk/strings.xml b/packages/SettingsLib/res/values-kk/strings.xml
index f80421f..058eecb 100644
--- a/packages/SettingsLib/res/values-kk/strings.xml
+++ b/packages/SettingsLib/res/values-kk/strings.xml
@@ -40,10 +40,8 @@
<string name="connected_via_passpoint" msgid="2826205693803088747">"%1$s арқылы қосылған"</string>
<string name="available_via_passpoint" msgid="1617440946846329613">"%1$s арқылы қолжетімді"</string>
<string name="wifi_connected_no_internet" msgid="8202906332837777829">"Қосылған, интернет жоқ"</string>
- <!-- no translation found for wifi_status_no_internet (5784710974669608361) -->
- <skip />
- <!-- no translation found for wifi_status_sign_in_required (123517180404752756) -->
- <skip />
+ <string name="wifi_status_no_internet" msgid="5784710974669608361">"Интернетпен байланыс жоқ"</string>
+ <string name="wifi_status_sign_in_required" msgid="123517180404752756">"Есептік жазбаға кіру керек"</string>
<string name="wifi_ap_unable_to_handle_new_sta" msgid="5348824313514404541">"Кіру нүктесі уақытша бос емес"</string>
<string name="connected_via_carrier" msgid="7583780074526041912">"%1$s арқылы қосылды"</string>
<string name="available_via_carrier" msgid="1469036129740799053">"%1$s арқылы қолжетімді"</string>
@@ -67,12 +65,9 @@
<string name="bluetooth_connected_no_headset_battery_level" msgid="1610296229139400266">"Жалғанды (телефонсыз), батарея заряды: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g><xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g>"</string>
<string name="bluetooth_connected_no_a2dp_battery_level" msgid="3908466636369853652">"Жалғанды (аудиосыз), батарея заряды: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g><xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g>"</string>
<string name="bluetooth_connected_no_headset_no_a2dp_battery_level" msgid="1163440823807659316">"Жалғанды (телефонсыз не аудиосыз), батарея заряды: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g><xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g>"</string>
- <!-- no translation found for bluetooth_active_battery_level (3149689299296462009) -->
- <skip />
- <!-- no translation found for bluetooth_battery_level (1447164613319663655) -->
- <skip />
- <!-- no translation found for bluetooth_active_no_battery_level (8380223546730241956) -->
- <skip />
+ <string name="bluetooth_active_battery_level" msgid="3149689299296462009">"Қосулы, батарея қуаты: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
+ <string name="bluetooth_battery_level" msgid="1447164613319663655">"Батарея қуаты: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
+ <string name="bluetooth_active_no_battery_level" msgid="8380223546730241956">"Қосулы"</string>
<string name="bluetooth_profile_a2dp" msgid="2031475486179830674">"Meдиа аудиосы"</string>
<string name="bluetooth_profile_headset" msgid="7815495680863246034">"Телефон қоңыраулары"</string>
<string name="bluetooth_profile_opp" msgid="9168139293654233697">"Файл жіберу"</string>
@@ -119,14 +114,10 @@
<string name="bluetooth_talkback_headphone" msgid="26580326066627664">"Құлақаспап"</string>
<string name="bluetooth_talkback_input_peripheral" msgid="5165842622743212268">"Кіріс құралы"</string>
<string name="bluetooth_talkback_bluetooth" msgid="5615463912185280812">"Bluetooth"</string>
- <!-- no translation found for bluetooth_hearingaid_left_pairing_message (7378813500862148102) -->
- <skip />
- <!-- no translation found for bluetooth_hearingaid_right_pairing_message (1550373802309160891) -->
- <skip />
- <!-- no translation found for bluetooth_hearingaid_left_battery_level (8797811465352097562) -->
- <skip />
- <!-- no translation found for bluetooth_hearingaid_right_battery_level (7309476148173459677) -->
- <skip />
+ <string name="bluetooth_hearingaid_left_pairing_message" msgid="7378813500862148102">"Сол жақ есту аппаратын жұпталуда…"</string>
+ <string name="bluetooth_hearingaid_right_pairing_message" msgid="1550373802309160891">"Оң жақ есту аппараты жұпталуда…"</string>
+ <string name="bluetooth_hearingaid_left_battery_level" msgid="8797811465352097562">"Сол жақ. Батарея қуаты: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
+ <string name="bluetooth_hearingaid_right_battery_level" msgid="7309476148173459677">"Оң жақ. Батарея қуаты: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
<string name="accessibility_wifi_off" msgid="1166761729660614716">"Wi-Fi өшірулі."</string>
<string name="accessibility_no_wifi" msgid="8834610636137374508">"Wi-Fi ажыратылған."</string>
<string name="accessibility_wifi_one_bar" msgid="4869376278894301820">"Wi-Fi сигналы — бір жолақ."</string>
@@ -246,15 +237,12 @@
<string name="private_dns_mode_opportunistic" msgid="8314986739896927399">"Автоматты"</string>
<string name="private_dns_mode_provider" msgid="8354935160639360804">"Жеке DNS провайдерінің хост атауы"</string>
<string name="private_dns_mode_provider_hostname_hint" msgid="2487492386970928143">"DNS провайдерінің хост атауын енгізіңіз"</string>
- <!-- no translation found for private_dns_mode_provider_failure (231837290365031223) -->
- <skip />
+ <string name="private_dns_mode_provider_failure" msgid="231837290365031223">"Қосылмады"</string>
<string name="wifi_display_certification_summary" msgid="1155182309166746973">"Сымсыз дисплей растау опцияларын көрсету"</string>
<string name="wifi_verbose_logging_summary" msgid="6615071616111731958">"Wi‑Fi жур. тір. дең. арт., Wi‑Fi желісін таңдағышта әр SSID RSSI бойынша көрсету"</string>
<string name="wifi_connected_mac_randomization_summary" msgid="1743059848752201485">"Wi‑Fi желісіне қосылу кезінде MAC мекенжайларын еркін таңдау"</string>
- <!-- no translation found for wifi_metered_label (4514924227256839725) -->
- <skip />
- <!-- no translation found for wifi_unmetered_label (6124098729457992931) -->
- <skip />
+ <string name="wifi_metered_label" msgid="4514924227256839725">"Шектелген"</string>
+ <string name="wifi_unmetered_label" msgid="6124098729457992931">"Шектелмеген"</string>
<string name="select_logd_size_title" msgid="7433137108348553508">"Журналға тіркеуші буферінің өлшемдері"</string>
<string name="select_logd_size_dialog_title" msgid="1206769310236476760">"Әр журнал буфері үшін журналға тіркеуші өлшемдерін таңдау"</string>
<string name="dev_logpersist_clear_warning_title" msgid="684806692440237967">"Тіркеуіштің тұрақты жадын тазарту керек пе?"</string>
diff --git a/packages/SettingsLib/res/values-km/strings.xml b/packages/SettingsLib/res/values-km/strings.xml
index 09f28bc..046b53b 100644
--- a/packages/SettingsLib/res/values-km/strings.xml
+++ b/packages/SettingsLib/res/values-km/strings.xml
@@ -40,10 +40,8 @@
<string name="connected_via_passpoint" msgid="2826205693803088747">"បានភ្ជាប់តាមរយៈ %1$s"</string>
<string name="available_via_passpoint" msgid="1617440946846329613">"មានតាមរយៈ %1$s"</string>
<string name="wifi_connected_no_internet" msgid="8202906332837777829">"បានភ្ជាប់ ប៉ុន្តែគ្មានអ៊ីនធឺណិតទេ"</string>
- <!-- no translation found for wifi_status_no_internet (5784710974669608361) -->
- <skip />
- <!-- no translation found for wifi_status_sign_in_required (123517180404752756) -->
- <skip />
+ <string name="wifi_status_no_internet" msgid="5784710974669608361">"គ្មានអ៊ីនធឺណិតទេ"</string>
+ <string name="wifi_status_sign_in_required" msgid="123517180404752756">"តម្រូវឱ្យចូលគណនី"</string>
<string name="wifi_ap_unable_to_handle_new_sta" msgid="5348824313514404541">"ចំណុចចូលប្រើពេញជាបណ្តោះអាសន្ន"</string>
<string name="connected_via_carrier" msgid="7583780074526041912">"បានភ្ជាប់តាមរយៈ %1$s"</string>
<string name="available_via_carrier" msgid="1469036129740799053">"មានតាមរយៈ %1$s"</string>
@@ -67,12 +65,9 @@
<string name="bluetooth_connected_no_headset_battery_level" msgid="1610296229139400266">"បានភ្ជាប់ (គ្មានទូរសព្ទទេ) ហើយថ្មមានកម្រិត <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g><xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g>"</string>
<string name="bluetooth_connected_no_a2dp_battery_level" msgid="3908466636369853652">"បានភ្ជាប់ (គ្មានមេឌៀទេ) ហើយថ្មមានកម្រិត <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g><xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g>"</string>
<string name="bluetooth_connected_no_headset_no_a2dp_battery_level" msgid="1163440823807659316">"បានភ្ជាប់ (គ្មានទូរសព្ទ ឬមេឌៀទេ) ហើយថ្មមានកម្រិត <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g><xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g>"</string>
- <!-- no translation found for bluetooth_active_battery_level (3149689299296462009) -->
- <skip />
- <!-- no translation found for bluetooth_battery_level (1447164613319663655) -->
- <skip />
- <!-- no translation found for bluetooth_active_no_battery_level (8380223546730241956) -->
- <skip />
+ <string name="bluetooth_active_battery_level" msgid="3149689299296462009">"សកម្ម ថ្ម <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
+ <string name="bluetooth_battery_level" msgid="1447164613319663655">"ថ្ម <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
+ <string name="bluetooth_active_no_battery_level" msgid="8380223546730241956">"សកម្ម"</string>
<string name="bluetooth_profile_a2dp" msgid="2031475486179830674">"សំឡេងមេឌៀ"</string>
<string name="bluetooth_profile_headset" msgid="7815495680863246034">"ការហៅទូរសព្ទ"</string>
<string name="bluetooth_profile_opp" msgid="9168139293654233697">"ផ្ទេរឯកសារ"</string>
@@ -119,14 +114,10 @@
<string name="bluetooth_talkback_headphone" msgid="26580326066627664">"កាស"</string>
<string name="bluetooth_talkback_input_peripheral" msgid="5165842622743212268">"ធាតុបញ្ចូលបន្ថែម"</string>
<string name="bluetooth_talkback_bluetooth" msgid="5615463912185280812">"ប៊្លូធូស"</string>
- <!-- no translation found for bluetooth_hearingaid_left_pairing_message (7378813500862148102) -->
- <skip />
- <!-- no translation found for bluetooth_hearingaid_right_pairing_message (1550373802309160891) -->
- <skip />
- <!-- no translation found for bluetooth_hearingaid_left_battery_level (8797811465352097562) -->
- <skip />
- <!-- no translation found for bluetooth_hearingaid_right_battery_level (7309476148173459677) -->
- <skip />
+ <string name="bluetooth_hearingaid_left_pairing_message" msgid="7378813500862148102">"កំពុងផ្គូផ្គងឧបករណ៍ជំនួយការស្តាប់ខាងឆ្វេង…"</string>
+ <string name="bluetooth_hearingaid_right_pairing_message" msgid="1550373802309160891">"កំពុងផ្គូផ្គងឧបករណ៍ជំនួយការស្តាប់ខាងស្តាំ…"</string>
+ <string name="bluetooth_hearingaid_left_battery_level" msgid="8797811465352097562">"ឆ្វេង៖ ថ្ម <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
+ <string name="bluetooth_hearingaid_right_battery_level" msgid="7309476148173459677">"ស្តាំ៖ ថ្ម <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
<string name="accessibility_wifi_off" msgid="1166761729660614716">"បានបិទ Wifi"</string>
<string name="accessibility_no_wifi" msgid="8834610636137374508">"បានផ្តាច់ Wifi"</string>
<string name="accessibility_wifi_one_bar" msgid="4869376278894301820">"Wifi មួយកាំ"</string>
@@ -246,15 +237,12 @@
<string name="private_dns_mode_opportunistic" msgid="8314986739896927399">"ស្វ័យប្រវត្តិ"</string>
<string name="private_dns_mode_provider" msgid="8354935160639360804">"ឈ្មោះម៉ាស៊ីនក្រុមហ៊ុនផ្ដល់សេវា DNS ឯកជន"</string>
<string name="private_dns_mode_provider_hostname_hint" msgid="2487492386970928143">"បញ្ចូលឈ្មោះម៉ាស៊ីនរបស់ក្រុមហ៊ុនផ្ដល់សេវា DNS"</string>
- <!-- no translation found for private_dns_mode_provider_failure (231837290365031223) -->
- <skip />
+ <string name="private_dns_mode_provider_failure" msgid="231837290365031223">"មិនអាចភ្ជាប់បានទេ"</string>
<string name="wifi_display_certification_summary" msgid="1155182309166746973">"បង្ហាញជម្រើសសម្រាប់វិញ្ញាបនបត្របង្ហាញឥតខ្សែ"</string>
<string name="wifi_verbose_logging_summary" msgid="6615071616111731958">"បង្កើនកម្រិតកំណត់ហេតុវ៉ាយហ្វាយបង្ហាញក្នុង SSID RSSI ក្នុងកម្មវិធីជ្រើសវ៉ាយហ្វាយ"</string>
<string name="wifi_connected_mac_randomization_summary" msgid="1743059848752201485">"ជ្រើសរើសអាសយដ្ឋាន MAC ដោយចៃដន្យ នៅពេលភ្ជាប់បណ្តាញ Wi‑Fi"</string>
- <!-- no translation found for wifi_metered_label (4514924227256839725) -->
- <skip />
- <!-- no translation found for wifi_unmetered_label (6124098729457992931) -->
- <skip />
+ <string name="wifi_metered_label" msgid="4514924227256839725">"មានការកំណត់"</string>
+ <string name="wifi_unmetered_label" msgid="6124098729457992931">"មិនមានការកំណត់"</string>
<string name="select_logd_size_title" msgid="7433137108348553508">"ទំហំ buffer របស់ Logger"</string>
<string name="select_logd_size_dialog_title" msgid="1206769310236476760">"ជ្រើសទំហំ Logger per log buffer"</string>
<string name="dev_logpersist_clear_warning_title" msgid="684806692440237967">"ជម្រះទំហំផ្ទុក logger ដែលប្រើបានយូរឬ?"</string>
diff --git a/packages/SettingsLib/res/values-kn/strings.xml b/packages/SettingsLib/res/values-kn/strings.xml
index 65273c7..a7756ed 100644
--- a/packages/SettingsLib/res/values-kn/strings.xml
+++ b/packages/SettingsLib/res/values-kn/strings.xml
@@ -197,8 +197,7 @@
<string name="keep_screen_on" msgid="1146389631208760344">"ಎಚ್ಚರವಾಗಿರು"</string>
<string name="keep_screen_on_summary" msgid="2173114350754293009">"ಚಾರ್ಜ್ ಮಾಡುವಾಗ ಪರದೆಯು ಎಂದಿಗೂ ನಿದ್ರಾವಸ್ಥೆಗೆ ಹೋಗುವುದಿಲ್ಲ"</string>
<string name="bt_hci_snoop_log" msgid="3340699311158865670">"ಬ್ಲೂಟೂತ್ HCI ಸ್ನೂಪ್ಲಾಗ್"</string>
- <!-- no translation found for bt_hci_snoop_log_summary (366083475849911315) -->
- <skip />
+ <string name="bt_hci_snoop_log_summary" msgid="366083475849911315">"ಫೈಲ್ನಲ್ಲಿ ಎಲ್ಲ ಬ್ಲೂಟೂತ್ HCI ಪ್ಯಾಕೆಟ್ಗಳನ್ನು ಸೆರೆಹಿಡಿಯಿರಿ (ಈ ಸೆಟ್ಟಿಂಗ್ ಅನ್ನು ಬದಲಾಯಿಸಿದ ನಂತರ ಬ್ಲೂಟೂತ್ ಟಾಗಲ್ ಮಾಡಿ)"</string>
<string name="oem_unlock_enable" msgid="6040763321967327691">"OEM ಅನ್ಲಾಕ್ ಮಾಡಲಾಗುತ್ತಿದೆ"</string>
<string name="oem_unlock_enable_summary" msgid="4720281828891618376">"ಬೂಟ್ಲೋಡರ್ ಅನ್ಲಾಕ್ ಮಾಡಲು ಅನುಮತಿಸಿ"</string>
<string name="confirm_enable_oem_unlock_title" msgid="4802157344812385674">"OEM ಅನ್ಲಾಕ್ ಮಾಡುವಿಕೆಯನ್ನು ಅನುಮತಿಸುವುದೇ?"</string>
diff --git a/packages/SettingsLib/res/values-ko/strings.xml b/packages/SettingsLib/res/values-ko/strings.xml
index cae1535..2c6a9a2 100644
--- a/packages/SettingsLib/res/values-ko/strings.xml
+++ b/packages/SettingsLib/res/values-ko/strings.xml
@@ -40,10 +40,8 @@
<string name="connected_via_passpoint" msgid="2826205693803088747">"%1$s을(를) 통해 연결됨"</string>
<string name="available_via_passpoint" msgid="1617440946846329613">"%1$s을(를) 통해 사용 가능"</string>
<string name="wifi_connected_no_internet" msgid="8202906332837777829">"연결됨, 인터넷 사용 불가"</string>
- <!-- no translation found for wifi_status_no_internet (5784710974669608361) -->
- <skip />
- <!-- no translation found for wifi_status_sign_in_required (123517180404752756) -->
- <skip />
+ <string name="wifi_status_no_internet" msgid="5784710974669608361">"인터넷 연결 없음"</string>
+ <string name="wifi_status_sign_in_required" msgid="123517180404752756">"로그인 필요"</string>
<string name="wifi_ap_unable_to_handle_new_sta" msgid="5348824313514404541">"액세스 포인트가 일시적으로 가득 참"</string>
<string name="connected_via_carrier" msgid="7583780074526041912">"%1$s을(를) 통해 연결됨"</string>
<string name="available_via_carrier" msgid="1469036129740799053">"%1$s을(를) 통해 사용 가능"</string>
@@ -67,12 +65,9 @@
<string name="bluetooth_connected_no_headset_battery_level" msgid="1610296229139400266">"연결됨(전화 없음), 배터리 <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g><xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g>"</string>
<string name="bluetooth_connected_no_a2dp_battery_level" msgid="3908466636369853652">"연결됨(미디어 없음), 배터리 <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g><xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g>"</string>
<string name="bluetooth_connected_no_headset_no_a2dp_battery_level" msgid="1163440823807659316">"연결됨(전화 또는 미디어 없음), 배터리 <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g><xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g>"</string>
- <!-- no translation found for bluetooth_active_battery_level (3149689299296462009) -->
- <skip />
- <!-- no translation found for bluetooth_battery_level (1447164613319663655) -->
- <skip />
- <!-- no translation found for bluetooth_active_no_battery_level (8380223546730241956) -->
- <skip />
+ <string name="bluetooth_active_battery_level" msgid="3149689299296462009">"활성, 배터리 <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
+ <string name="bluetooth_battery_level" msgid="1447164613319663655">"배터리 <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
+ <string name="bluetooth_active_no_battery_level" msgid="8380223546730241956">"활성"</string>
<string name="bluetooth_profile_a2dp" msgid="2031475486179830674">"미디어 오디오"</string>
<string name="bluetooth_profile_headset" msgid="7815495680863246034">"전화 통화"</string>
<string name="bluetooth_profile_opp" msgid="9168139293654233697">"파일 전송"</string>
@@ -119,14 +114,10 @@
<string name="bluetooth_talkback_headphone" msgid="26580326066627664">"헤드폰"</string>
<string name="bluetooth_talkback_input_peripheral" msgid="5165842622743212268">"입력 주변기기"</string>
<string name="bluetooth_talkback_bluetooth" msgid="5615463912185280812">"블루투스"</string>
- <!-- no translation found for bluetooth_hearingaid_left_pairing_message (7378813500862148102) -->
- <skip />
- <!-- no translation found for bluetooth_hearingaid_right_pairing_message (1550373802309160891) -->
- <skip />
- <!-- no translation found for bluetooth_hearingaid_left_battery_level (8797811465352097562) -->
- <skip />
- <!-- no translation found for bluetooth_hearingaid_right_battery_level (7309476148173459677) -->
- <skip />
+ <string name="bluetooth_hearingaid_left_pairing_message" msgid="7378813500862148102">"왼쪽 보청기 페어링 중…"</string>
+ <string name="bluetooth_hearingaid_right_pairing_message" msgid="1550373802309160891">"오른쪽 보청기 페어링 중..."</string>
+ <string name="bluetooth_hearingaid_left_battery_level" msgid="8797811465352097562">"왼쪽 - 배터리 <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
+ <string name="bluetooth_hearingaid_right_battery_level" msgid="7309476148173459677">"오른쪽 - 배터리 <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
<string name="accessibility_wifi_off" msgid="1166761729660614716">"Wi-Fi가 꺼져 있습니다."</string>
<string name="accessibility_no_wifi" msgid="8834610636137374508">"Wi-Fi 연결이 끊어졌습니다."</string>
<string name="accessibility_wifi_one_bar" msgid="4869376278894301820">"Wi-Fi 신호 막대가 한 개입니다."</string>
@@ -246,15 +237,12 @@
<string name="private_dns_mode_opportunistic" msgid="8314986739896927399">"자동"</string>
<string name="private_dns_mode_provider" msgid="8354935160639360804">"비공개 DNS 제공업체 호스트 이름"</string>
<string name="private_dns_mode_provider_hostname_hint" msgid="2487492386970928143">"DNS 제공업체의 호스트 이름 입력"</string>
- <!-- no translation found for private_dns_mode_provider_failure (231837290365031223) -->
- <skip />
+ <string name="private_dns_mode_provider_failure" msgid="231837290365031223">"연결할 수 없음"</string>
<string name="wifi_display_certification_summary" msgid="1155182309166746973">"무선 디스플레이 인증서 옵션 표시"</string>
<string name="wifi_verbose_logging_summary" msgid="6615071616111731958">"Wi‑Fi 로깅 수준을 높이고, Wi‑Fi 선택도구에서 SSID RSSI당 값을 표시합니다."</string>
<string name="wifi_connected_mac_randomization_summary" msgid="1743059848752201485">"Wi‑Fi 네트워크에 연결할 때 MAC 주소 임의 선택"</string>
- <!-- no translation found for wifi_metered_label (4514924227256839725) -->
- <skip />
- <!-- no translation found for wifi_unmetered_label (6124098729457992931) -->
- <skip />
+ <string name="wifi_metered_label" msgid="4514924227256839725">"종량제"</string>
+ <string name="wifi_unmetered_label" msgid="6124098729457992931">"무제한"</string>
<string name="select_logd_size_title" msgid="7433137108348553508">"로거 버퍼 크기"</string>
<string name="select_logd_size_dialog_title" msgid="1206769310236476760">"로그 버퍼당 로거 크기 선택"</string>
<string name="dev_logpersist_clear_warning_title" msgid="684806692440237967">"로거 영구 저장소를 삭제하시겠습니까?"</string>
diff --git a/packages/SettingsLib/res/values-ky/strings.xml b/packages/SettingsLib/res/values-ky/strings.xml
index 65689f1..f6318f2 100644
--- a/packages/SettingsLib/res/values-ky/strings.xml
+++ b/packages/SettingsLib/res/values-ky/strings.xml
@@ -40,10 +40,8 @@
<string name="connected_via_passpoint" msgid="2826205693803088747">"%1$s аркылуу жеткиликтүү"</string>
<string name="available_via_passpoint" msgid="1617440946846329613">"%1$s аркылуу жеткиликтүү"</string>
<string name="wifi_connected_no_internet" msgid="8202906332837777829">"Туташып турат, Интернет жок"</string>
- <!-- no translation found for wifi_status_no_internet (5784710974669608361) -->
- <skip />
- <!-- no translation found for wifi_status_sign_in_required (123517180404752756) -->
- <skip />
+ <string name="wifi_status_no_internet" msgid="5784710974669608361">"Интернет жок"</string>
+ <string name="wifi_status_sign_in_required" msgid="123517180404752756">"Аккаунтка кирүү талап кылынат"</string>
<string name="wifi_ap_unable_to_handle_new_sta" msgid="5348824313514404541">"Туташуу түйүнү убактылуу толуп калды"</string>
<string name="connected_via_carrier" msgid="7583780074526041912">"%1$s аркылуу туташты"</string>
<string name="available_via_carrier" msgid="1469036129740799053">"%1$s аркылуу иштейт"</string>
@@ -67,12 +65,9 @@
<string name="bluetooth_connected_no_headset_battery_level" msgid="1610296229139400266">"Туташып турат (телефониясыз), батареянын деңгээли – <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g><xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g>"</string>
<string name="bluetooth_connected_no_a2dp_battery_level" msgid="3908466636369853652">"Туташып турат (медиасыз), батареянын деңгээли – <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g><xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g>"</string>
<string name="bluetooth_connected_no_headset_no_a2dp_battery_level" msgid="1163440823807659316">"Туташып турат (телефониясыз же медиасыз), батареянын деңгээли – <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g><xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g>"</string>
- <!-- no translation found for bluetooth_active_battery_level (3149689299296462009) -->
- <skip />
- <!-- no translation found for bluetooth_battery_level (1447164613319663655) -->
- <skip />
- <!-- no translation found for bluetooth_active_no_battery_level (8380223546730241956) -->
- <skip />
+ <string name="bluetooth_active_battery_level" msgid="3149689299296462009">"Жигердүү, батареянын деңгээли: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
+ <string name="bluetooth_battery_level" msgid="1447164613319663655">"Батареянын деңгээли: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
+ <string name="bluetooth_active_no_battery_level" msgid="8380223546730241956">"Жигердүү"</string>
<string name="bluetooth_profile_a2dp" msgid="2031475486179830674">"Аудио"</string>
<string name="bluetooth_profile_headset" msgid="7815495680863246034">"Телефон чалуулар"</string>
<string name="bluetooth_profile_opp" msgid="9168139293654233697">"Файл алмашуу"</string>
@@ -119,14 +114,10 @@
<string name="bluetooth_talkback_headphone" msgid="26580326066627664">"Кулакчын"</string>
<string name="bluetooth_talkback_input_peripheral" msgid="5165842622743212268">"Дайындарды киргизүүчү сырткы түзмөк"</string>
<string name="bluetooth_talkback_bluetooth" msgid="5615463912185280812">"Bluetooth"</string>
- <!-- no translation found for bluetooth_hearingaid_left_pairing_message (7378813500862148102) -->
- <skip />
- <!-- no translation found for bluetooth_hearingaid_right_pairing_message (1550373802309160891) -->
- <skip />
- <!-- no translation found for bluetooth_hearingaid_left_battery_level (8797811465352097562) -->
- <skip />
- <!-- no translation found for bluetooth_hearingaid_right_battery_level (7309476148173459677) -->
- <skip />
+ <string name="bluetooth_hearingaid_left_pairing_message" msgid="7378813500862148102">"Угуу аппаратынын сол кулагы жупташтырылууда…"</string>
+ <string name="bluetooth_hearingaid_right_pairing_message" msgid="1550373802309160891">"Угуу аппаратынын оң кулагы жупташтырылууда…"</string>
+ <string name="bluetooth_hearingaid_left_battery_level" msgid="8797811465352097562">"Сол кулак – батареянын деңгээли: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
+ <string name="bluetooth_hearingaid_right_battery_level" msgid="7309476148173459677">"Оң кулагы – батареянын деңгээли: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
<string name="accessibility_wifi_off" msgid="1166761729660614716">"Wifi өчүк."</string>
<string name="accessibility_no_wifi" msgid="8834610636137374508">"Wifi туташуусу жок."</string>
<string name="accessibility_wifi_one_bar" msgid="4869376278894301820">"Wifi: бир таякча."</string>
@@ -246,15 +237,12 @@
<string name="private_dns_mode_opportunistic" msgid="8314986739896927399">"Автоматтык режим"</string>
<string name="private_dns_mode_provider" msgid="8354935160639360804">"Купуя DNS түйүндүн аталышы"</string>
<string name="private_dns_mode_provider_hostname_hint" msgid="2487492386970928143">"DNS түйүндүн аталышын киргизиңиз"</string>
- <!-- no translation found for private_dns_mode_provider_failure (231837290365031223) -->
- <skip />
+ <string name="private_dns_mode_provider_failure" msgid="231837290365031223">"Туташпай койду"</string>
<string name="wifi_display_certification_summary" msgid="1155182309166746973">"Зымсыз дисплейди сертификатто мүмкүнчүлүктөрүн көргөзүү"</string>
<string name="wifi_verbose_logging_summary" msgid="6615071616111731958">"Wi-Fi Кармагычта Wi‑Fi протокол деңгээлин жогорулатуу жана ар бир SSID RSSI үчүн көрсөтүү."</string>
<string name="wifi_connected_mac_randomization_summary" msgid="1743059848752201485">"Wi‑Fi тармагына туташууда кокустан тандаган MAC дарегин колдонуу"</string>
- <!-- no translation found for wifi_metered_label (4514924227256839725) -->
- <skip />
- <!-- no translation found for wifi_unmetered_label (6124098729457992931) -->
- <skip />
+ <string name="wifi_metered_label" msgid="4514924227256839725">"Трафик ченелет"</string>
+ <string name="wifi_unmetered_label" msgid="6124098729457992931">"Чектелбеген тармак"</string>
<string name="select_logd_size_title" msgid="7433137108348553508">"Каттагыч буферлеринин өлчөмдөрү"</string>
<string name="select_logd_size_dialog_title" msgid="1206769310236476760">"Каттоо буфери үчүн Каттагычтын көлөмүн тандаңыз"</string>
<string name="dev_logpersist_clear_warning_title" msgid="684806692440237967">"Таржымалдын туруктуу диски тазалансынбы?"</string>
diff --git a/packages/SettingsLib/res/values-lo/strings.xml b/packages/SettingsLib/res/values-lo/strings.xml
index 434c6e7..f7dc1be 100644
--- a/packages/SettingsLib/res/values-lo/strings.xml
+++ b/packages/SettingsLib/res/values-lo/strings.xml
@@ -40,10 +40,8 @@
<string name="connected_via_passpoint" msgid="2826205693803088747">"ເຊື່ອມຕໍ່ຜ່ານ %1$s ແລ້ວ"</string>
<string name="available_via_passpoint" msgid="1617440946846329613">"ມີໃຫ້ຜ່ານ %1$s"</string>
<string name="wifi_connected_no_internet" msgid="8202906332837777829">"ເຊື່ອມຕໍ່ແລ້ວ, ບໍ່ມີອິນເຕີເນັດ"</string>
- <!-- no translation found for wifi_status_no_internet (5784710974669608361) -->
- <skip />
- <!-- no translation found for wifi_status_sign_in_required (123517180404752756) -->
- <skip />
+ <string name="wifi_status_no_internet" msgid="5784710974669608361">"ບໍ່ມີອິນເຕີເນັດ"</string>
+ <string name="wifi_status_sign_in_required" msgid="123517180404752756">"ຈຳເປັນຕ້ອງເຂົ້າສູ່ລະບົບ"</string>
<string name="wifi_ap_unable_to_handle_new_sta" msgid="5348824313514404541">"ຈຸດການເຂົ້າເຖິງເຕັມຊົ່ວຄາວ"</string>
<string name="connected_via_carrier" msgid="7583780074526041912">"ເຊື່ອມຕໍ່ຜ່ານ %1$s ແລ້ວ"</string>
<string name="available_via_carrier" msgid="1469036129740799053">"ໃຊ້ໄດ້ຜ່ານ %1$s"</string>
@@ -67,12 +65,9 @@
<string name="bluetooth_connected_no_headset_battery_level" msgid="1610296229139400266">"ເຊື່ອມຕໍ່ແລ້ວ (ບໍ່ມີໂທລະສັບ), ແບັດເຕີຣີ <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g><xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g>"</string>
<string name="bluetooth_connected_no_a2dp_battery_level" msgid="3908466636369853652">"ເຊື່ອມຕໍ່ແລ້ວ (ບໍ່ມີມີເດຍ), ແບັດເຕີຣີ <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g><xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g>"</string>
<string name="bluetooth_connected_no_headset_no_a2dp_battery_level" msgid="1163440823807659316">"ເຊື່ອມຕໍ່ແລ້ວ (ບໍ່ມີໂທລະສັບ ຫຼື ມີເດຍ), ແບັດເຕີຣີ <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g><xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g>"</string>
- <!-- no translation found for bluetooth_active_battery_level (3149689299296462009) -->
- <skip />
- <!-- no translation found for bluetooth_battery_level (1447164613319663655) -->
- <skip />
- <!-- no translation found for bluetooth_active_no_battery_level (8380223546730241956) -->
- <skip />
+ <string name="bluetooth_active_battery_level" msgid="3149689299296462009">"ເປີດໃຊ້ຢູ່, ແບັດເຕີຣີ <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
+ <string name="bluetooth_battery_level" msgid="1447164613319663655">"ແບັດເຕີຣີ <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
+ <string name="bluetooth_active_no_battery_level" msgid="8380223546730241956">"ອອນລາຍ"</string>
<string name="bluetooth_profile_a2dp" msgid="2031475486179830674">"ສຽງ"</string>
<string name="bluetooth_profile_headset" msgid="7815495680863246034">"ການໂທ"</string>
<string name="bluetooth_profile_opp" msgid="9168139293654233697">"ການໂອນຍ້າຍໄຟລ໌"</string>
@@ -119,14 +114,10 @@
<string name="bluetooth_talkback_headphone" msgid="26580326066627664">"ຫູຟັງ"</string>
<string name="bluetooth_talkback_input_peripheral" msgid="5165842622743212268">"ອຸປະກອນພ່ວງອິນພຸດ"</string>
<string name="bluetooth_talkback_bluetooth" msgid="5615463912185280812">"Bluetooth"</string>
- <!-- no translation found for bluetooth_hearingaid_left_pairing_message (7378813500862148102) -->
- <skip />
- <!-- no translation found for bluetooth_hearingaid_right_pairing_message (1550373802309160891) -->
- <skip />
- <!-- no translation found for bluetooth_hearingaid_left_battery_level (8797811465352097562) -->
- <skip />
- <!-- no translation found for bluetooth_hearingaid_right_battery_level (7309476148173459677) -->
- <skip />
+ <string name="bluetooth_hearingaid_left_pairing_message" msgid="7378813500862148102">"ກຳລັງຈັບຄູ່ເຄື່ອງຊ່ວຍຟັງຊ້າຍ…"</string>
+ <string name="bluetooth_hearingaid_right_pairing_message" msgid="1550373802309160891">"ກຳລັງຈັບຄູ່ເຄື່ອງຊ່ວຍຟັງຂວາ…"</string>
+ <string name="bluetooth_hearingaid_left_battery_level" msgid="8797811465352097562">"ຊ້າຍ - ແບັດເຕີຣີ <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
+ <string name="bluetooth_hearingaid_right_battery_level" msgid="7309476148173459677">"ຂວາ - ແບັດເຕີຣີ <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
<string name="accessibility_wifi_off" msgid="1166761729660614716">"WiFi ປິດຢູ່."</string>
<string name="accessibility_no_wifi" msgid="8834610636137374508">"ຕັດການເຊື່ອມຕໍ່ Wi-Fi ແລ້ວ."</string>
<string name="accessibility_wifi_one_bar" msgid="4869376278894301820">"ສັນຍານ Wi-Fi ນຶ່ງຂີດ."</string>
@@ -206,8 +197,7 @@
<string name="keep_screen_on" msgid="1146389631208760344">"ເປີດໜ້າຈໍຕະຫຼອດ"</string>
<string name="keep_screen_on_summary" msgid="2173114350754293009">"ໜ້າຈໍຈະບໍ່ປິດໃນຂະນະທີ່ສາກໄຟຢູ່"</string>
<string name="bt_hci_snoop_log" msgid="3340699311158865670">"ເປີດໃຊ້ງານການຊອດແນມ Bluetooth HCI"</string>
- <!-- no translation found for bt_hci_snoop_log_summary (366083475849911315) -->
- <skip />
+ <string name="bt_hci_snoop_log_summary" msgid="366083475849911315">"ບັນທຶກແພັກເກັດ Bluetooth HCI ທັງໝົດໃນໄຟລ໌ (ສະຫຼັບການໃຊ້ Bluetooth ຫຼັງຈາກການປ່ຽນແປງການຕັ້ງຄ່ານີ້)"</string>
<string name="oem_unlock_enable" msgid="6040763321967327691">"ການປົດລັອກ OEM"</string>
<string name="oem_unlock_enable_summary" msgid="4720281828891618376">"ອະນຸຍາດໃຫ້ປົດລັອກບູດໂຫຼດເດີ"</string>
<string name="confirm_enable_oem_unlock_title" msgid="4802157344812385674">"ອະນຸຍາດການປົກລັອກ OEM ບໍ?"</string>
@@ -247,15 +237,12 @@
<string name="private_dns_mode_opportunistic" msgid="8314986739896927399">"ອັດຕະໂນມັດ"</string>
<string name="private_dns_mode_provider" msgid="8354935160639360804">"ຊື່ໂຮສຜູ້ໃຫ້ບໍລິການ DNS ສ່ວນຕົວ"</string>
<string name="private_dns_mode_provider_hostname_hint" msgid="2487492386970928143">"ລະບຸຊື່ໂຮສຂອງຜູ້ໃຫ້ບໍລິການ DNS"</string>
- <!-- no translation found for private_dns_mode_provider_failure (231837290365031223) -->
- <skip />
+ <string name="private_dns_mode_provider_failure" msgid="231837290365031223">"ບໍ່ສາມາດເຊື່ອມຕໍ່ໄດ້"</string>
<string name="wifi_display_certification_summary" msgid="1155182309166746973">"ສະແດງໂຕເລືອກສຳລັບການສະແດງການຮັບຮອງລະບົບໄຮ້ສາຍ"</string>
<string name="wifi_verbose_logging_summary" msgid="6615071616111731958">"ເພີ່ມລະດັບການເກັບປະຫວັດ Wi‑Fi, ສະແດງຕໍ່ SSID RSSI ໃນ Wi‑Fi Picker"</string>
<string name="wifi_connected_mac_randomization_summary" msgid="1743059848752201485">"ສຸ່ມທີ່ຢູ່ MAC ເມື່ອເຊື່ອມຕໍ່ຫາເຄືອຂ່າຍ Wi‑Fi"</string>
- <!-- no translation found for wifi_metered_label (4514924227256839725) -->
- <skip />
- <!-- no translation found for wifi_unmetered_label (6124098729457992931) -->
- <skip />
+ <string name="wifi_metered_label" msgid="4514924227256839725">"ມີການວັດແທກ"</string>
+ <string name="wifi_unmetered_label" msgid="6124098729457992931">"ບໍ່ໄດ້ວັດແທກ"</string>
<string name="select_logd_size_title" msgid="7433137108348553508">"ຂະໜາດບັບເຟີໂຕລັອກ"</string>
<string name="select_logd_size_dialog_title" msgid="1206769310236476760">"ເລືອກຂະໜາດລັອກຕໍ່ບັບເຟີ"</string>
<string name="dev_logpersist_clear_warning_title" msgid="684806692440237967">"ລຶບລ້າງບ່ອນຈັດເກັບຖາວອນຂອງຕົວບັນທຶກບໍ່?"</string>
diff --git a/packages/SettingsLib/res/values-lt/strings.xml b/packages/SettingsLib/res/values-lt/strings.xml
index 66912f6..4eef77d 100644
--- a/packages/SettingsLib/res/values-lt/strings.xml
+++ b/packages/SettingsLib/res/values-lt/strings.xml
@@ -197,8 +197,7 @@
<string name="keep_screen_on" msgid="1146389631208760344">"Veikti"</string>
<string name="keep_screen_on_summary" msgid="2173114350754293009">"Kraunant ekranas niekada neveiks miego režimu"</string>
<string name="bt_hci_snoop_log" msgid="3340699311158865670">"Įgalinti „Bluetooth“ HCI šnipinėjimo žurnalą"</string>
- <!-- no translation found for bt_hci_snoop_log_summary (366083475849911315) -->
- <skip />
+ <string name="bt_hci_snoop_log_summary" msgid="366083475849911315">"Užfiksuoti visus faile esančius „Bluetooth“ HCI paketus (pakeitę nustatymą išjunkite ir vėl įjunkite „Bluetooth“)"</string>
<string name="oem_unlock_enable" msgid="6040763321967327691">"OĮG atrakinimas"</string>
<string name="oem_unlock_enable_summary" msgid="4720281828891618376">"Leisti atrakinti oper. sistemos paleidimo progr."</string>
<string name="confirm_enable_oem_unlock_title" msgid="4802157344812385674">"Leisti OĮG atrakinimą?"</string>
diff --git a/packages/SettingsLib/res/values-ml/strings.xml b/packages/SettingsLib/res/values-ml/strings.xml
index 8972733..f9d3495 100644
--- a/packages/SettingsLib/res/values-ml/strings.xml
+++ b/packages/SettingsLib/res/values-ml/strings.xml
@@ -197,8 +197,7 @@
<string name="keep_screen_on" msgid="1146389631208760344">"സജീവമായി തുടരുക"</string>
<string name="keep_screen_on_summary" msgid="2173114350754293009">"ചാർജ്ജുചെയ്യുമ്പോൾ സ്ക്രീൻ ഒരിക്കലും സുഷുപ്തിയിലാകില്ല"</string>
<string name="bt_hci_snoop_log" msgid="3340699311158865670">"ബ്ലൂടൂത്ത് HCI സ്നൂപ്പ് ലോഗ് സജീവമാക്കൂ"</string>
- <!-- no translation found for bt_hci_snoop_log_summary (366083475849911315) -->
- <skip />
+ <string name="bt_hci_snoop_log_summary" msgid="366083475849911315">"എല്ലാ Bluetooth HCI പാക്കറ്റുകളും ഒരു ഫയലിൽ ക്യാപ്ചർ ചെയ്യുക (ഈ ക്രമീകരണം മാറ്റിയ ശേഷം Bluetooth മാറ്റുക)"</string>
<string name="oem_unlock_enable" msgid="6040763321967327691">"OEM അൺലോക്കുചെയ്യൽ"</string>
<string name="oem_unlock_enable_summary" msgid="4720281828891618376">"അൺലോക്കാകാൻ ബൂട്ട്ലോഡറിനെ അനുവദിക്കുക"</string>
<string name="confirm_enable_oem_unlock_title" msgid="4802157344812385674">"OEM അൺലോക്കുചെയ്യൽ അനുവദിക്കണോ?"</string>
diff --git a/packages/SettingsLib/res/values-mn/strings.xml b/packages/SettingsLib/res/values-mn/strings.xml
index bc1d2e7..5bd034c 100644
--- a/packages/SettingsLib/res/values-mn/strings.xml
+++ b/packages/SettingsLib/res/values-mn/strings.xml
@@ -40,10 +40,8 @@
<string name="connected_via_passpoint" msgid="2826205693803088747">"%1$s-р холбогдсон"</string>
<string name="available_via_passpoint" msgid="1617440946846329613">"%1$s-р боломжтой"</string>
<string name="wifi_connected_no_internet" msgid="8202906332837777829">"Холбогдсон хэдий ч интернет алга"</string>
- <!-- no translation found for wifi_status_no_internet (5784710974669608361) -->
- <skip />
- <!-- no translation found for wifi_status_sign_in_required (123517180404752756) -->
- <skip />
+ <string name="wifi_status_no_internet" msgid="5784710974669608361">"Интернэт алга"</string>
+ <string name="wifi_status_sign_in_required" msgid="123517180404752756">"Нэвтрэх шаардлагатай"</string>
<string name="wifi_ap_unable_to_handle_new_sta" msgid="5348824313514404541">"Хандах цэг түр хугацаанд дүүрсэн байна"</string>
<string name="connected_via_carrier" msgid="7583780074526041912">"%1$s-р холбогдсон"</string>
<string name="available_via_carrier" msgid="1469036129740799053">"%1$s-р боломжтой"</string>
@@ -67,12 +65,9 @@
<string name="bluetooth_connected_no_headset_battery_level" msgid="1610296229139400266">"Холбогдсон (утас байхгүй), батерей <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g><xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g>"</string>
<string name="bluetooth_connected_no_a2dp_battery_level" msgid="3908466636369853652">"Холбогдсон (медиа байхгүй), батерей <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g><xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g>"</string>
<string name="bluetooth_connected_no_headset_no_a2dp_battery_level" msgid="1163440823807659316">"Холбогдсон (утас эсвэл медиа байхгүй), батерей <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g><xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g>"</string>
- <!-- no translation found for bluetooth_active_battery_level (3149689299296462009) -->
- <skip />
- <!-- no translation found for bluetooth_battery_level (1447164613319663655) -->
- <skip />
- <!-- no translation found for bluetooth_active_no_battery_level (8380223546730241956) -->
- <skip />
+ <string name="bluetooth_active_battery_level" msgid="3149689299296462009">"Идэвхтэй, батерей <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
+ <string name="bluetooth_battery_level" msgid="1447164613319663655">"Батерей <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
+ <string name="bluetooth_active_no_battery_level" msgid="8380223546730241956">"Идэвхтэй"</string>
<string name="bluetooth_profile_a2dp" msgid="2031475486179830674">"Медиа аудио"</string>
<string name="bluetooth_profile_headset" msgid="7815495680863246034">"Утасны дуудлага"</string>
<string name="bluetooth_profile_opp" msgid="9168139293654233697">"Файл дамжуулалт"</string>
@@ -119,14 +114,10 @@
<string name="bluetooth_talkback_headphone" msgid="26580326066627664">"Чихэвч"</string>
<string name="bluetooth_talkback_input_peripheral" msgid="5165842622743212268">"Нэмэлт оролт"</string>
<string name="bluetooth_talkback_bluetooth" msgid="5615463912185280812">"Bluetooth"</string>
- <!-- no translation found for bluetooth_hearingaid_left_pairing_message (7378813500862148102) -->
- <skip />
- <!-- no translation found for bluetooth_hearingaid_right_pairing_message (1550373802309160891) -->
- <skip />
- <!-- no translation found for bluetooth_hearingaid_left_battery_level (8797811465352097562) -->
- <skip />
- <!-- no translation found for bluetooth_hearingaid_right_battery_level (7309476148173459677) -->
- <skip />
+ <string name="bluetooth_hearingaid_left_pairing_message" msgid="7378813500862148102">"Зүүн талын сонсголын төхөөрөмжийг холбож байна…"</string>
+ <string name="bluetooth_hearingaid_right_pairing_message" msgid="1550373802309160891">"Баруун талын сонсголын төхөөрөмжийг холбож байна…"</string>
+ <string name="bluetooth_hearingaid_left_battery_level" msgid="8797811465352097562">"Зүүн - батерей <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
+ <string name="bluetooth_hearingaid_right_battery_level" msgid="7309476148173459677">"Баруун - батерей <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
<string name="accessibility_wifi_off" msgid="1166761729660614716">"Wifi унтраалттай байна."</string>
<string name="accessibility_no_wifi" msgid="8834610636137374508">"Wifi холбогдоогүй байна."</string>
<string name="accessibility_wifi_one_bar" msgid="4869376278894301820">"Wifi сүлжээний дохио нэг баганатай байна."</string>
@@ -246,15 +237,12 @@
<string name="private_dns_mode_opportunistic" msgid="8314986739896927399">"Автомат"</string>
<string name="private_dns_mode_provider" msgid="8354935160639360804">"Хувийн DNS-н үйлчилгээ үзүүлэгчийн хостын нэр"</string>
<string name="private_dns_mode_provider_hostname_hint" msgid="2487492386970928143">"DNS-н үйлчилгээ үзүүлэгчийн хостын нэрийг оруулах"</string>
- <!-- no translation found for private_dns_mode_provider_failure (231837290365031223) -->
- <skip />
+ <string name="private_dns_mode_provider_failure" msgid="231837290365031223">"Холбогдож чадсангүй"</string>
<string name="wifi_display_certification_summary" msgid="1155182309166746973">"Утасгүй дэлгэцийн сертификатын сонголтыг харуулах"</string>
<string name="wifi_verbose_logging_summary" msgid="6615071616111731958">"Wi‑Fi лог-н түвшинг нэмэгдүүлэх, Wi‑Fi Сонгогч дээрх SSID-д ногдох RSSI-г харуулах"</string>
<string name="wifi_connected_mac_randomization_summary" msgid="1743059848752201485">"Wi‑Fi сүлжээнд холбогдох үедээ шинэ дурын (random) MAC хаяг үүсгэх"</string>
- <!-- no translation found for wifi_metered_label (4514924227256839725) -->
- <skip />
- <!-- no translation found for wifi_unmetered_label (6124098729457992931) -->
- <skip />
+ <string name="wifi_metered_label" msgid="4514924227256839725">"Хязгаартай"</string>
+ <string name="wifi_unmetered_label" msgid="6124098729457992931">"Хязгааргүй"</string>
<string name="select_logd_size_title" msgid="7433137108348553508">"Логгерын буферын хэмжээ"</string>
<string name="select_logd_size_dialog_title" msgid="1206769310236476760">"Лог буфер бүрт ногдох логгерын хэмжээг сонгоно уу"</string>
<string name="dev_logpersist_clear_warning_title" msgid="684806692440237967">"Нэвтрэгчийн тогтмол санг устгах уу?"</string>
diff --git a/packages/SettingsLib/res/values-mr/strings.xml b/packages/SettingsLib/res/values-mr/strings.xml
index 64f745c..70d142b 100644
--- a/packages/SettingsLib/res/values-mr/strings.xml
+++ b/packages/SettingsLib/res/values-mr/strings.xml
@@ -40,10 +40,8 @@
<string name="connected_via_passpoint" msgid="2826205693803088747">"%1$s द्वारे कनेक्ट केले"</string>
<string name="available_via_passpoint" msgid="1617440946846329613">"%1$s द्वारे उपलब्ध"</string>
<string name="wifi_connected_no_internet" msgid="8202906332837777829">"कनेक्ट केले, इंटरनेट नाही"</string>
- <!-- no translation found for wifi_status_no_internet (5784710974669608361) -->
- <skip />
- <!-- no translation found for wifi_status_sign_in_required (123517180404752756) -->
- <skip />
+ <string name="wifi_status_no_internet" msgid="5784710974669608361">"इंटरनेट नाही"</string>
+ <string name="wifi_status_sign_in_required" msgid="123517180404752756">"साइन इन करणे आवश्यक आहे"</string>
<string name="wifi_ap_unable_to_handle_new_sta" msgid="5348824313514404541">"अॅक्सेस पॉइंट तात्पुरते भरलेले"</string>
<string name="connected_via_carrier" msgid="7583780074526041912">"%1$s ने कनेक्ट केले"</string>
<string name="available_via_carrier" msgid="1469036129740799053">"%1$s ने उपलब्ध"</string>
@@ -67,12 +65,9 @@
<string name="bluetooth_connected_no_headset_battery_level" msgid="1610296229139400266">"कनेक्ट केले (फोन नाही), बॅटरी <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g><xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g>"</string>
<string name="bluetooth_connected_no_a2dp_battery_level" msgid="3908466636369853652">"कनेक्ट केले (मीडिया नाही), बॅटरी <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g><xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g>"</string>
<string name="bluetooth_connected_no_headset_no_a2dp_battery_level" msgid="1163440823807659316">"कनेक्ट केले (फोन किंवा मीडिया नाही), बॅटरी <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g><xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g>"</string>
- <!-- no translation found for bluetooth_active_battery_level (3149689299296462009) -->
- <skip />
- <!-- no translation found for bluetooth_battery_level (1447164613319663655) -->
- <skip />
- <!-- no translation found for bluetooth_active_no_battery_level (8380223546730241956) -->
- <skip />
+ <string name="bluetooth_active_battery_level" msgid="3149689299296462009">"अॅक्टिव्ह, <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> बॅटरी"</string>
+ <string name="bluetooth_battery_level" msgid="1447164613319663655">"<xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> बॅटरी"</string>
+ <string name="bluetooth_active_no_battery_level" msgid="8380223546730241956">"अॅक्टिव्ह"</string>
<string name="bluetooth_profile_a2dp" msgid="2031475486179830674">"मीडिया ऑडिओ"</string>
<string name="bluetooth_profile_headset" msgid="7815495680863246034">"फोन कॉल"</string>
<string name="bluetooth_profile_opp" msgid="9168139293654233697">"फाइल स्थानांतरण"</string>
@@ -119,14 +114,10 @@
<string name="bluetooth_talkback_headphone" msgid="26580326066627664">"हेडफोन"</string>
<string name="bluetooth_talkback_input_peripheral" msgid="5165842622743212268">"इनपुट परिधीय"</string>
<string name="bluetooth_talkback_bluetooth" msgid="5615463912185280812">"ब्लूटूथ"</string>
- <!-- no translation found for bluetooth_hearingaid_left_pairing_message (7378813500862148102) -->
- <skip />
- <!-- no translation found for bluetooth_hearingaid_right_pairing_message (1550373802309160891) -->
- <skip />
- <!-- no translation found for bluetooth_hearingaid_left_battery_level (8797811465352097562) -->
- <skip />
- <!-- no translation found for bluetooth_hearingaid_right_battery_level (7309476148173459677) -->
- <skip />
+ <string name="bluetooth_hearingaid_left_pairing_message" msgid="7378813500862148102">"डावीकडील श्रवण यंत्र जोडत आहे…"</string>
+ <string name="bluetooth_hearingaid_right_pairing_message" msgid="1550373802309160891">"उजवीकडील श्रवण यंत्र जोडत आहे…"</string>
+ <string name="bluetooth_hearingaid_left_battery_level" msgid="8797811465352097562">"डावी - <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> बॅटरी"</string>
+ <string name="bluetooth_hearingaid_right_battery_level" msgid="7309476148173459677">"उजवी - <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> बॅटरी"</string>
<string name="accessibility_wifi_off" msgid="1166761729660614716">"वाय फाय बंद."</string>
<string name="accessibility_no_wifi" msgid="8834610636137374508">"वाय फाय डिस्कनेक्ट झाले."</string>
<string name="accessibility_wifi_one_bar" msgid="4869376278894301820">"वाय फाय एक बार."</string>
@@ -206,8 +197,7 @@
<string name="keep_screen_on" msgid="1146389631208760344">"सक्रिय रहा"</string>
<string name="keep_screen_on_summary" msgid="2173114350754293009">"चार्ज होत असताना स्क्रीन कधीही निष्क्रिय होणार नाही"</string>
<string name="bt_hci_snoop_log" msgid="3340699311158865670">"ब्लूटूथ HCI स्नूप लॉग सक्षम करा"</string>
- <!-- no translation found for bt_hci_snoop_log_summary (366083475849911315) -->
- <skip />
+ <string name="bt_hci_snoop_log_summary" msgid="366083475849911315">"फाइलमध्ये सर्व ब्लूटूथ HCI पॅकेट्स कॅप्चर करा (हे सेटिंग बदलल्यानंतर ब्ल्यूटूथ टॉगल करा)"</string>
<string name="oem_unlock_enable" msgid="6040763321967327691">"OEM अनलॉक करणे"</string>
<string name="oem_unlock_enable_summary" msgid="4720281828891618376">"बूटलोडर अनलॉक करण्यासाठी अनुमती द्या"</string>
<string name="confirm_enable_oem_unlock_title" msgid="4802157344812385674">"OEM अनलॉक करण्यास अनुमती द्यायची?"</string>
@@ -247,15 +237,12 @@
<string name="private_dns_mode_opportunistic" msgid="8314986739896927399">"आपोआप"</string>
<string name="private_dns_mode_provider" msgid="8354935160639360804">"खाजगी DNS पुरवठादार होस्ट नाव"</string>
<string name="private_dns_mode_provider_hostname_hint" msgid="2487492386970928143">"DNS पुरवठादाराचे होस्टनाव टाका"</string>
- <!-- no translation found for private_dns_mode_provider_failure (231837290365031223) -->
- <skip />
+ <string name="private_dns_mode_provider_failure" msgid="231837290365031223">"कनेक्ट करू शकलो नाही"</string>
<string name="wifi_display_certification_summary" msgid="1155182309166746973">"वायरलेस डिस्प्ले प्रमाणिकरणाचे पर्याय दाखवा"</string>
<string name="wifi_verbose_logging_summary" msgid="6615071616111731958">"वाय-फाय लॉगिंग स्तर वाढवा, वाय-फाय सिलेक्टरमध्ये प्रति SSID RSSI दर्शवा"</string>
<string name="wifi_connected_mac_randomization_summary" msgid="1743059848752201485">"वाय-फाय नेटवर्कशी कनेक्ट करताना MAC अॅड्रेस रँडमाइझ करा"</string>
- <!-- no translation found for wifi_metered_label (4514924227256839725) -->
- <skip />
- <!-- no translation found for wifi_unmetered_label (6124098729457992931) -->
- <skip />
+ <string name="wifi_metered_label" msgid="4514924227256839725">"मीटरने मोजलेले"</string>
+ <string name="wifi_unmetered_label" msgid="6124098729457992931">"मीटरने न मोजलेले"</string>
<string name="select_logd_size_title" msgid="7433137108348553508">"लॉगर बफर आकार"</string>
<string name="select_logd_size_dialog_title" msgid="1206769310236476760">"प्रति लॉग बफर लॉगर आकार निवडा"</string>
<string name="dev_logpersist_clear_warning_title" msgid="684806692440237967">"लॉगरवर सतत असणारा संचय साफ करायचा?"</string>
diff --git a/packages/SettingsLib/res/values-ms/strings.xml b/packages/SettingsLib/res/values-ms/strings.xml
index 7f8e73e..2e78318 100644
--- a/packages/SettingsLib/res/values-ms/strings.xml
+++ b/packages/SettingsLib/res/values-ms/strings.xml
@@ -40,10 +40,8 @@
<string name="connected_via_passpoint" msgid="2826205693803088747">"Disambungkan melalui %1$s"</string>
<string name="available_via_passpoint" msgid="1617440946846329613">"Tersedia melalui %1$s"</string>
<string name="wifi_connected_no_internet" msgid="8202906332837777829">"Disambungkan, tiada Internet"</string>
- <!-- no translation found for wifi_status_no_internet (5784710974669608361) -->
- <skip />
- <!-- no translation found for wifi_status_sign_in_required (123517180404752756) -->
- <skip />
+ <string name="wifi_status_no_internet" msgid="5784710974669608361">"Tiada Internet"</string>
+ <string name="wifi_status_sign_in_required" msgid="123517180404752756">"Log masuk diperlukan"</string>
<string name="wifi_ap_unable_to_handle_new_sta" msgid="5348824313514404541">"Titik akses penuh buat sementara waktu"</string>
<string name="connected_via_carrier" msgid="7583780074526041912">"Disambungkan melalui %1$s"</string>
<string name="available_via_carrier" msgid="1469036129740799053">"Tersedia melalui %1$s"</string>
@@ -67,12 +65,9 @@
<string name="bluetooth_connected_no_headset_battery_level" msgid="1610296229139400266">"Disambungkan (tiada telefon), bateri <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g><xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g>"</string>
<string name="bluetooth_connected_no_a2dp_battery_level" msgid="3908466636369853652">"Disambungkan (tiada media), bateri <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g><xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g>"</string>
<string name="bluetooth_connected_no_headset_no_a2dp_battery_level" msgid="1163440823807659316">"Disambungkan (tiada telefon atau media), bateri <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g><xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g>"</string>
- <!-- no translation found for bluetooth_active_battery_level (3149689299296462009) -->
- <skip />
- <!-- no translation found for bluetooth_battery_level (1447164613319663655) -->
- <skip />
- <!-- no translation found for bluetooth_active_no_battery_level (8380223546730241956) -->
- <skip />
+ <string name="bluetooth_active_battery_level" msgid="3149689299296462009">"Aktif, bateri <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
+ <string name="bluetooth_battery_level" msgid="1447164613319663655">"Bateri <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
+ <string name="bluetooth_active_no_battery_level" msgid="8380223546730241956">"Aktif"</string>
<string name="bluetooth_profile_a2dp" msgid="2031475486179830674">"Audio media"</string>
<string name="bluetooth_profile_headset" msgid="7815495680863246034">"Panggilan telefon"</string>
<string name="bluetooth_profile_opp" msgid="9168139293654233697">"Pemindahan fail"</string>
@@ -119,14 +114,10 @@
<string name="bluetooth_talkback_headphone" msgid="26580326066627664">"Fon kepala"</string>
<string name="bluetooth_talkback_input_peripheral" msgid="5165842622743212268">"Persisian Input"</string>
<string name="bluetooth_talkback_bluetooth" msgid="5615463912185280812">"Bluetooth"</string>
- <!-- no translation found for bluetooth_hearingaid_left_pairing_message (7378813500862148102) -->
- <skip />
- <!-- no translation found for bluetooth_hearingaid_right_pairing_message (1550373802309160891) -->
- <skip />
- <!-- no translation found for bluetooth_hearingaid_left_battery_level (8797811465352097562) -->
- <skip />
- <!-- no translation found for bluetooth_hearingaid_right_battery_level (7309476148173459677) -->
- <skip />
+ <string name="bluetooth_hearingaid_left_pairing_message" msgid="7378813500862148102">"Menggandingkan alat bantu pendengaran kiri…"</string>
+ <string name="bluetooth_hearingaid_right_pairing_message" msgid="1550373802309160891">"Menggandingkan alat bantu pendengaran kanan…"</string>
+ <string name="bluetooth_hearingaid_left_battery_level" msgid="8797811465352097562">"Kiri - bateri <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
+ <string name="bluetooth_hearingaid_right_battery_level" msgid="7309476148173459677">"Kanan - bateri <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
<string name="accessibility_wifi_off" msgid="1166761729660614716">"Wi-Fi dimatikan."</string>
<string name="accessibility_no_wifi" msgid="8834610636137374508">"Wi-Fi diputuskan sambungannya."</string>
<string name="accessibility_wifi_one_bar" msgid="4869376278894301820">"Wi-Fi satu bar."</string>
@@ -246,15 +237,12 @@
<string name="private_dns_mode_opportunistic" msgid="8314986739896927399">"Automatik"</string>
<string name="private_dns_mode_provider" msgid="8354935160639360804">"Nama hos pembekal DNS peribadi"</string>
<string name="private_dns_mode_provider_hostname_hint" msgid="2487492386970928143">"Masukkan nama hos pembekal DNS"</string>
- <!-- no translation found for private_dns_mode_provider_failure (231837290365031223) -->
- <skip />
+ <string name="private_dns_mode_provider_failure" msgid="231837290365031223">"Tidak dapat menyambung"</string>
<string name="wifi_display_certification_summary" msgid="1155182309166746973">"Tunjukkan pilihan untuk pensijilan paparan wayarles"</string>
<string name="wifi_verbose_logging_summary" msgid="6615071616111731958">"Tingkatkan tahap pengelogan Wi-Fi, tunjuk setiap SSID RSSI dalam Pemilih Wi-Fi"</string>
<string name="wifi_connected_mac_randomization_summary" msgid="1743059848752201485">"Rawakkan alamat MAC apabila menyambung ke rangkaian Wi‑Fi"</string>
- <!-- no translation found for wifi_metered_label (4514924227256839725) -->
- <skip />
- <!-- no translation found for wifi_unmetered_label (6124098729457992931) -->
- <skip />
+ <string name="wifi_metered_label" msgid="4514924227256839725">"Bermeter"</string>
+ <string name="wifi_unmetered_label" msgid="6124098729457992931">"Tidak bermeter"</string>
<string name="select_logd_size_title" msgid="7433137108348553508">"Saiz penimbal pengelog"</string>
<string name="select_logd_size_dialog_title" msgid="1206769310236476760">"Pilih saiz Pengelog bagi setiap penimbal log"</string>
<string name="dev_logpersist_clear_warning_title" msgid="684806692440237967">"Kosongkan storan gigih pengelog?"</string>
diff --git a/packages/SettingsLib/res/values-my/strings.xml b/packages/SettingsLib/res/values-my/strings.xml
index 1a80a06..e3f996a 100644
--- a/packages/SettingsLib/res/values-my/strings.xml
+++ b/packages/SettingsLib/res/values-my/strings.xml
@@ -197,7 +197,7 @@
<string name="keep_screen_on" msgid="1146389631208760344">"ဖွင့်လျက်သား"</string>
<string name="keep_screen_on_summary" msgid="2173114350754293009">"အားသွင်းနေစဉ် ဖန်သားပြင်မှာဘယ်သောအခါမှ ပိတ်မည်မဟုတ်ပါ။"</string>
<string name="bt_hci_snoop_log" msgid="3340699311158865670">"ဘလူးတုသ် HCI snoop မှတ်တမ်းကို ဖွင့်ရန်။"</string>
- <string name="bt_hci_snoop_log_summary" msgid="366083475849911315">"ဖိုင်တစ်ခုတွင် ဘလူးတုသ် HCI အစုလိုက်များကို ဖမ်းယူရန် (ဤဆက်တင်ကို ပြောင်းပြီးသည့်အခါ ဘလူးတုသ် ဖွင့်/ပိတ် လုပ်ပါ)"</string>
+ <string name="bt_hci_snoop_log_summary" msgid="366083475849911315">"ဖိုင်တစ်ခုတွင် ဘလူးတုသ် HCI အစုလိုက်များကို သိမ်းယူရန် (ဤဆက်တင်ကို ပြောင်းပြီးသည့်အခါ ဘလူးတုသ် ဖွင့်/ပိတ် လုပ်ပါ)"</string>
<string name="oem_unlock_enable" msgid="6040763321967327691">"OEM သော့ဖွင့်ခြင်း"</string>
<string name="oem_unlock_enable_summary" msgid="4720281828891618376">"အစပြုခြင်းကိရိယာအား သော့ဖွင့်ရန် ခွင့်ပြုမည်"</string>
<string name="confirm_enable_oem_unlock_title" msgid="4802157344812385674">"OEM သော့ဖွင့်ခြင်း ခွင့်ပြုမလား?"</string>
diff --git a/packages/SettingsLib/res/values-nb/strings.xml b/packages/SettingsLib/res/values-nb/strings.xml
index cdb7448..369d7d8 100644
--- a/packages/SettingsLib/res/values-nb/strings.xml
+++ b/packages/SettingsLib/res/values-nb/strings.xml
@@ -40,10 +40,8 @@
<string name="connected_via_passpoint" msgid="2826205693803088747">"Tilkoblet via %1$s"</string>
<string name="available_via_passpoint" msgid="1617440946846329613">"Tilgjengelig via %1$s"</string>
<string name="wifi_connected_no_internet" msgid="8202906332837777829">"Tilkoblet – ingen Internett-tilgang"</string>
- <!-- no translation found for wifi_status_no_internet (5784710974669608361) -->
- <skip />
- <!-- no translation found for wifi_status_sign_in_required (123517180404752756) -->
- <skip />
+ <string name="wifi_status_no_internet" msgid="5784710974669608361">"Ingen Internett-tilkobling"</string>
+ <string name="wifi_status_sign_in_required" msgid="123517180404752756">"Pålogging kreves"</string>
<string name="wifi_ap_unable_to_handle_new_sta" msgid="5348824313514404541">"Tilgangspunktet er midlertidig fullt"</string>
<string name="connected_via_carrier" msgid="7583780074526041912">"Tilkoblet via %1$s"</string>
<string name="available_via_carrier" msgid="1469036129740799053">"Tilgjengelig via %1$s"</string>
@@ -67,12 +65,9 @@
<string name="bluetooth_connected_no_headset_battery_level" msgid="1610296229139400266">"Koblet til (ingen telefon), batteri <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g><xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g>"</string>
<string name="bluetooth_connected_no_a2dp_battery_level" msgid="3908466636369853652">"Koblet til (ingen medier), batteri <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g><xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g>"</string>
<string name="bluetooth_connected_no_headset_no_a2dp_battery_level" msgid="1163440823807659316">"Koblet til (ingen telefon eller medier), batteri <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g><xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g>"</string>
- <!-- no translation found for bluetooth_active_battery_level (3149689299296462009) -->
- <skip />
- <!-- no translation found for bluetooth_battery_level (1447164613319663655) -->
- <skip />
- <!-- no translation found for bluetooth_active_no_battery_level (8380223546730241956) -->
- <skip />
+ <string name="bluetooth_active_battery_level" msgid="3149689299296462009">"Aktiv, <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> batteri"</string>
+ <string name="bluetooth_battery_level" msgid="1447164613319663655">"<xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> batteri"</string>
+ <string name="bluetooth_active_no_battery_level" msgid="8380223546730241956">"Aktiv"</string>
<string name="bluetooth_profile_a2dp" msgid="2031475486179830674">"Medielyd"</string>
<string name="bluetooth_profile_headset" msgid="7815495680863246034">"Telefonsamtaler"</string>
<string name="bluetooth_profile_opp" msgid="9168139293654233697">"Filoverføring"</string>
@@ -119,14 +114,10 @@
<string name="bluetooth_talkback_headphone" msgid="26580326066627664">"Øretelefoner"</string>
<string name="bluetooth_talkback_input_peripheral" msgid="5165842622743212268">"Inndata fra ytre utstyrsenheter"</string>
<string name="bluetooth_talkback_bluetooth" msgid="5615463912185280812">"Bluetooth"</string>
- <!-- no translation found for bluetooth_hearingaid_left_pairing_message (7378813500862148102) -->
- <skip />
- <!-- no translation found for bluetooth_hearingaid_right_pairing_message (1550373802309160891) -->
- <skip />
- <!-- no translation found for bluetooth_hearingaid_left_battery_level (8797811465352097562) -->
- <skip />
- <!-- no translation found for bluetooth_hearingaid_right_battery_level (7309476148173459677) -->
- <skip />
+ <string name="bluetooth_hearingaid_left_pairing_message" msgid="7378813500862148102">"Tilkobler venstre høreapparat …"</string>
+ <string name="bluetooth_hearingaid_right_pairing_message" msgid="1550373802309160891">"Tilkobler høyre høreapparat …"</string>
+ <string name="bluetooth_hearingaid_left_battery_level" msgid="8797811465352097562">"Venstre – <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> batteri"</string>
+ <string name="bluetooth_hearingaid_right_battery_level" msgid="7309476148173459677">"Høyre – <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> batteri"</string>
<string name="accessibility_wifi_off" msgid="1166761729660614716">"Wi-Fi er av."</string>
<string name="accessibility_no_wifi" msgid="8834610636137374508">"Wi-Fi er frakoblet."</string>
<string name="accessibility_wifi_one_bar" msgid="4869376278894301820">"Wi-Fi-signal med én stolpe."</string>
@@ -246,15 +237,12 @@
<string name="private_dns_mode_opportunistic" msgid="8314986739896927399">"Automatisk"</string>
<string name="private_dns_mode_provider" msgid="8354935160639360804">"Vertsnavn for privat DNS-leverandør"</string>
<string name="private_dns_mode_provider_hostname_hint" msgid="2487492386970928143">"Skriv inn vertsnavnet til DNS-leverandøren"</string>
- <!-- no translation found for private_dns_mode_provider_failure (231837290365031223) -->
- <skip />
+ <string name="private_dns_mode_provider_failure" msgid="231837290365031223">"Kunne ikke koble til"</string>
<string name="wifi_display_certification_summary" msgid="1155182309166746973">"Vis alternativer for sertifisering av trådløs skjerm"</string>
<string name="wifi_verbose_logging_summary" msgid="6615071616111731958">"Øk Wi-Fi-loggenivå – vis per SSID RSSI i Wi-Fi-velgeren"</string>
<string name="wifi_connected_mac_randomization_summary" msgid="1743059848752201485">"Angi tilfeldig MAC-adresse når du kobler til Wi-Fi-nettverk"</string>
- <!-- no translation found for wifi_metered_label (4514924227256839725) -->
- <skip />
- <!-- no translation found for wifi_unmetered_label (6124098729457992931) -->
- <skip />
+ <string name="wifi_metered_label" msgid="4514924227256839725">"Med datamåling"</string>
+ <string name="wifi_unmetered_label" msgid="6124098729457992931">"Uten datamåling"</string>
<string name="select_logd_size_title" msgid="7433137108348553508">"Bufferstørrelser for logg"</string>
<string name="select_logd_size_dialog_title" msgid="1206769310236476760">"Velg loggstørrelse per loggbuffer"</string>
<string name="dev_logpersist_clear_warning_title" msgid="684806692440237967">"Vil du tømme det varige logglageret?"</string>
diff --git a/packages/SettingsLib/res/values-ne/strings.xml b/packages/SettingsLib/res/values-ne/strings.xml
index 0835c6c..2386d61 100644
--- a/packages/SettingsLib/res/values-ne/strings.xml
+++ b/packages/SettingsLib/res/values-ne/strings.xml
@@ -40,10 +40,8 @@
<string name="connected_via_passpoint" msgid="2826205693803088747">"%1$s मार्फत जडित"</string>
<string name="available_via_passpoint" msgid="1617440946846329613">"%1$s मार्फत उपलब्ध"</string>
<string name="wifi_connected_no_internet" msgid="8202906332837777829">"जडान गरियो तर इन्टरनेट छैन"</string>
- <!-- no translation found for wifi_status_no_internet (5784710974669608361) -->
- <skip />
- <!-- no translation found for wifi_status_sign_in_required (123517180404752756) -->
- <skip />
+ <string name="wifi_status_no_internet" msgid="5784710974669608361">"इन्टरनेटमाथिको पहुँच छैन"</string>
+ <string name="wifi_status_sign_in_required" msgid="123517180404752756">"साइन इन गर्न आवश्यक छ"</string>
<string name="wifi_ap_unable_to_handle_new_sta" msgid="5348824313514404541">"पहुँचसम्बन्धी स्थान अस्थायी रूपमा भरिएको छ"</string>
<string name="connected_via_carrier" msgid="7583780074526041912">"%1$s मार्फत जडान गरियो"</string>
<string name="available_via_carrier" msgid="1469036129740799053">"%1$s मार्फत उपलब्ध"</string>
@@ -67,12 +65,9 @@
<string name="bluetooth_connected_no_headset_battery_level" msgid="1610296229139400266">"जडान गरियो (फोनबाहेेक), ब्याट्री <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g><xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g>"</string>
<string name="bluetooth_connected_no_a2dp_battery_level" msgid="3908466636369853652">"जडान गरियो (मिडियाबाहेक), ब्याट्री <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g><xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g>"</string>
<string name="bluetooth_connected_no_headset_no_a2dp_battery_level" msgid="1163440823807659316">"जडान गरियो (फोन वा मिडियाबाहेक), ब्याट्री <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g><xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g>"</string>
- <!-- no translation found for bluetooth_active_battery_level (3149689299296462009) -->
- <skip />
- <!-- no translation found for bluetooth_battery_level (1447164613319663655) -->
- <skip />
- <!-- no translation found for bluetooth_active_no_battery_level (8380223546730241956) -->
- <skip />
+ <string name="bluetooth_active_battery_level" msgid="3149689299296462009">"सक्रिय, ब्याट्रीको स्तर: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
+ <string name="bluetooth_battery_level" msgid="1447164613319663655">"ब्याट्रीको स्तर: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
+ <string name="bluetooth_active_no_battery_level" msgid="8380223546730241956">"सक्रिय"</string>
<string name="bluetooth_profile_a2dp" msgid="2031475486179830674">"मिडिया अडियो"</string>
<string name="bluetooth_profile_headset" msgid="7815495680863246034">"फोन कलहरू"</string>
<string name="bluetooth_profile_opp" msgid="9168139293654233697">"फाइल स्थानान्तरण"</string>
@@ -119,14 +114,10 @@
<string name="bluetooth_talkback_headphone" msgid="26580326066627664">"हेडफोन"</string>
<string name="bluetooth_talkback_input_peripheral" msgid="5165842622743212268">"इनपुट सम्बन्धी बाह्य यन्त्र"</string>
<string name="bluetooth_talkback_bluetooth" msgid="5615463912185280812">"ब्लुटुथ"</string>
- <!-- no translation found for bluetooth_hearingaid_left_pairing_message (7378813500862148102) -->
- <skip />
- <!-- no translation found for bluetooth_hearingaid_right_pairing_message (1550373802309160891) -->
- <skip />
- <!-- no translation found for bluetooth_hearingaid_left_battery_level (8797811465352097562) -->
- <skip />
- <!-- no translation found for bluetooth_hearingaid_right_battery_level (7309476148173459677) -->
- <skip />
+ <string name="bluetooth_hearingaid_left_pairing_message" msgid="7378813500862148102">"दायाँतर्फको श्रवण यन्त्रको जोडा बनाउँदै…"</string>
+ <string name="bluetooth_hearingaid_right_pairing_message" msgid="1550373802309160891">"बायाँतर्फको श्रवण यन्त्रको जोडा बनाउँदै…"</string>
+ <string name="bluetooth_hearingaid_left_battery_level" msgid="8797811465352097562">"बायाँ - ब्याट्रीको स्तर: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
+ <string name="bluetooth_hearingaid_right_battery_level" msgid="7309476148173459677">"दायाँ - ब्याट्रीको स्तर: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
<string name="accessibility_wifi_off" msgid="1166761729660614716">"Wi-Fi बन्द।"</string>
<string name="accessibility_no_wifi" msgid="8834610636137374508">"Wi-Fi जडान विच्छेद भयो।"</string>
<string name="accessibility_wifi_one_bar" msgid="4869376278894301820">"Wi-Fi एक पट्टि।"</string>
@@ -206,8 +197,7 @@
<string name="keep_screen_on" msgid="1146389631208760344">"जागा रहनुहोस्"</string>
<string name="keep_screen_on_summary" msgid="2173114350754293009">"चार्ज गर्ने बेलामा स्क्रिन कहिल्यै सुत्दैन।"</string>
<string name="bt_hci_snoop_log" msgid="3340699311158865670">"ब्लुटुथ HCI snoop लग सक्षम पार्नुहोस्"</string>
- <!-- no translation found for bt_hci_snoop_log_summary (366083475849911315) -->
- <skip />
+ <string name="bt_hci_snoop_log_summary" msgid="366083475849911315">"फाइलका सबै ब्लुटुथ HCI प्याकेटहरू समावेश गर्नुहोस् (यो सेटिङ परिवर्तन गरेपछि ब्लुटुथ टगल गर्नुहोस्)"</string>
<string name="oem_unlock_enable" msgid="6040763321967327691">"OEM अनलक गर्दै"</string>
<string name="oem_unlock_enable_summary" msgid="4720281828891618376">"अनलक हुन बूटलोडरलाई अनुमति दिनुहोस्"</string>
<string name="confirm_enable_oem_unlock_title" msgid="4802157344812385674">"OEM अनलक गर्न अनुमति दिने?"</string>
@@ -247,15 +237,12 @@
<string name="private_dns_mode_opportunistic" msgid="8314986739896927399">"स्वचालित"</string>
<string name="private_dns_mode_provider" msgid="8354935160639360804">"निजी DNS प्रदायकको होस्टनाम"</string>
<string name="private_dns_mode_provider_hostname_hint" msgid="2487492386970928143">"DNS प्रदायकको होस्टनाम प्रविष्ट गर्नुहोस्"</string>
- <!-- no translation found for private_dns_mode_provider_failure (231837290365031223) -->
- <skip />
+ <string name="private_dns_mode_provider_failure" msgid="231837290365031223">"जडान गर्न सकिएन"</string>
<string name="wifi_display_certification_summary" msgid="1155182309166746973">"ताररहित प्रदर्शन प्रमाणीकरणका लागि विकल्पहरू देखाउनुहोस्"</string>
<string name="wifi_verbose_logging_summary" msgid="6615071616111731958">"Wi-Fi लग स्तर बढाउनुहोस्, Wi-Fi चयनकर्तामा प्रति SSID RSSI देखाइन्छ"</string>
<string name="wifi_connected_mac_randomization_summary" msgid="1743059848752201485">"Wi‑Fi नेटवर्कहरूमा जडान गर्ने बेला MAC को ठेगाना अनियमित गर्नुहोस्"</string>
- <!-- no translation found for wifi_metered_label (4514924227256839725) -->
- <skip />
- <!-- no translation found for wifi_unmetered_label (6124098729457992931) -->
- <skip />
+ <string name="wifi_metered_label" msgid="4514924227256839725">"मिटर गरिएको जडान भनी चिन्ह लगाइएको"</string>
+ <string name="wifi_unmetered_label" msgid="6124098729457992931">"मिटर नगरिएको"</string>
<string name="select_logd_size_title" msgid="7433137108348553508">"लगर बफर आकारहरू"</string>
<string name="select_logd_size_dialog_title" msgid="1206769310236476760">"लग बफर प्रति लगर आकार चयन गर्नुहोस्"</string>
<string name="dev_logpersist_clear_warning_title" msgid="684806692440237967">"लगरको निरन्तर भण्डारणलाई खाली गर्ने हो?"</string>
diff --git a/packages/SettingsLib/res/values-nl/strings.xml b/packages/SettingsLib/res/values-nl/strings.xml
index 18d3a08..69e2301 100644
--- a/packages/SettingsLib/res/values-nl/strings.xml
+++ b/packages/SettingsLib/res/values-nl/strings.xml
@@ -40,10 +40,8 @@
<string name="connected_via_passpoint" msgid="2826205693803088747">"Verbonden via %1$s"</string>
<string name="available_via_passpoint" msgid="1617440946846329613">"Beschikbaar via %1$s"</string>
<string name="wifi_connected_no_internet" msgid="8202906332837777829">"Verbonden, geen internet"</string>
- <!-- no translation found for wifi_status_no_internet (5784710974669608361) -->
- <skip />
- <!-- no translation found for wifi_status_sign_in_required (123517180404752756) -->
- <skip />
+ <string name="wifi_status_no_internet" msgid="5784710974669608361">"Geen internet"</string>
+ <string name="wifi_status_sign_in_required" msgid="123517180404752756">"Inloggen vereist"</string>
<string name="wifi_ap_unable_to_handle_new_sta" msgid="5348824313514404541">"Toegangspunt tijdelijk vol"</string>
<string name="connected_via_carrier" msgid="7583780074526041912">"Verbonden via %1$s"</string>
<string name="available_via_carrier" msgid="1469036129740799053">"Beschikbaar via %1$s"</string>
@@ -67,12 +65,9 @@
<string name="bluetooth_connected_no_headset_battery_level" msgid="1610296229139400266">"Verbonden: <xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g> (geen telefoon), batterij: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
<string name="bluetooth_connected_no_a2dp_battery_level" msgid="3908466636369853652">"Verbonden: <xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g> (geen media), batterij: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
<string name="bluetooth_connected_no_headset_no_a2dp_battery_level" msgid="1163440823807659316">"Verbonden: <xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g> (geen telefoon of media), batterij: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
- <!-- no translation found for bluetooth_active_battery_level (3149689299296462009) -->
- <skip />
- <!-- no translation found for bluetooth_battery_level (1447164613319663655) -->
- <skip />
- <!-- no translation found for bluetooth_active_no_battery_level (8380223546730241956) -->
- <skip />
+ <string name="bluetooth_active_battery_level" msgid="3149689299296462009">"Actief, batterijniveau <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
+ <string name="bluetooth_battery_level" msgid="1447164613319663655">"Batterijniveau <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
+ <string name="bluetooth_active_no_battery_level" msgid="8380223546730241956">"Actief"</string>
<string name="bluetooth_profile_a2dp" msgid="2031475486179830674">"Media-audio"</string>
<string name="bluetooth_profile_headset" msgid="7815495680863246034">"Telefoongesprekken"</string>
<string name="bluetooth_profile_opp" msgid="9168139293654233697">"Bestandsoverdracht"</string>
@@ -119,14 +114,10 @@
<string name="bluetooth_talkback_headphone" msgid="26580326066627664">"Hoofdtelefoon"</string>
<string name="bluetooth_talkback_input_peripheral" msgid="5165842622743212268">"Randapparaat voor invoer"</string>
<string name="bluetooth_talkback_bluetooth" msgid="5615463912185280812">"Bluetooth"</string>
- <!-- no translation found for bluetooth_hearingaid_left_pairing_message (7378813500862148102) -->
- <skip />
- <!-- no translation found for bluetooth_hearingaid_right_pairing_message (1550373802309160891) -->
- <skip />
- <!-- no translation found for bluetooth_hearingaid_left_battery_level (8797811465352097562) -->
- <skip />
- <!-- no translation found for bluetooth_hearingaid_right_battery_level (7309476148173459677) -->
- <skip />
+ <string name="bluetooth_hearingaid_left_pairing_message" msgid="7378813500862148102">"Linker gehoorapparaat koppelen…"</string>
+ <string name="bluetooth_hearingaid_right_pairing_message" msgid="1550373802309160891">"Rechter gehoorapparaat koppelen…"</string>
+ <string name="bluetooth_hearingaid_left_battery_level" msgid="8797811465352097562">"Links: batterijniveau <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
+ <string name="bluetooth_hearingaid_right_battery_level" msgid="7309476148173459677">"Rechts: batterijniveau <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
<string name="accessibility_wifi_off" msgid="1166761729660614716">"Wifi: uitgeschakeld."</string>
<string name="accessibility_no_wifi" msgid="8834610636137374508">"Wifi-verbinding verbroken."</string>
<string name="accessibility_wifi_one_bar" msgid="4869376278894301820">"Wifi: één streepje."</string>
@@ -246,15 +237,12 @@
<string name="private_dns_mode_opportunistic" msgid="8314986739896927399">"Automatisch"</string>
<string name="private_dns_mode_provider" msgid="8354935160639360804">"Hostnaam van privé-DNS-provider"</string>
<string name="private_dns_mode_provider_hostname_hint" msgid="2487492386970928143">"Geef hostnaam van DNS-provider op"</string>
- <!-- no translation found for private_dns_mode_provider_failure (231837290365031223) -->
- <skip />
+ <string name="private_dns_mode_provider_failure" msgid="231837290365031223">"Kan geen verbinding maken"</string>
<string name="wifi_display_certification_summary" msgid="1155182309166746973">"Opties weergeven voor certificering van draadloze weergave"</string>
<string name="wifi_verbose_logging_summary" msgid="6615071616111731958">"Logniveau voor wifi verhogen, weergeven per SSID RSSI in wifi-kiezer"</string>
<string name="wifi_connected_mac_randomization_summary" msgid="1743059848752201485">"Een willekeurig MAC-adres bij het maken van verbinding met wifi-netwerken"</string>
- <!-- no translation found for wifi_metered_label (4514924227256839725) -->
- <skip />
- <!-- no translation found for wifi_unmetered_label (6124098729457992931) -->
- <skip />
+ <string name="wifi_metered_label" msgid="4514924227256839725">"Betaald"</string>
+ <string name="wifi_unmetered_label" msgid="6124098729457992931">"Gratis"</string>
<string name="select_logd_size_title" msgid="7433137108348553508">"Logger-buffergrootten"</string>
<string name="select_logd_size_dialog_title" msgid="1206769310236476760">"Kies Logger-grootten per logbuffer"</string>
<string name="dev_logpersist_clear_warning_title" msgid="684806692440237967">"Persistente loggeropslag wissen?"</string>
diff --git a/packages/SettingsLib/res/values-or/strings.xml b/packages/SettingsLib/res/values-or/strings.xml
index d7b2dc9..4591872 100644
--- a/packages/SettingsLib/res/values-or/strings.xml
+++ b/packages/SettingsLib/res/values-or/strings.xml
@@ -206,8 +206,7 @@
<string name="keep_screen_on" msgid="1146389631208760344">"ଜାଗ୍ରତ ରଖନ୍ତୁ"</string>
<string name="keep_screen_on_summary" msgid="2173114350754293009">"ଚାର୍ଜ ହେବାବେଳେ ସ୍କ୍ରୀନ୍ ଆଦୌ ବନ୍ଦ ହେବନାହିଁ"</string>
<string name="bt_hci_snoop_log" msgid="3340699311158865670">"ବ୍ଲୁଟୁଥ୍ HCI ସ୍ନୁପ୍ ଲଗ୍ ସକ୍ଷମ କରନ୍ତୁ"</string>
- <!-- no translation found for bt_hci_snoop_log_summary (366083475849911315) -->
- <skip />
+ <string name="bt_hci_snoop_log_summary" msgid="366083475849911315">"ଗୋଟିଏ ଫାଇଲ୍ରେ ସମସ୍ତ ବ୍ଲୁ-ଟୁଥ୍ HCI ପ୍ୟାକେଟ୍ଗୁଡିକୁ କ୍ୟାପଚର୍ କରନ୍ତୁ (ଏହି ସେଟିଙ୍ଗ ବଦଳାଇବା ପରେ ବ୍ଲୁ-ଟୁଥ୍କୁ ଅନ୍ କିମ୍ବା ଅଫ୍ କରନ୍ତୁ)"</string>
<string name="oem_unlock_enable" msgid="6040763321967327691">"OEM ଅନଲକ୍ କରିବା"</string>
<string name="oem_unlock_enable_summary" msgid="4720281828891618376">"bootloaderକୁ ଅନ୍ଲକ୍ ହେବାର ଅନୁମତି ଦିଅନ୍ତୁ"</string>
<string name="confirm_enable_oem_unlock_title" msgid="4802157344812385674">"OEM ଅନଲକ୍ କରିବା ଅନୁମତି ଦେବେ?"</string>
diff --git a/packages/SettingsLib/res/values-pa/strings.xml b/packages/SettingsLib/res/values-pa/strings.xml
index 313413a..21a3be0 100644
--- a/packages/SettingsLib/res/values-pa/strings.xml
+++ b/packages/SettingsLib/res/values-pa/strings.xml
@@ -40,10 +40,8 @@
<string name="connected_via_passpoint" msgid="2826205693803088747">"%1$s ਰਾਹੀਂ ਕਨੈਕਟ ਕੀਤਾ"</string>
<string name="available_via_passpoint" msgid="1617440946846329613">"%1$s ਰਾਹੀਂ ਉਪਲਬਧ"</string>
<string name="wifi_connected_no_internet" msgid="8202906332837777829">"ਕਨੈਕਟ ਕੀਤਾ, ਕੋਈ ਇੰਟਰਨੈੱਟ ਨਹੀਂ"</string>
- <!-- no translation found for wifi_status_no_internet (5784710974669608361) -->
- <skip />
- <!-- no translation found for wifi_status_sign_in_required (123517180404752756) -->
- <skip />
+ <string name="wifi_status_no_internet" msgid="5784710974669608361">"ਇੰਟਰਨੈੱਟ ਨਹੀਂ"</string>
+ <string name="wifi_status_sign_in_required" msgid="123517180404752756">"ਸਾਈਨ-ਇਨ ਲੋੜੀਂਦਾ ਹੈ"</string>
<string name="wifi_ap_unable_to_handle_new_sta" msgid="5348824313514404541">"ਐਕਸੈੱਸ ਪੁਆਇੰਟ ਅਸਥਾਈ ਤੌਰ \'ਤੇ ਸੰਪੂਰਨ ਰੁਝੇਂਵੇਂ ਵਿੱਚ ਹੈ"</string>
<string name="connected_via_carrier" msgid="7583780074526041912">"%1$s ਰਾਹੀਂ ਕਨੈਕਟ ਕੀਤਾ"</string>
<string name="available_via_carrier" msgid="1469036129740799053">"%1$s ਰਾਹੀਂ ਉਪਲਬਧ"</string>
@@ -67,12 +65,9 @@
<string name="bluetooth_connected_no_headset_battery_level" msgid="1610296229139400266">"ਕਨੈਕਟ ਕੀਤਾ ਹੋਇਆ (ਕੋਈ ਫ਼ੋਨ ਨਹੀਂ), ਬੈਟਰੀ ਦਾ ਪੱਧਰ <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g><xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g>"</string>
<string name="bluetooth_connected_no_a2dp_battery_level" msgid="3908466636369853652">"ਕਨੈਕਟ ਕੀਤਾ ਹੋਇਆ (ਕੋਈ ਮੀਡੀਆ ਨਹੀਂ), ਬੈਟਰੀ ਦਾ ਪੱਧਰ <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g><xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g>"</string>
<string name="bluetooth_connected_no_headset_no_a2dp_battery_level" msgid="1163440823807659316">"ਕਨੈਕਟ ਕੀਤਾ ਹੋਇਆ (ਕੋਈ ਫ਼ੋਨ ਜਾਂ ਮੀਡੀਆ ਨਹੀਂ), ਬੈਟਰੀ ਦਾ ਪੱਧਰ <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g><xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g>"</string>
- <!-- no translation found for bluetooth_active_battery_level (3149689299296462009) -->
- <skip />
- <!-- no translation found for bluetooth_battery_level (1447164613319663655) -->
- <skip />
- <!-- no translation found for bluetooth_active_no_battery_level (8380223546730241956) -->
- <skip />
+ <string name="bluetooth_active_battery_level" msgid="3149689299296462009">"ਕਿਰਿਆਸ਼ੀਲ, <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> ਬੈਟਰੀ"</string>
+ <string name="bluetooth_battery_level" msgid="1447164613319663655">"<xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> ਬੈਟਰੀ"</string>
+ <string name="bluetooth_active_no_battery_level" msgid="8380223546730241956">"ਕਿਰਿਆਸ਼ੀਲ"</string>
<string name="bluetooth_profile_a2dp" msgid="2031475486179830674">"ਮੀਡੀਆ ਆਡੀਓ"</string>
<string name="bluetooth_profile_headset" msgid="7815495680863246034">"ਫ਼ੋਨ ਕਾਲਾਂ"</string>
<string name="bluetooth_profile_opp" msgid="9168139293654233697">"ਫਾਈਲ ਟ੍ਰਾਂਸਫਰ"</string>
@@ -119,14 +114,10 @@
<string name="bluetooth_talkback_headphone" msgid="26580326066627664">"ਹੈੱਡਫੋਨ"</string>
<string name="bluetooth_talkback_input_peripheral" msgid="5165842622743212268">"ਇਨਪੁੱਟ ਪੈਰਿਫੈਰਲ"</string>
<string name="bluetooth_talkback_bluetooth" msgid="5615463912185280812">"ਬਲੂਟੁੱਥ"</string>
- <!-- no translation found for bluetooth_hearingaid_left_pairing_message (7378813500862148102) -->
- <skip />
- <!-- no translation found for bluetooth_hearingaid_right_pairing_message (1550373802309160891) -->
- <skip />
- <!-- no translation found for bluetooth_hearingaid_left_battery_level (8797811465352097562) -->
- <skip />
- <!-- no translation found for bluetooth_hearingaid_right_battery_level (7309476148173459677) -->
- <skip />
+ <string name="bluetooth_hearingaid_left_pairing_message" msgid="7378813500862148102">"ਖੱਬੇ ਪਾਸੇ ਦਾ ਸੁਣਨ ਦਾ ਸਾਧਨ ਜੋੜਾਬੱਧ ਕੀਤਾ ਜਾ ਰਿਹਾ ਹੈ…"</string>
+ <string name="bluetooth_hearingaid_right_pairing_message" msgid="1550373802309160891">"ਸੱਜੇ ਪਾਸੇ ਦਾ ਸੁਣਨ ਦਾ ਸਾਧਨ ਜੋੜਾਬੱਧ ਕੀਤਾ ਜਾ ਰਿਹਾ ਹੈ…"</string>
+ <string name="bluetooth_hearingaid_left_battery_level" msgid="8797811465352097562">"ਖੱਬੇ ਪਾਸੇ - <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> ਬੈਟਰੀ"</string>
+ <string name="bluetooth_hearingaid_right_battery_level" msgid="7309476148173459677">"ਸੱਜੇ ਪਾਸੇ - <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> ਬੈਟਰੀ"</string>
<string name="accessibility_wifi_off" msgid="1166761729660614716">"Wifi ਬੰਦ।"</string>
<string name="accessibility_no_wifi" msgid="8834610636137374508">"Wifi ਡਿਸਕਨੈਕਟ ਕੀਤਾ।"</string>
<string name="accessibility_wifi_one_bar" msgid="4869376278894301820">"Wifi ਇੱਕ ਬਾਰ।"</string>
@@ -206,8 +197,7 @@
<string name="keep_screen_on" msgid="1146389631208760344">"ਸਕਿਰਿਆ ਰੱਖੋ"</string>
<string name="keep_screen_on_summary" msgid="2173114350754293009">"ਸਕ੍ਰੀਨ ਚਾਰਜਿੰਗ ਦੇ ਸਮੇਂ ਕਦੇ ਵੀ ਸਲੀਪ ਨਹੀਂ ਹੋਵੇਗੀ"</string>
<string name="bt_hci_snoop_log" msgid="3340699311158865670">"ਬਲੂਟੁੱਥ HCI ਸਨੂਪ ਲੌਗ ਨੂੰ ਚਾਲੂ ਕਰੋ"</string>
- <!-- no translation found for bt_hci_snoop_log_summary (366083475849911315) -->
- <skip />
+ <string name="bt_hci_snoop_log_summary" msgid="366083475849911315">"ਇੱਕ ਫ਼ਾਈਲ ਵਿੱਚ ਸਾਰੇ ਬਲੂਟੁੱਥ HCI ਪੈਕੇਟਾਂ ਨੂੰ ਕੈਪਚਰ ਕਰੋ (ਇਹ ਸੈਟਿੰਗ ਬਦਲਣ ਤੋਂ ਬਾਅਦ ਬਲੂਟੁੱਥ ਟੌਗਲ ਕਰੋ)"</string>
<string name="oem_unlock_enable" msgid="6040763321967327691">"OEM ਅਣਲਾਕ ਕਰਨਾ"</string>
<string name="oem_unlock_enable_summary" msgid="4720281828891618376">"ਬੂਟਲੋਡਰ ਨੂੰ ਅਣਲਾਕ ਕੀਤੇ ਜਾਣ ਦੀ ਆਗਿਆ ਦਿਓ"</string>
<string name="confirm_enable_oem_unlock_title" msgid="4802157344812385674">"ਕੀ OEM ਨੂੰ ਅਣਲਾਕ ਕਰਨ ਦੀ ਆਗਿਆ ਦੇਣੀ ਹੈ?"</string>
@@ -247,15 +237,12 @@
<string name="private_dns_mode_opportunistic" msgid="8314986739896927399">"ਸਵੈਚਲਿਤ"</string>
<string name="private_dns_mode_provider" msgid="8354935160639360804">"ਨਿੱਜੀ DNS ਪ੍ਰਦਾਨਕ ਹੋਸਟਨਾਮ"</string>
<string name="private_dns_mode_provider_hostname_hint" msgid="2487492386970928143">"DNS ਪ੍ਰਦਾਨਕ ਦਾ ਹੋਸਟਨਾਮ ਦਾਖਲ ਕਰੋ"</string>
- <!-- no translation found for private_dns_mode_provider_failure (231837290365031223) -->
- <skip />
+ <string name="private_dns_mode_provider_failure" msgid="231837290365031223">"ਕਨੈਕਟ ਨਹੀਂ ਕੀਤਾ ਜਾ ਸਕਿਆ"</string>
<string name="wifi_display_certification_summary" msgid="1155182309166746973">"ਵਾਇਰਲੈੱਸ ਡਿਸਪਲੇ ਪ੍ਰਮਾਣੀਕਰਨ ਲਈ ਚੋਣਾਂ ਪ੍ਰਦਰਸ਼ਿਤ ਕਰੋ"</string>
<string name="wifi_verbose_logging_summary" msgid="6615071616111731958">"ਵਾਈ‑ਫਾਈ ਲੌਗਿੰਗ ਪੱਧਰ ਵਧਾਓ, ਵਾਈ‑ਫਾਈ Picker ਵਿੱਚ ਪ੍ਰਤੀ SSID RSSI ਦਿਖਾਓ"</string>
<string name="wifi_connected_mac_randomization_summary" msgid="1743059848752201485">"ਵਾਈ-ਫਾਈ ਨੈੱਟਵਰਕਾਂ ਨਾਲ ਕਨੈਕਟ ਹੋਣ \'ਤੇ MAC ਪਤਾ ਬੇਤਰਤੀਬਵਾਰ ਚੁਣੋ"</string>
- <!-- no translation found for wifi_metered_label (4514924227256839725) -->
- <skip />
- <!-- no translation found for wifi_unmetered_label (6124098729457992931) -->
- <skip />
+ <string name="wifi_metered_label" msgid="4514924227256839725">"ਮੀਟਰਬੱਧ ਕੀਤਾ ਗਿਆ"</string>
+ <string name="wifi_unmetered_label" msgid="6124098729457992931">"ਗੈਰ-ਮੀਟਰਬੱਧ ਕੀਤਾ ਗਿਆ"</string>
<string name="select_logd_size_title" msgid="7433137108348553508">"ਲੌਗਰ ਬਫ਼ਰ ਆਕਾਰ"</string>
<string name="select_logd_size_dialog_title" msgid="1206769310236476760">"ਪ੍ਰਤੀ ਲੌਗ ਬਫ਼ਰ ਲੌਗਰ ਆਕਾਰ ਚੁਣੋ"</string>
<string name="dev_logpersist_clear_warning_title" msgid="684806692440237967">"ਕੀ ਲੌਗਰ ਪ੍ਰਸਿੱਸਟੈਂਟ ਸਟੋਰੇਜ ਨੂੰ ਸਾਫ਼ ਕਰਨਾ ਹੈ?"</string>
diff --git a/packages/SettingsLib/res/values-pl/strings.xml b/packages/SettingsLib/res/values-pl/strings.xml
index 3192719..fa396f2 100644
--- a/packages/SettingsLib/res/values-pl/strings.xml
+++ b/packages/SettingsLib/res/values-pl/strings.xml
@@ -40,10 +40,8 @@
<string name="connected_via_passpoint" msgid="2826205693803088747">"Połączono przez %1$s"</string>
<string name="available_via_passpoint" msgid="1617440946846329613">"Dostępne przez %1$s"</string>
<string name="wifi_connected_no_internet" msgid="8202906332837777829">"Połączono, brak internetu"</string>
- <!-- no translation found for wifi_status_no_internet (5784710974669608361) -->
- <skip />
- <!-- no translation found for wifi_status_sign_in_required (123517180404752756) -->
- <skip />
+ <string name="wifi_status_no_internet" msgid="5784710974669608361">"Brak internetu"</string>
+ <string name="wifi_status_sign_in_required" msgid="123517180404752756">"Musisz się zalogować"</string>
<string name="wifi_ap_unable_to_handle_new_sta" msgid="5348824313514404541">"Punkt dostępu jest tymczasowo zajęty"</string>
<string name="connected_via_carrier" msgid="7583780074526041912">"Połączono przez: %1$s"</string>
<string name="available_via_carrier" msgid="1469036129740799053">"Dostępna przez: %1$s"</string>
@@ -67,12 +65,9 @@
<string name="bluetooth_connected_no_headset_battery_level" msgid="1610296229139400266">"Połączono (bez telefonu), bateria: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> – <xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g>"</string>
<string name="bluetooth_connected_no_a2dp_battery_level" msgid="3908466636369853652">"Połączono (bez multimediów), bateria: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> – <xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g>"</string>
<string name="bluetooth_connected_no_headset_no_a2dp_battery_level" msgid="1163440823807659316">"Połączono (bez telefonu i multimediów), bateria <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> – <xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g>"</string>
- <!-- no translation found for bluetooth_active_battery_level (3149689299296462009) -->
- <skip />
- <!-- no translation found for bluetooth_battery_level (1447164613319663655) -->
- <skip />
- <!-- no translation found for bluetooth_active_no_battery_level (8380223546730241956) -->
- <skip />
+ <string name="bluetooth_active_battery_level" msgid="3149689299296462009">"Aktywne, <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> naładowania baterii"</string>
+ <string name="bluetooth_battery_level" msgid="1447164613319663655">"<xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> naładowania baterii"</string>
+ <string name="bluetooth_active_no_battery_level" msgid="8380223546730241956">"Urządzenie aktywne"</string>
<string name="bluetooth_profile_a2dp" msgid="2031475486179830674">"Dźwięk multimediów"</string>
<string name="bluetooth_profile_headset" msgid="7815495680863246034">"Połączenia telefoniczne"</string>
<string name="bluetooth_profile_opp" msgid="9168139293654233697">"Przesyłanie pliku"</string>
@@ -119,14 +114,10 @@
<string name="bluetooth_talkback_headphone" msgid="26580326066627664">"Słuchawki"</string>
<string name="bluetooth_talkback_input_peripheral" msgid="5165842622743212268">"Peryferyjne urządzenie wejściowe"</string>
<string name="bluetooth_talkback_bluetooth" msgid="5615463912185280812">"Bluetooth"</string>
- <!-- no translation found for bluetooth_hearingaid_left_pairing_message (7378813500862148102) -->
- <skip />
- <!-- no translation found for bluetooth_hearingaid_right_pairing_message (1550373802309160891) -->
- <skip />
- <!-- no translation found for bluetooth_hearingaid_left_battery_level (8797811465352097562) -->
- <skip />
- <!-- no translation found for bluetooth_hearingaid_right_battery_level (7309476148173459677) -->
- <skip />
+ <string name="bluetooth_hearingaid_left_pairing_message" msgid="7378813500862148102">"Paruję lewy aparat słuchowy…"</string>
+ <string name="bluetooth_hearingaid_right_pairing_message" msgid="1550373802309160891">"Paruję prawy aparat słuchowy…"</string>
+ <string name="bluetooth_hearingaid_left_battery_level" msgid="8797811465352097562">"Aparat lewy – <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> naładowania baterii"</string>
+ <string name="bluetooth_hearingaid_right_battery_level" msgid="7309476148173459677">"Aparat prawy – <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> naładowania baterii"</string>
<string name="accessibility_wifi_off" msgid="1166761729660614716">"Wi-Fi wyłączone."</string>
<string name="accessibility_no_wifi" msgid="8834610636137374508">"Wi-Fi odłączone."</string>
<string name="accessibility_wifi_one_bar" msgid="4869376278894301820">"Wi-Fi: jeden pasek."</string>
@@ -246,15 +237,12 @@
<string name="private_dns_mode_opportunistic" msgid="8314986739896927399">"Automatyczny"</string>
<string name="private_dns_mode_provider" msgid="8354935160639360804">"Nazwa hosta dostawcy prywatnego DNS"</string>
<string name="private_dns_mode_provider_hostname_hint" msgid="2487492386970928143">"Wpisz nazwę hosta dostawcy DNS"</string>
- <!-- no translation found for private_dns_mode_provider_failure (231837290365031223) -->
- <skip />
+ <string name="private_dns_mode_provider_failure" msgid="231837290365031223">"Nie udało się połączyć"</string>
<string name="wifi_display_certification_summary" msgid="1155182309166746973">"Pokaż opcje certyfikacji wyświetlacza bezprzewodowego"</string>
<string name="wifi_verbose_logging_summary" msgid="6615071616111731958">"Zwiększ poziom rejestrowania Wi‑Fi, pokazuj według RSSI SSID w selektorze Wi‑Fi"</string>
<string name="wifi_connected_mac_randomization_summary" msgid="1743059848752201485">"Wygeneruj losowo adres MAC podczas łączenia z siecią Wi‑Fi"</string>
- <!-- no translation found for wifi_metered_label (4514924227256839725) -->
- <skip />
- <!-- no translation found for wifi_unmetered_label (6124098729457992931) -->
- <skip />
+ <string name="wifi_metered_label" msgid="4514924227256839725">"Użycie danych jest mierzone"</string>
+ <string name="wifi_unmetered_label" msgid="6124098729457992931">"Użycie danych nie jest mierzone"</string>
<string name="select_logd_size_title" msgid="7433137108348553508">"Rozmiary bufora Rejestratora"</string>
<string name="select_logd_size_dialog_title" msgid="1206769310236476760">"Wybierz rozmiary Rejestratora/bufor dziennika"</string>
<string name="dev_logpersist_clear_warning_title" msgid="684806692440237967">"Wyczyścić pamięć trwałych dzienników?"</string>
diff --git a/packages/SettingsLib/res/values-ru/strings.xml b/packages/SettingsLib/res/values-ru/strings.xml
index fdf8290..b0d65b66 100644
--- a/packages/SettingsLib/res/values-ru/strings.xml
+++ b/packages/SettingsLib/res/values-ru/strings.xml
@@ -40,10 +40,8 @@
<string name="connected_via_passpoint" msgid="2826205693803088747">"Подключено к %1$s"</string>
<string name="available_via_passpoint" msgid="1617440946846329613">"Доступно через %1$s"</string>
<string name="wifi_connected_no_internet" msgid="8202906332837777829">"Подключено, без доступа к Интернету"</string>
- <!-- no translation found for wifi_status_no_internet (5784710974669608361) -->
- <skip />
- <!-- no translation found for wifi_status_sign_in_required (123517180404752756) -->
- <skip />
+ <string name="wifi_status_no_internet" msgid="5784710974669608361">"Нет подключения к Интернету"</string>
+ <string name="wifi_status_sign_in_required" msgid="123517180404752756">"Требуется выполнить вход."</string>
<string name="wifi_ap_unable_to_handle_new_sta" msgid="5348824313514404541">"К точке доступа подключено слишком много устройств"</string>
<string name="connected_via_carrier" msgid="7583780074526041912">"Подключено к %1$s"</string>
<string name="available_via_carrier" msgid="1469036129740799053">"Доступно через %1$s"</string>
@@ -67,12 +65,9 @@
<string name="bluetooth_connected_no_headset_battery_level" msgid="1610296229139400266">"Подключено (кроме звонков), уровень заряда батареи: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g><xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g>"</string>
<string name="bluetooth_connected_no_a2dp_battery_level" msgid="3908466636369853652">"Подключено (кроме аудио), уровень заряда батареи: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g><xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g>"</string>
<string name="bluetooth_connected_no_headset_no_a2dp_battery_level" msgid="1163440823807659316">"Подключено (кроме звонков и аудио), уровень заряда батареи: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g><xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g>"</string>
- <!-- no translation found for bluetooth_active_battery_level (3149689299296462009) -->
- <skip />
- <!-- no translation found for bluetooth_battery_level (1447164613319663655) -->
- <skip />
- <!-- no translation found for bluetooth_active_no_battery_level (8380223546730241956) -->
- <skip />
+ <string name="bluetooth_active_battery_level" msgid="3149689299296462009">"Активно. Уровень заряда: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>."</string>
+ <string name="bluetooth_battery_level" msgid="1447164613319663655">"Уровень заряда: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
+ <string name="bluetooth_active_no_battery_level" msgid="8380223546730241956">"Активно"</string>
<string name="bluetooth_profile_a2dp" msgid="2031475486179830674">"Профиль A2DP"</string>
<string name="bluetooth_profile_headset" msgid="7815495680863246034">"Звонки"</string>
<string name="bluetooth_profile_opp" msgid="9168139293654233697">"Профиль OPP"</string>
@@ -119,14 +114,10 @@
<string name="bluetooth_talkback_headphone" msgid="26580326066627664">"Наушники"</string>
<string name="bluetooth_talkback_input_peripheral" msgid="5165842622743212268">"Периферийное устройство ввода"</string>
<string name="bluetooth_talkback_bluetooth" msgid="5615463912185280812">"Bluetooth"</string>
- <!-- no translation found for bluetooth_hearingaid_left_pairing_message (7378813500862148102) -->
- <skip />
- <!-- no translation found for bluetooth_hearingaid_right_pairing_message (1550373802309160891) -->
- <skip />
- <!-- no translation found for bluetooth_hearingaid_left_battery_level (8797811465352097562) -->
- <skip />
- <!-- no translation found for bluetooth_hearingaid_right_battery_level (7309476148173459677) -->
- <skip />
+ <string name="bluetooth_hearingaid_left_pairing_message" msgid="7378813500862148102">"Подключаем левый слуховой аппарат…"</string>
+ <string name="bluetooth_hearingaid_right_pairing_message" msgid="1550373802309160891">"Подключаем правый слуховой аппарат…"</string>
+ <string name="bluetooth_hearingaid_left_battery_level" msgid="8797811465352097562">"Левый слуховой аппарат: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> заряда"</string>
+ <string name="bluetooth_hearingaid_right_battery_level" msgid="7309476148173459677">"Правый слуховой аппарат: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> заряда"</string>
<string name="accessibility_wifi_off" msgid="1166761729660614716">"Wi-Fi выключен"</string>
<string name="accessibility_no_wifi" msgid="8834610636137374508">"Wi-Fi отключен"</string>
<string name="accessibility_wifi_one_bar" msgid="4869376278894301820">"Wi-Fi: одно деление"</string>
@@ -246,15 +237,12 @@
<string name="private_dns_mode_opportunistic" msgid="8314986739896927399">"Автоматический режим"</string>
<string name="private_dns_mode_provider" msgid="8354935160639360804">"Имя хоста поставщика персонального DNS-сервера"</string>
<string name="private_dns_mode_provider_hostname_hint" msgid="2487492386970928143">"Введите имя хоста поставщика услуг DNS"</string>
- <!-- no translation found for private_dns_mode_provider_failure (231837290365031223) -->
- <skip />
+ <string name="private_dns_mode_provider_failure" msgid="231837290365031223">"Ошибка подключения"</string>
<string name="wifi_display_certification_summary" msgid="1155182309166746973">"Показывать параметры сертификации беспроводных мониторов"</string>
<string name="wifi_verbose_logging_summary" msgid="6615071616111731958">"При выборе Wi‑Fi указывать в журнале RSSI для каждого SSID"</string>
<string name="wifi_connected_mac_randomization_summary" msgid="1743059848752201485">"Генерировать случайные MAC-адреса при подключении к сетям Wi-Fi"</string>
- <!-- no translation found for wifi_metered_label (4514924227256839725) -->
- <skip />
- <!-- no translation found for wifi_unmetered_label (6124098729457992931) -->
- <skip />
+ <string name="wifi_metered_label" msgid="4514924227256839725">"Сеть с тарификацией трафика"</string>
+ <string name="wifi_unmetered_label" msgid="6124098729457992931">"Сеть без тарификации трафика"</string>
<string name="select_logd_size_title" msgid="7433137108348553508">"Размер буфера журнала"</string>
<string name="select_logd_size_dialog_title" msgid="1206769310236476760">"Выберите размер буфера журнала"</string>
<string name="dev_logpersist_clear_warning_title" msgid="684806692440237967">"Очистить постоянный диск журнала?"</string>
diff --git a/packages/SettingsLib/res/values-si/strings.xml b/packages/SettingsLib/res/values-si/strings.xml
index 82bd3b3..8294383 100644
--- a/packages/SettingsLib/res/values-si/strings.xml
+++ b/packages/SettingsLib/res/values-si/strings.xml
@@ -40,10 +40,8 @@
<string name="connected_via_passpoint" msgid="2826205693803088747">"%1$s හරහා සම්බන්ධ විය"</string>
<string name="available_via_passpoint" msgid="1617440946846329613">"%1$s හරහා ලබා ගැනීමට හැකිය"</string>
<string name="wifi_connected_no_internet" msgid="8202906332837777829">"සම්බන්ධයි, අන්තර්ජාලය නැත"</string>
- <!-- no translation found for wifi_status_no_internet (5784710974669608361) -->
- <skip />
- <!-- no translation found for wifi_status_sign_in_required (123517180404752756) -->
- <skip />
+ <string name="wifi_status_no_internet" msgid="5784710974669608361">"අන්තර්ජාලය නැත"</string>
+ <string name="wifi_status_sign_in_required" msgid="123517180404752756">"පිරීම අවශ්යයි"</string>
<string name="wifi_ap_unable_to_handle_new_sta" msgid="5348824313514404541">"ප්රවේශ ලක්ෂ්ය තාවකාලිකව පිරී ඇත"</string>
<string name="connected_via_carrier" msgid="7583780074526041912">"%1$s හරහා සම්බන්ධ විය"</string>
<string name="available_via_carrier" msgid="1469036129740799053">"%1$s හරහා ලබා ගැනීමට හැකිය"</string>
@@ -67,12 +65,9 @@
<string name="bluetooth_connected_no_headset_battery_level" msgid="1610296229139400266">"සම්බන්ධිතයි (දුරකථනය නැත), බැටරිය <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g><xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g>"</string>
<string name="bluetooth_connected_no_a2dp_battery_level" msgid="3908466636369853652">"සම්බන්ධිතයි (මාධ්ය නැත), බැටරිය <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g><xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g>"</string>
<string name="bluetooth_connected_no_headset_no_a2dp_battery_level" msgid="1163440823807659316">"සම්බන්ධිතයි (දුරකථනය හෝ මාධ්ය නැත), බැටරිය <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g><xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g>"</string>
- <!-- no translation found for bluetooth_active_battery_level (3149689299296462009) -->
- <skip />
- <!-- no translation found for bluetooth_battery_level (1447164613319663655) -->
- <skip />
- <!-- no translation found for bluetooth_active_no_battery_level (8380223546730241956) -->
- <skip />
+ <string name="bluetooth_active_battery_level" msgid="3149689299296462009">"ක්රියාකාරී, බැටරිය <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
+ <string name="bluetooth_battery_level" msgid="1447164613319663655">"බැටරිය <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
+ <string name="bluetooth_active_no_battery_level" msgid="8380223546730241956">"ක්රියාකාරී"</string>
<string name="bluetooth_profile_a2dp" msgid="2031475486179830674">"මාධ්ය ශ්රව්ය"</string>
<string name="bluetooth_profile_headset" msgid="7815495680863246034">"දුරකථන ඇමතුම්"</string>
<string name="bluetooth_profile_opp" msgid="9168139293654233697">"ගොනු හුවමාරුව"</string>
@@ -119,14 +114,10 @@
<string name="bluetooth_talkback_headphone" msgid="26580326066627664">"හෙඩ්ෆෝන්"</string>
<string name="bluetooth_talkback_input_peripheral" msgid="5165842622743212268">"ආදාන උපාංග"</string>
<string name="bluetooth_talkback_bluetooth" msgid="5615463912185280812">"බ්ලූටූත්"</string>
- <!-- no translation found for bluetooth_hearingaid_left_pairing_message (7378813500862148102) -->
- <skip />
- <!-- no translation found for bluetooth_hearingaid_right_pairing_message (1550373802309160891) -->
- <skip />
- <!-- no translation found for bluetooth_hearingaid_left_battery_level (8797811465352097562) -->
- <skip />
- <!-- no translation found for bluetooth_hearingaid_right_battery_level (7309476148173459677) -->
- <skip />
+ <string name="bluetooth_hearingaid_left_pairing_message" msgid="7378813500862148102">"වම් ශ්රවණාධාරකය යුගල කරමින්..."</string>
+ <string name="bluetooth_hearingaid_right_pairing_message" msgid="1550373802309160891">"දකුණු ශ්රවණාධාරකය යුගල කරමින්…"</string>
+ <string name="bluetooth_hearingaid_left_battery_level" msgid="8797811465352097562">"වම් - බැටරිය <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
+ <string name="bluetooth_hearingaid_right_battery_level" msgid="7309476148173459677">"දකුණු - බැටරිය <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
<string name="accessibility_wifi_off" msgid="1166761729660614716">"Wifi අක්රියයි."</string>
<string name="accessibility_no_wifi" msgid="8834610636137374508">"Wifi සම්බන්ධ කර නොමැත."</string>
<string name="accessibility_wifi_one_bar" msgid="4869376278894301820">"Wifi තීරු එකයි."</string>
@@ -246,15 +237,12 @@
<string name="private_dns_mode_opportunistic" msgid="8314986739896927399">"ස්වයංක්රිය"</string>
<string name="private_dns_mode_provider" msgid="8354935160639360804">"පුද්ගලික DNS සැපයුම්කරු සත්කාරක නම"</string>
<string name="private_dns_mode_provider_hostname_hint" msgid="2487492386970928143">"DNS සැපයුම්කරුගේ සත්කාරක නම ඇතුළු කරන්න"</string>
- <!-- no translation found for private_dns_mode_provider_failure (231837290365031223) -->
- <skip />
+ <string name="private_dns_mode_provider_failure" msgid="231837290365031223">"සම්බන්ධ වීමට නොහැකි විය"</string>
<string name="wifi_display_certification_summary" msgid="1155182309166746973">"නොරැහැන් සංදර්ශක සහතිකය සඳහා විකල්ප පෙන්වන්න"</string>
<string name="wifi_verbose_logging_summary" msgid="6615071616111731958">"Wi‑Fi ලොග් මට්ටම වැඩි කරන්න, Wi‑Fi තෝරනයෙහි SSID RSSI අනුව පෙන්වන්න"</string>
<string name="wifi_connected_mac_randomization_summary" msgid="1743059848752201485">"Wi-Fi ජාලවලට සම්බන්ධ වීමේදී MAC ලිපිනය සසම්භාවීකරණය"</string>
- <!-- no translation found for wifi_metered_label (4514924227256839725) -->
- <skip />
- <!-- no translation found for wifi_unmetered_label (6124098729457992931) -->
- <skip />
+ <string name="wifi_metered_label" msgid="4514924227256839725">"මනිනු ලැබේ"</string>
+ <string name="wifi_unmetered_label" msgid="6124098729457992931">"මනින්නේ නැත"</string>
<string name="select_logd_size_title" msgid="7433137108348553508">"ලෝගයේ අන්තරාවක ප්රමාණය"</string>
<string name="select_logd_size_dialog_title" msgid="1206769310236476760">"ලොග අන්තරාවකට ලෝගයේ ප්රමාණය තෝරන්න"</string>
<string name="dev_logpersist_clear_warning_title" msgid="684806692440237967">"ලොගකරු නොනවතින ගබඩාව හිස් කරන්නද?"</string>
diff --git a/packages/SettingsLib/res/values-sv/strings.xml b/packages/SettingsLib/res/values-sv/strings.xml
index 0636816..2ee17e5 100644
--- a/packages/SettingsLib/res/values-sv/strings.xml
+++ b/packages/SettingsLib/res/values-sv/strings.xml
@@ -40,10 +40,8 @@
<string name="connected_via_passpoint" msgid="2826205693803088747">"Anslutet via %1$s"</string>
<string name="available_via_passpoint" msgid="1617440946846329613">"Tillgängligt via %1$s"</string>
<string name="wifi_connected_no_internet" msgid="8202906332837777829">"Ansluten, inget internet"</string>
- <!-- no translation found for wifi_status_no_internet (5784710974669608361) -->
- <skip />
- <!-- no translation found for wifi_status_sign_in_required (123517180404752756) -->
- <skip />
+ <string name="wifi_status_no_internet" msgid="5784710974669608361">"Inget internet"</string>
+ <string name="wifi_status_sign_in_required" msgid="123517180404752756">"Inloggning krävs"</string>
<string name="wifi_ap_unable_to_handle_new_sta" msgid="5348824313514404541">"Åtkomstpunkten har inga platser över för tillfället"</string>
<string name="connected_via_carrier" msgid="7583780074526041912">"Anslutet via %1$s"</string>
<string name="available_via_carrier" msgid="1469036129740799053">"Tillgängligt via %1$s"</string>
@@ -67,12 +65,9 @@
<string name="bluetooth_connected_no_headset_battery_level" msgid="1610296229139400266">"Ansluten (ingen mobil), batterinivå <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g><xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g>"</string>
<string name="bluetooth_connected_no_a2dp_battery_level" msgid="3908466636369853652">"Ansluten (inga medier), batterinivå <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g><xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g>"</string>
<string name="bluetooth_connected_no_headset_no_a2dp_battery_level" msgid="1163440823807659316">"Ansluten (ingen mobil och inga medier), batterinivå <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g><xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g>"</string>
- <!-- no translation found for bluetooth_active_battery_level (3149689299296462009) -->
- <skip />
- <!-- no translation found for bluetooth_battery_level (1447164613319663655) -->
- <skip />
- <!-- no translation found for bluetooth_active_no_battery_level (8380223546730241956) -->
- <skip />
+ <string name="bluetooth_active_battery_level" msgid="3149689299296462009">"Aktiv. <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> batteri"</string>
+ <string name="bluetooth_battery_level" msgid="1447164613319663655">"<xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> batteri"</string>
+ <string name="bluetooth_active_no_battery_level" msgid="8380223546730241956">"Aktiv"</string>
<string name="bluetooth_profile_a2dp" msgid="2031475486179830674">"Medialjud"</string>
<string name="bluetooth_profile_headset" msgid="7815495680863246034">"Telefonsamtal"</string>
<string name="bluetooth_profile_opp" msgid="9168139293654233697">"Filöverföring"</string>
@@ -119,14 +114,10 @@
<string name="bluetooth_talkback_headphone" msgid="26580326066627664">"Hörlur"</string>
<string name="bluetooth_talkback_input_peripheral" msgid="5165842622743212268">"Inmatning från kringutrustning"</string>
<string name="bluetooth_talkback_bluetooth" msgid="5615463912185280812">"Bluetooth"</string>
- <!-- no translation found for bluetooth_hearingaid_left_pairing_message (7378813500862148102) -->
- <skip />
- <!-- no translation found for bluetooth_hearingaid_right_pairing_message (1550373802309160891) -->
- <skip />
- <!-- no translation found for bluetooth_hearingaid_left_battery_level (8797811465352097562) -->
- <skip />
- <!-- no translation found for bluetooth_hearingaid_right_battery_level (7309476148173459677) -->
- <skip />
+ <string name="bluetooth_hearingaid_left_pairing_message" msgid="7378813500862148102">"Parkopplar vänster hörapparat …"</string>
+ <string name="bluetooth_hearingaid_right_pairing_message" msgid="1550373802309160891">"Parkopplar höger hörapparat …"</string>
+ <string name="bluetooth_hearingaid_left_battery_level" msgid="8797811465352097562">"Vänster – <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> batteri"</string>
+ <string name="bluetooth_hearingaid_right_battery_level" msgid="7309476148173459677">"Höger – <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> batteri"</string>
<string name="accessibility_wifi_off" msgid="1166761729660614716">"Wi-Fi är inaktiverat."</string>
<string name="accessibility_no_wifi" msgid="8834610636137374508">"Ingen Wi-Fi-anslutning."</string>
<string name="accessibility_wifi_one_bar" msgid="4869376278894301820">"Wi-Fi: en stapel."</string>
@@ -246,15 +237,12 @@
<string name="private_dns_mode_opportunistic" msgid="8314986739896927399">"Automatisk"</string>
<string name="private_dns_mode_provider" msgid="8354935160639360804">"Värdnamn för leverantör av privat DNS"</string>
<string name="private_dns_mode_provider_hostname_hint" msgid="2487492386970928143">"Ange värdnamn för DNS-leverantör"</string>
- <!-- no translation found for private_dns_mode_provider_failure (231837290365031223) -->
- <skip />
+ <string name="private_dns_mode_provider_failure" msgid="231837290365031223">"Kan inte ansluta"</string>
<string name="wifi_display_certification_summary" msgid="1155182309166746973">"Visa certifieringsalternativ för Wi-Fi-skärmdelning"</string>
<string name="wifi_verbose_logging_summary" msgid="6615071616111731958">"Öka loggningsnivån för Wi-Fi, visa per SSID RSSI i Wi‑Fi Picker"</string>
<string name="wifi_connected_mac_randomization_summary" msgid="1743059848752201485">"Generera en slumpmässig MAC-adress när du ansluter till Wi‑Fi-nätverk"</string>
- <!-- no translation found for wifi_metered_label (4514924227256839725) -->
- <skip />
- <!-- no translation found for wifi_unmetered_label (6124098729457992931) -->
- <skip />
+ <string name="wifi_metered_label" msgid="4514924227256839725">"Med datapriser"</string>
+ <string name="wifi_unmetered_label" msgid="6124098729457992931">"Utan datapriser"</string>
<string name="select_logd_size_title" msgid="7433137108348553508">"Buffertstorlekar för logg"</string>
<string name="select_logd_size_dialog_title" msgid="1206769310236476760">"Välj loggstorlekar per loggbuffert"</string>
<string name="dev_logpersist_clear_warning_title" msgid="684806692440237967">"Vill du rensa lagringsutrymmet för loggar?"</string>
diff --git a/packages/SettingsLib/res/values-ta/strings.xml b/packages/SettingsLib/res/values-ta/strings.xml
index f3fe2e9..88800e9 100644
--- a/packages/SettingsLib/res/values-ta/strings.xml
+++ b/packages/SettingsLib/res/values-ta/strings.xml
@@ -206,8 +206,7 @@
<string name="keep_screen_on" msgid="1146389631208760344">"செயலில் வைத்திரு"</string>
<string name="keep_screen_on_summary" msgid="2173114350754293009">"சார்ஜ் ஏறும்போது திரை எப்போதும் உறக்கநிலைக்குச் செல்லாது"</string>
<string name="bt_hci_snoop_log" msgid="3340699311158865670">"புளூடூத் HCI ஸ்னுப் பதிவை இயக்கு"</string>
- <!-- no translation found for bt_hci_snoop_log_summary (366083475849911315) -->
- <skip />
+ <string name="bt_hci_snoop_log_summary" msgid="366083475849911315">"கோப்பில் உள்ள புளூடூத் HCI பாக்கெட்டுகள் அனைத்தையும் படமெடுக்கும் (இந்த அமைப்பை மாற்றிய பிறகு, புளூடூத் நிலைமாற்றப்படும்)"</string>
<string name="oem_unlock_enable" msgid="6040763321967327691">"OEM திறத்தல்"</string>
<string name="oem_unlock_enable_summary" msgid="4720281828891618376">"பூட்லோடரைத் திறக்க அனுமதி"</string>
<string name="confirm_enable_oem_unlock_title" msgid="4802157344812385674">"OEM திறத்தலை அனுமதிக்கவா?"</string>
diff --git a/packages/SettingsLib/res/values-te/strings.xml b/packages/SettingsLib/res/values-te/strings.xml
index 5558e8d..090e3c5 100644
--- a/packages/SettingsLib/res/values-te/strings.xml
+++ b/packages/SettingsLib/res/values-te/strings.xml
@@ -40,10 +40,8 @@
<string name="connected_via_passpoint" msgid="2826205693803088747">"%1$s ద్వారా కనెక్ట్ చేయబడింది"</string>
<string name="available_via_passpoint" msgid="1617440946846329613">"%1$s ద్వారా అందుబాటులో ఉంది"</string>
<string name="wifi_connected_no_internet" msgid="8202906332837777829">"కనెక్ట్ చేయబడింది, ఇంటర్నెట్ లేదు"</string>
- <!-- no translation found for wifi_status_no_internet (5784710974669608361) -->
- <skip />
- <!-- no translation found for wifi_status_sign_in_required (123517180404752756) -->
- <skip />
+ <string name="wifi_status_no_internet" msgid="5784710974669608361">"ఇంటర్నెట్ లేదు"</string>
+ <string name="wifi_status_sign_in_required" msgid="123517180404752756">"సైన్ ఇన్ చేయాలి"</string>
<string name="wifi_ap_unable_to_handle_new_sta" msgid="5348824313514404541">"యాక్సెస్ పాయింట్ తాత్కాలికంగా నిండుకుంది"</string>
<string name="connected_via_carrier" msgid="7583780074526041912">"%1$s ద్వారా కనెక్ట్ చేయబడింది"</string>
<string name="available_via_carrier" msgid="1469036129740799053">"%1$s ద్వారా అందుబాటులో ఉంది"</string>
@@ -67,12 +65,9 @@
<string name="bluetooth_connected_no_headset_battery_level" msgid="1610296229139400266">"కనెక్ట్ చేయబడింది (ఫోన్ కాదు), బ్యాటరీ <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g><xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g>"</string>
<string name="bluetooth_connected_no_a2dp_battery_level" msgid="3908466636369853652">"కనెక్ట్ చేయబడింది (మీడియా కాదు), బ్యాటరీ <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g><xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g>"</string>
<string name="bluetooth_connected_no_headset_no_a2dp_battery_level" msgid="1163440823807659316">"కనెక్ట్ చేయబడింది (ఫోన్ లేదా మీడియా కాదు), బ్యాటరీ <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g><xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g>"</string>
- <!-- no translation found for bluetooth_active_battery_level (3149689299296462009) -->
- <skip />
- <!-- no translation found for bluetooth_battery_level (1447164613319663655) -->
- <skip />
- <!-- no translation found for bluetooth_active_no_battery_level (8380223546730241956) -->
- <skip />
+ <string name="bluetooth_active_battery_level" msgid="3149689299296462009">"యాక్టివ్గా ఉంది, <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> బ్యాటరీ"</string>
+ <string name="bluetooth_battery_level" msgid="1447164613319663655">"<xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> బ్యాటరీ"</string>
+ <string name="bluetooth_active_no_battery_level" msgid="8380223546730241956">"యాక్టివ్గా ఉంది"</string>
<string name="bluetooth_profile_a2dp" msgid="2031475486179830674">"మీడియా ఆడియో"</string>
<string name="bluetooth_profile_headset" msgid="7815495680863246034">"ఫోన్ కాల్లు"</string>
<string name="bluetooth_profile_opp" msgid="9168139293654233697">"ఫైల్ బదిలీ"</string>
@@ -119,14 +114,10 @@
<string name="bluetooth_talkback_headphone" msgid="26580326066627664">"హెడ్ఫోన్"</string>
<string name="bluetooth_talkback_input_peripheral" msgid="5165842622743212268">"ఇన్పుట్ అనుబంధ పరికరం"</string>
<string name="bluetooth_talkback_bluetooth" msgid="5615463912185280812">"బ్లూటూత్"</string>
- <!-- no translation found for bluetooth_hearingaid_left_pairing_message (7378813500862148102) -->
- <skip />
- <!-- no translation found for bluetooth_hearingaid_right_pairing_message (1550373802309160891) -->
- <skip />
- <!-- no translation found for bluetooth_hearingaid_left_battery_level (8797811465352097562) -->
- <skip />
- <!-- no translation found for bluetooth_hearingaid_right_battery_level (7309476148173459677) -->
- <skip />
+ <string name="bluetooth_hearingaid_left_pairing_message" msgid="7378813500862148102">"ఎడమ వైపు వినికిడి పరికరాన్ని జత చేస్తోంది…"</string>
+ <string name="bluetooth_hearingaid_right_pairing_message" msgid="1550373802309160891">"కుడి వైపు వినికిడి పరికరాన్ని జత చేస్తోంది…"</string>
+ <string name="bluetooth_hearingaid_left_battery_level" msgid="8797811465352097562">"ఎడమ వైపు - <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> బ్యాటరీ"</string>
+ <string name="bluetooth_hearingaid_right_battery_level" msgid="7309476148173459677">"కుడి వైపు - <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> బ్యాటరీ"</string>
<string name="accessibility_wifi_off" msgid="1166761729660614716">"Wifi ఆఫ్లో ఉంది."</string>
<string name="accessibility_no_wifi" msgid="8834610636137374508">"Wifi డిస్కనెక్ట్ చేయబడింది."</string>
<string name="accessibility_wifi_one_bar" msgid="4869376278894301820">"Wifi సిగ్నల్ ఒక బార్ ఉంది."</string>
@@ -206,8 +197,7 @@
<string name="keep_screen_on" msgid="1146389631208760344">"సక్రియంగా ఉంచు"</string>
<string name="keep_screen_on_summary" msgid="2173114350754293009">"ఛార్జ్ చేస్తున్నప్పుడు స్క్రీన్ ఎప్పటికీ నిద్రావస్థలోకి వెళ్లదు"</string>
<string name="bt_hci_snoop_log" msgid="3340699311158865670">"బ్లూటూత్ HCI రహస్య లాగ్ను ప్రారంభించు"</string>
- <!-- no translation found for bt_hci_snoop_log_summary (366083475849911315) -->
- <skip />
+ <string name="bt_hci_snoop_log_summary" msgid="366083475849911315">"ఫైల్లో అన్ని బ్లూటూత్ HCI ప్యాకెట్లను క్యాప్చర్ చేస్తుంది (ఈ సెట్టింగ్ని మార్చిన తర్వాత బ్లూటూత్ని టోగుల్ చేయండి)"</string>
<string name="oem_unlock_enable" msgid="6040763321967327691">"OEM అన్లాకింగ్"</string>
<string name="oem_unlock_enable_summary" msgid="4720281828891618376">"బూట్లోడర్ అన్లాక్ కావడానికి అనుమతించు"</string>
<string name="confirm_enable_oem_unlock_title" msgid="4802157344812385674">"OEM అన్లాకింగ్ను అనుమతించాలా?"</string>
@@ -247,15 +237,12 @@
<string name="private_dns_mode_opportunistic" msgid="8314986739896927399">"ఆటోమేటిక్"</string>
<string name="private_dns_mode_provider" msgid="8354935160639360804">"ప్రైవేట్ DNS ప్రదాత హోస్ట్పేరు"</string>
<string name="private_dns_mode_provider_hostname_hint" msgid="2487492386970928143">"DNS ప్రదాత యొక్క హోస్ట్పేరును నమోదు చేయండి"</string>
- <!-- no translation found for private_dns_mode_provider_failure (231837290365031223) -->
- <skip />
+ <string name="private_dns_mode_provider_failure" msgid="231837290365031223">"కనెక్ట్ చేయడం సాధ్యపడలేదు"</string>
<string name="wifi_display_certification_summary" msgid="1155182309166746973">"వైర్లెస్ ప్రదర్శన సర్టిఫికెట్ కోసం ఎంపికలను చూపు"</string>
<string name="wifi_verbose_logging_summary" msgid="6615071616111731958">"Wi‑Fi ఎంపికలో SSID RSSI ప్రకారం చూపబడే Wi‑Fi లాగింగ్ స్థాయిని పెంచండి"</string>
<string name="wifi_connected_mac_randomization_summary" msgid="1743059848752201485">"Wi-Fi నెట్వర్క్కు కనెక్ట్ చేస్తున్నప్పుడు MAC చిరునామాను యాదృచ్ఛికం చేయండి"</string>
- <!-- no translation found for wifi_metered_label (4514924227256839725) -->
- <skip />
- <!-- no translation found for wifi_unmetered_label (6124098729457992931) -->
- <skip />
+ <string name="wifi_metered_label" msgid="4514924227256839725">"గణించబడుతోంది"</string>
+ <string name="wifi_unmetered_label" msgid="6124098729457992931">"గణించబడటం లేదు"</string>
<string name="select_logd_size_title" msgid="7433137108348553508">"లాగర్ బఫర్ పరిమాణాలు"</string>
<string name="select_logd_size_dialog_title" msgid="1206769310236476760">"లాగ్ బఫర్కి లాగర్ పరిమా. ఎంచుకోండి"</string>
<string name="dev_logpersist_clear_warning_title" msgid="684806692440237967">"లాగర్ నిరంతర నిల్వలోని డేటాను తీసివేయాలా?"</string>
diff --git a/packages/SettingsLib/res/values-ur/strings.xml b/packages/SettingsLib/res/values-ur/strings.xml
index fac268b..fd2f1ea 100644
--- a/packages/SettingsLib/res/values-ur/strings.xml
+++ b/packages/SettingsLib/res/values-ur/strings.xml
@@ -206,8 +206,7 @@
<string name="keep_screen_on" msgid="1146389631208760344">"بیدار رکھیں"</string>
<string name="keep_screen_on_summary" msgid="2173114350754293009">"چارج ہوتے وقت اسکرین کبھی بھی سلیپ وضع میں نہيں جائے گی"</string>
<string name="bt_hci_snoop_log" msgid="3340699311158865670">"بلوٹوتھ HCI کا جاسوسی لاگ فعال کریں"</string>
- <!-- no translation found for bt_hci_snoop_log_summary (366083475849911315) -->
- <skip />
+ <string name="bt_hci_snoop_log_summary" msgid="366083475849911315">"سبھی بلوٹوتھ HCI کے پیکٹس ایک فائل میں کیپچر کریں (اس ترتیب کو تبدیل کرنے کے بعد بلوٹوتھ ٹوگل کریں)"</string>
<string name="oem_unlock_enable" msgid="6040763321967327691">"OEM اَن لاکنگ"</string>
<string name="oem_unlock_enable_summary" msgid="4720281828891618376">"بوٹ لوڈر کو غیر مقفل ہونے کی اجازت دیں"</string>
<string name="confirm_enable_oem_unlock_title" msgid="4802157344812385674">"OEM اَن لاکنگ کی اجازت دیں؟"</string>
diff --git a/packages/SettingsLib/res/values-uz/strings.xml b/packages/SettingsLib/res/values-uz/strings.xml
index 648cda7..23ad2ca 100644
--- a/packages/SettingsLib/res/values-uz/strings.xml
+++ b/packages/SettingsLib/res/values-uz/strings.xml
@@ -40,10 +40,8 @@
<string name="connected_via_passpoint" msgid="2826205693803088747">"%1$s orqali ulangan"</string>
<string name="available_via_passpoint" msgid="1617440946846329613">"%1$s orqali ishlaydi"</string>
<string name="wifi_connected_no_internet" msgid="8202906332837777829">"Ulangan, lekin internet aloqasi yo‘q"</string>
- <!-- no translation found for wifi_status_no_internet (5784710974669608361) -->
- <skip />
- <!-- no translation found for wifi_status_sign_in_required (123517180404752756) -->
- <skip />
+ <string name="wifi_status_no_internet" msgid="5784710974669608361">"Internet yo‘q"</string>
+ <string name="wifi_status_sign_in_required" msgid="123517180404752756">"Hisob bilan kirish zarur"</string>
<string name="wifi_ap_unable_to_handle_new_sta" msgid="5348824313514404541">"Internet kirish nuqtasi vaqtinchalik to‘lgan"</string>
<string name="connected_via_carrier" msgid="7583780074526041912">"%1$s orqali ulangan"</string>
<string name="available_via_carrier" msgid="1469036129740799053">"%1$s orqali ishlaydi"</string>
@@ -67,12 +65,9 @@
<string name="bluetooth_connected_no_headset_battery_level" msgid="1610296229139400266">"<xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g> ulandi (telefondan tashqari), batareya quvvati: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
<string name="bluetooth_connected_no_a2dp_battery_level" msgid="3908466636369853652">"<xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g> ulandi (mediadan tashqari), batareya quvvati: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
<string name="bluetooth_connected_no_headset_no_a2dp_battery_level" msgid="1163440823807659316">"<xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g> ulandi (telefon yoki mediadan tashqari), batareya quvvati: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
- <!-- no translation found for bluetooth_active_battery_level (3149689299296462009) -->
- <skip />
- <!-- no translation found for bluetooth_battery_level (1447164613319663655) -->
- <skip />
- <!-- no translation found for bluetooth_active_no_battery_level (8380223546730241956) -->
- <skip />
+ <string name="bluetooth_active_battery_level" msgid="3149689299296462009">"Faol, batariya quvvati: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
+ <string name="bluetooth_battery_level" msgid="1447164613319663655">"Batareya quvvati: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
+ <string name="bluetooth_active_no_battery_level" msgid="8380223546730241956">"Faol"</string>
<string name="bluetooth_profile_a2dp" msgid="2031475486179830674">"Media audio"</string>
<string name="bluetooth_profile_headset" msgid="7815495680863246034">"Telefon chaqiruvlari"</string>
<string name="bluetooth_profile_opp" msgid="9168139293654233697">"Fayl uzatish"</string>
@@ -119,14 +114,10 @@
<string name="bluetooth_talkback_headphone" msgid="26580326066627664">"Quloqchin"</string>
<string name="bluetooth_talkback_input_peripheral" msgid="5165842622743212268">"Kiritish qurilmasi"</string>
<string name="bluetooth_talkback_bluetooth" msgid="5615463912185280812">"Bluetooth"</string>
- <!-- no translation found for bluetooth_hearingaid_left_pairing_message (7378813500862148102) -->
- <skip />
- <!-- no translation found for bluetooth_hearingaid_right_pairing_message (1550373802309160891) -->
- <skip />
- <!-- no translation found for bluetooth_hearingaid_left_battery_level (8797811465352097562) -->
- <skip />
- <!-- no translation found for bluetooth_hearingaid_right_battery_level (7309476148173459677) -->
- <skip />
+ <string name="bluetooth_hearingaid_left_pairing_message" msgid="7378813500862148102">"Chap eshitish apparati ulanmoqda…"</string>
+ <string name="bluetooth_hearingaid_right_pairing_message" msgid="1550373802309160891">"O‘ng eshitish apparati ulanmoqda…"</string>
+ <string name="bluetooth_hearingaid_left_battery_level" msgid="8797811465352097562">"Chap eshitish apparati – batariya quvvati: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
+ <string name="bluetooth_hearingaid_right_battery_level" msgid="7309476148173459677">"O‘ng eshitish apparati – batariya quvvati: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
<string name="accessibility_wifi_off" msgid="1166761729660614716">"Wi-Fi o‘chiq."</string>
<string name="accessibility_no_wifi" msgid="8834610636137374508">"Wi-Fi o‘chiq."</string>
<string name="accessibility_wifi_one_bar" msgid="4869376278894301820">"Wi-Fi: bitta ustun"</string>
@@ -246,15 +237,12 @@
<string name="private_dns_mode_opportunistic" msgid="8314986739896927399">"Avtomatik"</string>
<string name="private_dns_mode_provider" msgid="8354935160639360804">"Shaxsiy DNS provayderining host nomi"</string>
<string name="private_dns_mode_provider_hostname_hint" msgid="2487492386970928143">"DNS provayderining host nomini kiriting"</string>
- <!-- no translation found for private_dns_mode_provider_failure (231837290365031223) -->
- <skip />
+ <string name="private_dns_mode_provider_failure" msgid="231837290365031223">"Ulanmadi"</string>
<string name="wifi_display_certification_summary" msgid="1155182309166746973">"Simsiz monitorlarni sertifikatlash parametrini ko‘rsatish"</string>
<string name="wifi_verbose_logging_summary" msgid="6615071616111731958">"Wi-Fi ulanishini tanlashda har bir SSID uchun jurnalda ko‘rsatilsin"</string>
<string name="wifi_connected_mac_randomization_summary" msgid="1743059848752201485">"Wi-Fi tarmoqlarga ulanishda MAC manzilini tasodifiy tanlash"</string>
- <!-- no translation found for wifi_metered_label (4514924227256839725) -->
- <skip />
- <!-- no translation found for wifi_unmetered_label (6124098729457992931) -->
- <skip />
+ <string name="wifi_metered_label" msgid="4514924227256839725">"Trafik hisobi yuritiladigan tarmoq"</string>
+ <string name="wifi_unmetered_label" msgid="6124098729457992931">"Trafik hisobi yuritilmaydigan tarmoq"</string>
<string name="select_logd_size_title" msgid="7433137108348553508">"Jurnal buferi hajmi"</string>
<string name="select_logd_size_dialog_title" msgid="1206769310236476760">"Jurnal xotirasi hajmini tanlang"</string>
<string name="dev_logpersist_clear_warning_title" msgid="684806692440237967">"Jurnalning doimiy xotirasi tozalansinmi?"</string>
diff --git a/packages/SettingsLib/res/values-vi/strings.xml b/packages/SettingsLib/res/values-vi/strings.xml
index 0599aea..b03e3a1 100644
--- a/packages/SettingsLib/res/values-vi/strings.xml
+++ b/packages/SettingsLib/res/values-vi/strings.xml
@@ -40,10 +40,8 @@
<string name="connected_via_passpoint" msgid="2826205693803088747">"Được kết nối qua %1$s"</string>
<string name="available_via_passpoint" msgid="1617440946846329613">"Có sẵn qua %1$s"</string>
<string name="wifi_connected_no_internet" msgid="8202906332837777829">"Đã kết nối, không có Internet"</string>
- <!-- no translation found for wifi_status_no_internet (5784710974669608361) -->
- <skip />
- <!-- no translation found for wifi_status_sign_in_required (123517180404752756) -->
- <skip />
+ <string name="wifi_status_no_internet" msgid="5784710974669608361">"Không có Internet"</string>
+ <string name="wifi_status_sign_in_required" msgid="123517180404752756">"Yêu cầu đăng nhập"</string>
<string name="wifi_ap_unable_to_handle_new_sta" msgid="5348824313514404541">"Điểm truy cập tạm thời đã đạt đến giới hạn số lượng thiết bị truy cập."</string>
<string name="connected_via_carrier" msgid="7583780074526041912">"Được kết nối qua %1$s"</string>
<string name="available_via_carrier" msgid="1469036129740799053">"Có sẵn qua %1$s"</string>
@@ -67,12 +65,9 @@
<string name="bluetooth_connected_no_headset_battery_level" msgid="1610296229139400266">"Đã kết nối (không có điện thoại), mức pin <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g><xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g>"</string>
<string name="bluetooth_connected_no_a2dp_battery_level" msgid="3908466636369853652">"Đã kết nối (không có phương tiện), mức pin <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g><xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g>"</string>
<string name="bluetooth_connected_no_headset_no_a2dp_battery_level" msgid="1163440823807659316">"Đã kết nối (không có điện thoại hoặc phương tiện), mức pin <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g><xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g>"</string>
- <!-- no translation found for bluetooth_active_battery_level (3149689299296462009) -->
- <skip />
- <!-- no translation found for bluetooth_battery_level (1447164613319663655) -->
- <skip />
- <!-- no translation found for bluetooth_active_no_battery_level (8380223546730241956) -->
- <skip />
+ <string name="bluetooth_active_battery_level" msgid="3149689299296462009">"Đang hoạt động, mức pin <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
+ <string name="bluetooth_battery_level" msgid="1447164613319663655">"Mức pin <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
+ <string name="bluetooth_active_no_battery_level" msgid="8380223546730241956">"Đang hoạt động"</string>
<string name="bluetooth_profile_a2dp" msgid="2031475486179830674">"Âm thanh của phương tiện"</string>
<string name="bluetooth_profile_headset" msgid="7815495680863246034">"Cuộc gọi điện thoại"</string>
<string name="bluetooth_profile_opp" msgid="9168139293654233697">"Chuyển tệp"</string>
@@ -119,14 +114,10 @@
<string name="bluetooth_talkback_headphone" msgid="26580326066627664">"Tai nghe"</string>
<string name="bluetooth_talkback_input_peripheral" msgid="5165842622743212268">"Thiết bị ngoại vi vào"</string>
<string name="bluetooth_talkback_bluetooth" msgid="5615463912185280812">"Bluetooth"</string>
- <!-- no translation found for bluetooth_hearingaid_left_pairing_message (7378813500862148102) -->
- <skip />
- <!-- no translation found for bluetooth_hearingaid_right_pairing_message (1550373802309160891) -->
- <skip />
- <!-- no translation found for bluetooth_hearingaid_left_battery_level (8797811465352097562) -->
- <skip />
- <!-- no translation found for bluetooth_hearingaid_right_battery_level (7309476148173459677) -->
- <skip />
+ <string name="bluetooth_hearingaid_left_pairing_message" msgid="7378813500862148102">"Đang ghép nối thiết bị trợ thính bên trái…"</string>
+ <string name="bluetooth_hearingaid_right_pairing_message" msgid="1550373802309160891">"Đang ghép nối thiết bị trợ thính bên phải…"</string>
+ <string name="bluetooth_hearingaid_left_battery_level" msgid="8797811465352097562">"Bên trái - Mức pin <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
+ <string name="bluetooth_hearingaid_right_battery_level" msgid="7309476148173459677">"Bên phải - Mức pin <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
<string name="accessibility_wifi_off" msgid="1166761729660614716">"Đã tắt Wi-Fi."</string>
<string name="accessibility_no_wifi" msgid="8834610636137374508">"Đã ngắt kết nối Wi-Fi."</string>
<string name="accessibility_wifi_one_bar" msgid="4869376278894301820">"Tín hiệu Wi-Fi một vạch."</string>
@@ -246,15 +237,12 @@
<string name="private_dns_mode_opportunistic" msgid="8314986739896927399">"Tự động"</string>
<string name="private_dns_mode_provider" msgid="8354935160639360804">"Tên máy chủ của nhà cung cấp DNS riêng tư"</string>
<string name="private_dns_mode_provider_hostname_hint" msgid="2487492386970928143">"Nhập tên máy chủ của nhà cung cấp DNS"</string>
- <!-- no translation found for private_dns_mode_provider_failure (231837290365031223) -->
- <skip />
+ <string name="private_dns_mode_provider_failure" msgid="231837290365031223">"Không thể kết nối"</string>
<string name="wifi_display_certification_summary" msgid="1155182309166746973">"Hiển thị tùy chọn chứng nhận hiển thị không dây"</string>
<string name="wifi_verbose_logging_summary" msgid="6615071616111731958">"Tăng mức ghi nhật ký Wi‑Fi, hiển thị mỗi SSID RSSI trong bộ chọn Wi‑Fi"</string>
<string name="wifi_connected_mac_randomization_summary" msgid="1743059848752201485">"Lựa chọn ngẫu nhiên địa chỉ MAC khi kết nối với mạng Wi‑Fi"</string>
- <!-- no translation found for wifi_metered_label (4514924227256839725) -->
- <skip />
- <!-- no translation found for wifi_unmetered_label (6124098729457992931) -->
- <skip />
+ <string name="wifi_metered_label" msgid="4514924227256839725">"Đo lượng dữ liệu"</string>
+ <string name="wifi_unmetered_label" msgid="6124098729457992931">"Không đo lượng dữ liệu"</string>
<string name="select_logd_size_title" msgid="7433137108348553508">"Kích cỡ tải trình ghi"</string>
<string name="select_logd_size_dialog_title" msgid="1206769310236476760">"Chọn kích thước Trình ghi/lần tải nhật ký"</string>
<string name="dev_logpersist_clear_warning_title" msgid="684806692440237967">"Xóa bộ nhớ ổn định trong trình ghi nhật ký?"</string>
diff --git a/packages/SettingsLib/res/values-zh-rCN/strings.xml b/packages/SettingsLib/res/values-zh-rCN/strings.xml
index 22ba3c3..db77946 100644
--- a/packages/SettingsLib/res/values-zh-rCN/strings.xml
+++ b/packages/SettingsLib/res/values-zh-rCN/strings.xml
@@ -40,10 +40,8 @@
<string name="connected_via_passpoint" msgid="2826205693803088747">"已通过%1$s连接"</string>
<string name="available_via_passpoint" msgid="1617440946846329613">"可通过%1$s连接"</string>
<string name="wifi_connected_no_internet" msgid="8202906332837777829">"已连接,但无法访问互联网"</string>
- <!-- no translation found for wifi_status_no_internet (5784710974669608361) -->
- <skip />
- <!-- no translation found for wifi_status_sign_in_required (123517180404752756) -->
- <skip />
+ <string name="wifi_status_no_internet" msgid="5784710974669608361">"无法访问互联网"</string>
+ <string name="wifi_status_sign_in_required" msgid="123517180404752756">"必须登录"</string>
<string name="wifi_ap_unable_to_handle_new_sta" msgid="5348824313514404541">"接入点暂时满载"</string>
<string name="connected_via_carrier" msgid="7583780074526041912">"已通过%1$s连接"</string>
<string name="available_via_carrier" msgid="1469036129740799053">"可通过%1$s连接"</string>
@@ -67,12 +65,9 @@
<string name="bluetooth_connected_no_headset_battery_level" msgid="1610296229139400266">"已连接(无手机信号),电量为 <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> <xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g>"</string>
<string name="bluetooth_connected_no_a2dp_battery_level" msgid="3908466636369853652">"已连接(无媒体信号),电量为 <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> <xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g>"</string>
<string name="bluetooth_connected_no_headset_no_a2dp_battery_level" msgid="1163440823807659316">"已连接(无手机或媒体信号),电量为 <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> <xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g>"</string>
- <!-- no translation found for bluetooth_active_battery_level (3149689299296462009) -->
- <skip />
- <!-- no translation found for bluetooth_battery_level (1447164613319663655) -->
- <skip />
- <!-- no translation found for bluetooth_active_no_battery_level (8380223546730241956) -->
- <skip />
+ <string name="bluetooth_active_battery_level" msgid="3149689299296462009">"使用中,电池电量:<xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
+ <string name="bluetooth_battery_level" msgid="1447164613319663655">"电池电量:<xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
+ <string name="bluetooth_active_no_battery_level" msgid="8380223546730241956">"使用中"</string>
<string name="bluetooth_profile_a2dp" msgid="2031475486179830674">"媒体音频"</string>
<string name="bluetooth_profile_headset" msgid="7815495680863246034">"通话"</string>
<string name="bluetooth_profile_opp" msgid="9168139293654233697">"文件传输"</string>
@@ -119,14 +114,10 @@
<string name="bluetooth_talkback_headphone" msgid="26580326066627664">"耳机"</string>
<string name="bluetooth_talkback_input_peripheral" msgid="5165842622743212268">"外围输入设备"</string>
<string name="bluetooth_talkback_bluetooth" msgid="5615463912185280812">"蓝牙"</string>
- <!-- no translation found for bluetooth_hearingaid_left_pairing_message (7378813500862148102) -->
- <skip />
- <!-- no translation found for bluetooth_hearingaid_right_pairing_message (1550373802309160891) -->
- <skip />
- <!-- no translation found for bluetooth_hearingaid_left_battery_level (8797811465352097562) -->
- <skip />
- <!-- no translation found for bluetooth_hearingaid_right_battery_level (7309476148173459677) -->
- <skip />
+ <string name="bluetooth_hearingaid_left_pairing_message" msgid="7378813500862148102">"正在配对左侧助听器…"</string>
+ <string name="bluetooth_hearingaid_right_pairing_message" msgid="1550373802309160891">"正在配对右侧助听器…"</string>
+ <string name="bluetooth_hearingaid_left_battery_level" msgid="8797811465352097562">"左侧 - 电池电量:<xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
+ <string name="bluetooth_hearingaid_right_battery_level" msgid="7309476148173459677">"右侧 - 电池电量:<xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
<string name="accessibility_wifi_off" msgid="1166761729660614716">"WLAN 已关闭。"</string>
<string name="accessibility_no_wifi" msgid="8834610636137374508">"WLAN 连接已断开。"</string>
<string name="accessibility_wifi_one_bar" msgid="4869376278894301820">"WLAN 信号强度为一格。"</string>
@@ -206,8 +197,7 @@
<string name="keep_screen_on" msgid="1146389631208760344">"不锁定屏幕"</string>
<string name="keep_screen_on_summary" msgid="2173114350754293009">"充电时屏幕不会休眠"</string>
<string name="bt_hci_snoop_log" msgid="3340699311158865670">"启用蓝牙 HCI 信息收集日志"</string>
- <!-- no translation found for bt_hci_snoop_log_summary (366083475849911315) -->
- <skip />
+ <string name="bt_hci_snoop_log_summary" msgid="366083475849911315">"捕获单个文件中的所有蓝牙 HCI 包(更改此设置之后切换蓝牙开关)"</string>
<string name="oem_unlock_enable" msgid="6040763321967327691">"OEM 解锁"</string>
<string name="oem_unlock_enable_summary" msgid="4720281828891618376">"允许解锁引导加载程序"</string>
<string name="confirm_enable_oem_unlock_title" msgid="4802157344812385674">"要允许 OEM 解锁吗?"</string>
@@ -247,15 +237,12 @@
<string name="private_dns_mode_opportunistic" msgid="8314986739896927399">"自动"</string>
<string name="private_dns_mode_provider" msgid="8354935160639360804">"私人 DNS 提供商主机名"</string>
<string name="private_dns_mode_provider_hostname_hint" msgid="2487492386970928143">"输入 DNS 提供商的主机名"</string>
- <!-- no translation found for private_dns_mode_provider_failure (231837290365031223) -->
- <skip />
+ <string name="private_dns_mode_provider_failure" msgid="231837290365031223">"无法连接"</string>
<string name="wifi_display_certification_summary" msgid="1155182309166746973">"显示无线显示认证选项"</string>
<string name="wifi_verbose_logging_summary" msgid="6615071616111731958">"提升WLAN日志记录级别(在WLAN选择器中显示每个SSID的RSSI)"</string>
<string name="wifi_connected_mac_randomization_summary" msgid="1743059848752201485">"连接到 WLAN 网络时随机选择 MAC 地址"</string>
- <!-- no translation found for wifi_metered_label (4514924227256839725) -->
- <skip />
- <!-- no translation found for wifi_unmetered_label (6124098729457992931) -->
- <skip />
+ <string name="wifi_metered_label" msgid="4514924227256839725">"按流量计费"</string>
+ <string name="wifi_unmetered_label" msgid="6124098729457992931">"不按流量计费"</string>
<string name="select_logd_size_title" msgid="7433137108348553508">"日志记录器缓冲区大小"</string>
<string name="select_logd_size_dialog_title" msgid="1206769310236476760">"选择每个日志缓冲区的日志记录器大小"</string>
<string name="dev_logpersist_clear_warning_title" msgid="684806692440237967">"要清除永久存储的日志记录器数据吗?"</string>
diff --git a/packages/SettingsLib/res/values-zh-rHK/strings.xml b/packages/SettingsLib/res/values-zh-rHK/strings.xml
index 887959d..0aa8383 100644
--- a/packages/SettingsLib/res/values-zh-rHK/strings.xml
+++ b/packages/SettingsLib/res/values-zh-rHK/strings.xml
@@ -40,7 +40,7 @@
<string name="connected_via_passpoint" msgid="2826205693803088747">"已透過 %1$s 連線"</string>
<string name="available_via_passpoint" msgid="1617440946846329613">"可透過 %1$s 連線"</string>
<string name="wifi_connected_no_internet" msgid="8202906332837777829">"已連線,但沒有互聯網"</string>
- <string name="wifi_status_no_internet" msgid="5784710974669608361">"沒有網際網路連線"</string>
+ <string name="wifi_status_no_internet" msgid="5784710974669608361">"沒有互聯網連線"</string>
<string name="wifi_status_sign_in_required" msgid="123517180404752756">"必須登入"</string>
<string name="wifi_ap_unable_to_handle_new_sta" msgid="5348824313514404541">"存取點暫時已滿"</string>
<string name="connected_via_carrier" msgid="7583780074526041912">"已透過 %1$s 連線"</string>
@@ -114,10 +114,10 @@
<string name="bluetooth_talkback_headphone" msgid="26580326066627664">"耳機"</string>
<string name="bluetooth_talkback_input_peripheral" msgid="5165842622743212268">"輸入周邊設備"</string>
<string name="bluetooth_talkback_bluetooth" msgid="5615463912185280812">"藍牙"</string>
- <string name="bluetooth_hearingaid_left_pairing_message" msgid="7378813500862148102">"正在配對左側助聽器…"</string>
- <string name="bluetooth_hearingaid_right_pairing_message" msgid="1550373802309160891">"正在配對右側助聽器…"</string>
- <string name="bluetooth_hearingaid_left_battery_level" msgid="8797811465352097562">"左側 - 電量:<xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
- <string name="bluetooth_hearingaid_right_battery_level" msgid="7309476148173459677">"右側 - 電量:<xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
+ <string name="bluetooth_hearingaid_left_pairing_message" msgid="7378813500862148102">"正在配對左邊的助聽器…"</string>
+ <string name="bluetooth_hearingaid_right_pairing_message" msgid="1550373802309160891">"正在配對右邊的助聽器…"</string>
+ <string name="bluetooth_hearingaid_left_battery_level" msgid="8797811465352097562">"左邊 - 電量:<xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
+ <string name="bluetooth_hearingaid_right_battery_level" msgid="7309476148173459677">"右邊 - 電量:<xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
<string name="accessibility_wifi_off" msgid="1166761729660614716">"Wi-Fi 已關閉。"</string>
<string name="accessibility_no_wifi" msgid="8834610636137374508">"Wi-Fi 連線已中斷。"</string>
<string name="accessibility_wifi_one_bar" msgid="4869376278894301820">"Wi-Fi 訊號一格。"</string>
@@ -241,8 +241,8 @@
<string name="wifi_display_certification_summary" msgid="1155182309166746973">"顯示無線螢幕分享認證的選項"</string>
<string name="wifi_verbose_logging_summary" msgid="6615071616111731958">"讓 Wi‑Fi 記錄功能升級,在 Wi‑Fi 選擇器中依每個 SSID RSSI 顯示 Wi‑Fi 詳細紀錄"</string>
<string name="wifi_connected_mac_randomization_summary" msgid="1743059848752201485">"連線至 Wi‑Fi 網絡時隨機產生 MAC 位址"</string>
- <string name="wifi_metered_label" msgid="4514924227256839725">"計量付費"</string>
- <string name="wifi_unmetered_label" msgid="6124098729457992931">"非計量付費"</string>
+ <string name="wifi_metered_label" msgid="4514924227256839725">"按用量收費"</string>
+ <string name="wifi_unmetered_label" msgid="6124098729457992931">"不限數據用量收費"</string>
<string name="select_logd_size_title" msgid="7433137108348553508">"記錄器緩衝區空間"</string>
<string name="select_logd_size_dialog_title" msgid="1206769310236476760">"選取每個記錄緩衝區的記錄器空間"</string>
<string name="dev_logpersist_clear_warning_title" msgid="684806692440237967">"要清除記錄器的持久儲存空間嗎?"</string>
diff --git a/packages/SettingsProvider/src/com/android/providers/settings/SettingsProtoDumpUtil.java b/packages/SettingsProvider/src/com/android/providers/settings/SettingsProtoDumpUtil.java
index f43e719..67053d8 100644
--- a/packages/SettingsProvider/src/com/android/providers/settings/SettingsProtoDumpUtil.java
+++ b/packages/SettingsProvider/src/com/android/providers/settings/SettingsProtoDumpUtil.java
@@ -742,6 +742,9 @@
dumpSetting(s, p,
Settings.Global.LOCATION_GLOBAL_KILL_SWITCH,
GlobalSettingsProto.Location.GLOBAL_KILL_SWITCH);
+ dumpSetting(s, p,
+ Settings.Global.GNSS_SATELLITE_BLACKLIST,
+ GlobalSettingsProto.Location.GNSS_SATELLITE_BLACKLIST);
p.end(locationToken);
final long lpmToken = p.start(GlobalSettingsProto.LOW_POWER_MODE);
@@ -2019,6 +2022,10 @@
SecureSettingsProto.Rotation.NUM_ROTATION_SUGGESTIONS_ACCEPTED);
p.end(rotationToken);
+ dumpSetting(s, p,
+ Settings.Secure.RTT_CALLING_MODE,
+ SecureSettingsProto.RTT_CALLING_MODE);
+
final long screensaverToken = p.start(SecureSettingsProto.SCREENSAVER);
dumpSetting(s, p,
Settings.Secure.SCREENSAVER_ENABLED,
@@ -2402,10 +2409,6 @@
SystemSettingsProto.Rotation.HIDE_ROTATION_LOCK_TOGGLE_FOR_ACCESSIBILITY);
p.end(rotationToken);
- dumpSetting(s, p,
- Settings.System.RTT_CALLING_MODE,
- SystemSettingsProto.RTT_CALLING_MODE);
-
final long screenToken = p.start(SystemSettingsProto.SCREEN);
dumpSetting(s, p,
Settings.System.SCREEN_OFF_TIMEOUT,
diff --git a/packages/SystemUI/AndroidManifest.xml b/packages/SystemUI/AndroidManifest.xml
index 3488168..d6fab4c 100644
--- a/packages/SystemUI/AndroidManifest.xml
+++ b/packages/SystemUI/AndroidManifest.xml
@@ -220,7 +220,8 @@
android:supportsRtl="true"
android:theme="@style/Theme.SystemUI"
android:defaultToDeviceProtectedStorage="true"
- android:directBootAware="true">
+ android:directBootAware="true"
+ android:appComponentFactory="android.support.v4.app.CoreComponentFactory">
<!-- Keep theme in sync with SystemUIApplication.onCreate().
Setting the theme on the application does not affect views inflated by services.
The application theme is set again from onCreate to take effect for those views. -->
diff --git a/packages/SystemUI/proguard.flags b/packages/SystemUI/proguard.flags
index 5b8881c..4b5d10e 100644
--- a/packages/SystemUI/proguard.flags
+++ b/packages/SystemUI/proguard.flags
@@ -41,3 +41,4 @@
-keep class com.android.systemui.plugins.** {
public protected *;
}
+-keep class android.support.v4.app.CoreComponentFactory
diff --git a/packages/SystemUI/res/drawable/ic_signal_airplane.xml b/packages/SystemUI/res/drawable/ic_signal_airplane.xml
index 50dd436..0a4d752 100644
--- a/packages/SystemUI/res/drawable/ic_signal_airplane.xml
+++ b/packages/SystemUI/res/drawable/ic_signal_airplane.xml
@@ -20,11 +20,11 @@
android:viewportWidth="20.5"
android:viewportHeight="20.5">
<group
- android:translateX="0.985"
- android:translateY="1.10">
+ android:translateX="1.75"
+ android:translateY="1.4">
<path
android:pathData="M16.01,9.87l-6.24,-3.9v-4.7C9.77,0.57 9.21,0 8.5,0S7.23,0.57 7.23,1.28v4.7L0.99,9.88c-0.37,0.23 -0.6,0.64 -0.6,1.08v0.41c0,0.29 0.29,0.5 0.55,0.41l6.27,-1.97v4.7l-1.37,1.02c-0.21,0.16 -0.34,0.41 -0.34,0.68v0.57c0,0.15 0.12,0.23 0.27,0.2 1.67,-0.47 1.12,-0.31 2.73,-0.78 1.03,0.3 1.7,0.49 2.72,0.78 0.15,0.03 0.27,-0.06 0.27,-0.2v-0.57c0,-0.27 -0.13,-0.52 -0.34,-0.68l-1.37,-1.02v-4.7l6.27,1.97c0.28,0.09 0.55,-0.12 0.55,-0.41v-0.41c0.01,-0.45 -0.23,-0.87 -0.59,-1.09z"
- android:fillColor="#FF0"/>
+ android:fillColor="#FFF"/>
</group>
</vector>
diff --git a/packages/SystemUI/res/drawable/stat_sys_ethernet.xml b/packages/SystemUI/res/drawable/stat_sys_ethernet.xml
index e765320..babaa9f 100644
--- a/packages/SystemUI/res/drawable/stat_sys_ethernet.xml
+++ b/packages/SystemUI/res/drawable/stat_sys_ethernet.xml
@@ -20,11 +20,11 @@
android:viewportWidth="53.0"
android:viewportHeight="48.0">
<path
- android:fillColor="?attr/singleToneColor"
+ android:fillColor="#FFF"
android:pathData="M15.54 13.52l-3.08-2.55L1.64 24l10.82 13.04 3.08-2.55L6.84 24l8.7-10.48zM14 26h4v-4h-4v4zm20-4h-4v4h4v-4zm-12 4h4v-4h-4v4zm13.54-15.04l-3.08 2.55L41.16 24l-8.7 10.48 3.08 2.55L46.36 24 35.54 10.96z"/>
<path
- android:fillColor="?attr/singleToneColor"
+ android:fillColor="#FFF"
android:pathData="M49.000000,40.000000l4.000000,0.000000l0.000000,4.000000l-4.000000,0.000000z"/>
<path
- android:fillColor="?attr/singleToneColor"
+ android:fillColor="#FFF"
android:pathData="M49.000000,20.000000l4.000000,0.000000l0.000000,16.100000l-4.000000,0.000000z"/></vector>
diff --git a/packages/SystemUI/res/drawable/stat_sys_ethernet_fully.xml b/packages/SystemUI/res/drawable/stat_sys_ethernet_fully.xml
index b7b154c..08a9993 100644
--- a/packages/SystemUI/res/drawable/stat_sys_ethernet_fully.xml
+++ b/packages/SystemUI/res/drawable/stat_sys_ethernet_fully.xml
@@ -19,6 +19,6 @@
android:viewportWidth="53.0"
android:viewportHeight="48.0">
<path
- android:fillColor="?attr/singleToneColor"
+ android:fillColor="#FFF"
android:pathData="M15.54 13.52l-3.08-2.55L1.64 24l10.82 13.04 3.08-2.55L6.84 24l8.7-10.48zM14 26h4v-4h-4v4zm20-4h-4v4h4v-4zm-12 4h4v-4h-4v4zm13.54-15.04l-3.08 2.55L41.16 24l-8.7 10.48 3.08 2.55L46.36 24 35.54 10.96z"/>
</vector>
diff --git a/packages/SystemUI/res/layout/quick_status_bar_header_system_icons.xml b/packages/SystemUI/res/layout/quick_status_bar_header_system_icons.xml
index f38129f..388b633 100644
--- a/packages/SystemUI/res/layout/quick_status_bar_header_system_icons.xml
+++ b/packages/SystemUI/res/layout/quick_status_bar_header_system_icons.xml
@@ -31,25 +31,23 @@
<com.android.systemui.statusbar.policy.Clock
android:id="@+id/clock"
- android:textAppearance="@style/TextAppearance.StatusBar.Clock"
android:layout_width="wrap_content"
android:layout_height="match_parent"
- android:singleLine="true"
+ android:gravity="center_vertical|start"
android:paddingStart="@dimen/status_bar_left_clock_starting_padding"
android:paddingEnd="@dimen/status_bar_left_clock_end_padding"
- android:gravity="center_vertical|start"
- systemui:showDark="false"
- />
+ android:singleLine="true"
+ android:textAppearance="@style/TextAppearance.StatusBar.Clock"
+ systemui:showDark="false" />
<com.android.systemui.statusbar.policy.DateView
android:id="@+id/date"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
- android:padding="4dp"
+ android:gravity="center_vertical"
android:singleLine="true"
android:textAppearance="@style/TextAppearance.StatusBar.Expanded.Date"
android:textSize="@dimen/qs_time_collapsed_size"
- android:gravity="center_vertical"
systemui:datePattern="@string/abbrev_wday_month_day_no_year_alarm" />
<android.widget.Space
@@ -57,12 +55,11 @@
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="1"
- android:gravity="center_vertical|center_horizontal"
- />
+ android:gravity="center_vertical|center_horizontal" />
- <com.android.systemui.BatteryMeterView android:id="@+id/battery"
+ <com.android.systemui.BatteryMeterView
+ android:id="@+id/battery"
android:layout_height="match_parent"
android:layout_width="wrap_content"
- android:gravity="center_vertical|end"
- />
+ android:gravity="center_vertical|end" />
</LinearLayout>
diff --git a/packages/SystemUI/res/layout/screen_pinning_request_buttons_land.xml b/packages/SystemUI/res/layout/screen_pinning_request_buttons_land.xml
index 37a1a90..367c13c 100644
--- a/packages/SystemUI/res/layout/screen_pinning_request_buttons_land.xml
+++ b/packages/SystemUI/res/layout/screen_pinning_request_buttons_land.xml
@@ -59,7 +59,6 @@
android:src="@drawable/screen_pinning_bg_circ" />
<ImageView
- android:id="@+id/screen_pinning_back_icon"
android:layout_height="match_parent"
android:layout_width="match_parent"
android:scaleType="center"
@@ -141,6 +140,7 @@
android:src="@drawable/screen_pinning_bg_circ" />
<ImageView
+ android:id="@+id/screen_pinning_back_icon"
android:layout_height="match_parent"
android:layout_width="match_parent"
android:scaleType="center"
diff --git a/packages/SystemUI/shared/src/com/android/systemui/shared/system/ActivityManagerWrapper.java b/packages/SystemUI/shared/src/com/android/systemui/shared/system/ActivityManagerWrapper.java
index 6aa2754..ca5b034 100644
--- a/packages/SystemUI/shared/src/com/android/systemui/shared/system/ActivityManagerWrapper.java
+++ b/packages/SystemUI/shared/src/com/android/systemui/shared/system/ActivityManagerWrapper.java
@@ -44,8 +44,10 @@
import android.graphics.Rect;
import android.os.Bundle;
import android.os.Handler;
+import android.os.IBinder;
import android.os.Looper;
import android.os.RemoteException;
+import android.os.ServiceManager;
import android.os.UserHandle;
import android.provider.Settings;
import android.util.Log;
@@ -53,6 +55,8 @@
import android.view.IRecentsAnimationRunner;
import android.view.RemoteAnimationTarget;
+
+import com.android.internal.app.IVoiceInteractionManagerService;
import com.android.systemui.shared.recents.model.Task;
import com.android.systemui.shared.recents.model.Task.TaskKey;
import com.android.systemui.shared.recents.model.ThumbnailData;
@@ -67,6 +71,9 @@
private static final ActivityManagerWrapper sInstance = new ActivityManagerWrapper();
+ // Should match the values in PhoneWindowManager
+ public static final String CLOSE_SYSTEM_WINDOWS_REASON_RECENTS = "recentapps";
+
private final PackageManager mPackageManager;
private final BackgroundExecutor mBackgroundExecutor;
private final TaskStackChangeListeners mTaskStackChangeListeners;
@@ -432,4 +439,21 @@
return false;
}
}
+
+ /**
+ * Shows a voice session identified by {@code token}
+ * @return true if the session was shown, false otherwise
+ */
+ public boolean showVoiceSession(IBinder token, Bundle args, int flags) {
+ IVoiceInteractionManagerService service = IVoiceInteractionManagerService.Stub.asInterface(
+ ServiceManager.getService(Context.VOICE_INTERACTION_MANAGER_SERVICE));
+ if (service == null) {
+ return false;
+ }
+ try {
+ return service.showSessionFromSession(token, args, flags);
+ } catch (RemoteException e) {
+ return false;
+ }
+ }
}
diff --git a/packages/SystemUI/src/com/android/systemui/BatteryMeterView.java b/packages/SystemUI/src/com/android/systemui/BatteryMeterView.java
index 1ae06d7..0683514 100644
--- a/packages/SystemUI/src/com/android/systemui/BatteryMeterView.java
+++ b/packages/SystemUI/src/com/android/systemui/BatteryMeterView.java
@@ -81,6 +81,14 @@
private float mDarkIntensity;
private int mUser;
+ /**
+ * Whether we should use colors that adapt based on wallpaper/the scrim behind quick settings.
+ */
+ private boolean mUseWallpaperTextColors;
+
+ private int mNonAdaptedForegroundColor;
+ private int mNonAdaptedBackgroundColor;
+
public BatteryMeterView(Context context) {
this(context, null, 0);
}
@@ -140,6 +148,29 @@
updateShowPercent();
}
+ /**
+ * Sets whether the battery meter view uses the wallpaperTextColor. If we're not using it, we'll
+ * revert back to dark-mode-based/tinted colors.
+ *
+ * @param shouldUseWallpaperTextColor whether we should use wallpaperTextColor for all
+ * components
+ */
+ public void useWallpaperTextColor(boolean shouldUseWallpaperTextColor) {
+ if (shouldUseWallpaperTextColor == mUseWallpaperTextColors) {
+ return;
+ }
+
+ mUseWallpaperTextColors = shouldUseWallpaperTextColor;
+
+ if (mUseWallpaperTextColors) {
+ updateColors(
+ Utils.getColorAttr(mContext, R.attr.wallpaperTextColor),
+ Utils.getColorAttr(mContext, R.attr.wallpaperTextColorSecondary));
+ } else {
+ updateColors(mNonAdaptedForegroundColor, mNonAdaptedBackgroundColor);
+ }
+ }
+
public void setColorsFromContext(Context context) {
if (context == null) {
return;
@@ -179,7 +210,8 @@
getContext().getContentResolver().registerContentObserver(
Settings.System.getUriFor(SHOW_BATTERY_PERCENT), false, mSettingObserver, mUser);
updateShowPercent();
- Dependency.get(TunerService.class).addTunable(this, StatusBarIconController.ICON_BLACKLIST);
+ Dependency.get(TunerService.class)
+ .addTunable(this, StatusBarIconController.ICON_BLACKLIST);
Dependency.get(ConfigurationController.class).addCallback(this);
mUserTracker.startTracking();
}
@@ -273,19 +305,23 @@
@Override
public void onDarkChanged(Rect area, float darkIntensity, int tint) {
mDarkIntensity = darkIntensity;
+
float intensity = DarkIconDispatcher.isInArea(area, this) ? darkIntensity : 0;
- int foreground = getColorForDarkIntensity(intensity, mLightModeFillColor,
- mDarkModeFillColor);
- int background = getColorForDarkIntensity(intensity, mLightModeBackgroundColor,
- mDarkModeBackgroundColor);
- mDrawable.setColors(foreground, background);
- setTextColor(foreground);
+ mNonAdaptedForegroundColor = getColorForDarkIntensity(
+ intensity, mLightModeFillColor, mDarkModeFillColor);
+ mNonAdaptedBackgroundColor = getColorForDarkIntensity(
+ intensity, mLightModeBackgroundColor,mDarkModeBackgroundColor);
+
+ if (!mUseWallpaperTextColors) {
+ updateColors(mNonAdaptedForegroundColor, mNonAdaptedBackgroundColor);
+ }
}
- public void setTextColor(int color) {
- mTextColor = color;
+ private void updateColors(int foregroundColor, int backgroundColor) {
+ mDrawable.setColors(foregroundColor, backgroundColor);
+ mTextColor = foregroundColor;
if (mBatteryPercentView != null) {
- mBatteryPercentView.setTextColor(color);
+ mBatteryPercentView.setTextColor(foregroundColor);
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/OverviewProxyService.java b/packages/SystemUI/src/com/android/systemui/OverviewProxyService.java
index 8cff56d..b1020cf 100644
--- a/packages/SystemUI/src/com/android/systemui/OverviewProxyService.java
+++ b/packages/SystemUI/src/com/android/systemui/OverviewProxyService.java
@@ -22,6 +22,7 @@
import android.content.Intent;
import android.content.IntentFilter;
import android.content.ServiceConnection;
+import android.content.pm.PackageManager;
import android.graphics.Rect;
import android.os.Binder;
import android.os.Handler;
@@ -39,6 +40,7 @@
import com.android.systemui.recents.misc.SystemServicesProxy;
import com.android.systemui.shared.recents.IOverviewProxy;
import com.android.systemui.shared.recents.ISystemUiProxy;
+import com.android.systemui.shared.system.ActivityManagerWrapper;
import com.android.systemui.shared.system.GraphicBufferCompat;
import com.android.systemui.statusbar.phone.StatusBar;
import com.android.systemui.statusbar.policy.CallbackController;
@@ -50,6 +52,7 @@
import java.util.ArrayList;
import java.util.List;
+import static android.content.pm.PackageManager.MATCH_DIRECT_BOOT_UNAWARE;
import static com.android.systemui.shared.system.NavigationBarCompat.FLAG_DISABLE_SWIPE_UP;
import static com.android.systemui.shared.system.NavigationBarCompat.InteractionType;
@@ -71,11 +74,13 @@
private final DeviceProvisionedController mDeviceProvisionedController
= Dependency.get(DeviceProvisionedController.class);
private final List<OverviewProxyListener> mConnectionCallbacks = new ArrayList<>();
+ private final Intent mQuickStepIntent;
private IOverviewProxy mOverviewProxy;
private int mConnectionBackoffAttempts;
private CharSequence mOnboardingText;
private @InteractionType int mInteractionFlags;
+ private boolean mIsEnabled;
private ISystemUiProxy mSysUiProxy = new ISystemUiProxy.Stub() {
@@ -130,14 +135,23 @@
});
}
} finally {
+ Prefs.putInt(mContext, Prefs.Key.QUICK_STEP_INTERACTION_FLAGS, mInteractionFlags);
Binder.restoreCallingIdentity(token);
}
}
};
- private final BroadcastReceiver mLauncherAddedReceiver = new BroadcastReceiver() {
+ private final BroadcastReceiver mLauncherStateChangedReceiver = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
+ updateEnabledState();
+
+ // When launcher service is disabled, reset interaction flags because it is inactive
+ if (!isEnabled()) {
+ mInteractionFlags = 0;
+ Prefs.remove(mContext, Prefs.Key.QUICK_STEP_INTERACTION_FLAGS);
+ }
+
// Reconnect immediately, instead of waiting for resume to arrive.
startConnectionToCurrentUser();
}
@@ -196,17 +210,21 @@
mConnectionBackoffAttempts = 0;
mRecentsComponentName = ComponentName.unflattenFromString(context.getString(
com.android.internal.R.string.config_recentsComponentName));
+ mQuickStepIntent = new Intent(ACTION_QUICKSTEP)
+ .setPackage(mRecentsComponentName.getPackageName());
+ mInteractionFlags = Prefs.getInt(mContext, Prefs.Key.QUICK_STEP_INTERACTION_FLAGS, 0);
// Listen for the package update changes.
if (SystemServicesProxy.getInstance(context)
.isSystemUser(mDeviceProvisionedController.getCurrentUser())) {
+ updateEnabledState();
mDeviceProvisionedController.addCallback(mDeviceProvisionedCallback);
IntentFilter filter = new IntentFilter(Intent.ACTION_PACKAGE_ADDED);
filter.addDataScheme("package");
filter.addDataSchemeSpecificPart(mRecentsComponentName.getPackageName(),
PatternMatcher.PATTERN_LITERAL);
filter.addAction(Intent.ACTION_PACKAGE_CHANGED);
- mContext.registerReceiver(mLauncherAddedReceiver, filter);
+ mContext.registerReceiver(mLauncherStateChangedReceiver, filter);
}
}
@@ -222,7 +240,7 @@
disconnectFromLauncherService();
// If user has not setup yet or already connected, do not try to connect
- if (!mDeviceProvisionedController.isCurrentUserSetup()) {
+ if (!mDeviceProvisionedController.isCurrentUserSetup() || !isEnabled()) {
return;
}
mHandler.removeCallbacks(mConnectionRunnable);
@@ -248,6 +266,7 @@
public void addCallback(OverviewProxyListener listener) {
mConnectionCallbacks.add(listener);
listener.onConnectionChanged(mOverviewProxy != null);
+ listener.onInteractionFlagsChanged(mInteractionFlags);
}
@Override
@@ -256,7 +275,11 @@
}
public boolean shouldShowSwipeUpUI() {
- return getProxy() != null && ((mInteractionFlags & FLAG_DISABLE_SWIPE_UP) == 0);
+ return isEnabled() && ((mInteractionFlags & FLAG_DISABLE_SWIPE_UP) == 0);
+ }
+
+ public boolean isEnabled() {
+ return mIsEnabled;
}
public IOverviewProxy getProxy() {
@@ -292,6 +315,12 @@
}
}
+ private void updateEnabledState() {
+ mIsEnabled = mContext.getPackageManager().resolveServiceAsUser(mQuickStepIntent,
+ MATCH_DIRECT_BOOT_UNAWARE,
+ ActivityManagerWrapper.getInstance().getCurrentUserId()) != null;
+ }
+
@Override
public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
pw.println(TAG_OPS + " state:");
diff --git a/packages/SystemUI/src/com/android/systemui/Prefs.java b/packages/SystemUI/src/com/android/systemui/Prefs.java
index 2a27147..7f7a769 100644
--- a/packages/SystemUI/src/com/android/systemui/Prefs.java
+++ b/packages/SystemUI/src/com/android/systemui/Prefs.java
@@ -54,7 +54,8 @@
Key.HAS_SEEN_RECENTS_ONBOARDING,
Key.SEEN_RINGER_GUIDANCE_COUNT,
Key.QS_HAS_TURNED_OFF_MOBILE_DATA,
- Key.TOUCHED_RINGER_TOGGLE
+ Key.TOUCHED_RINGER_TOGGLE,
+ Key.QUICK_STEP_INTERACTION_FLAGS
})
public @interface Key {
@Deprecated
@@ -93,6 +94,7 @@
String QS_TILE_SPECS_REVEALED = "QsTileSpecsRevealed";
String QS_HAS_TURNED_OFF_MOBILE_DATA = "QsHasTurnedOffMobileData";
String TOUCHED_RINGER_TOGGLE = "TouchedRingerToggle";
+ String QUICK_STEP_INTERACTION_FLAGS = "QuickStepInteractionFlags";
}
public static boolean getBoolean(Context context, @Key String key, boolean defaultValue) {
diff --git a/packages/SystemUI/src/com/android/systemui/SystemUIFactory.java b/packages/SystemUI/src/com/android/systemui/SystemUIFactory.java
index 039e7b5..0ba26e9 100644
--- a/packages/SystemUI/src/com/android/systemui/SystemUIFactory.java
+++ b/packages/SystemUI/src/com/android/systemui/SystemUIFactory.java
@@ -44,6 +44,7 @@
import com.android.systemui.statusbar.notification.VisualStabilityManager;
import com.android.systemui.statusbar.phone.DozeParameters;
import com.android.systemui.statusbar.phone.KeyguardBouncer;
+import com.android.systemui.statusbar.phone.KeyguardDismissUtil;
import com.android.systemui.statusbar.phone.LightBarController;
import com.android.systemui.statusbar.phone.LockIcon;
import com.android.systemui.statusbar.phone.LockscreenWallpaper;
@@ -142,5 +143,6 @@
providers.put(NotificationViewHierarchyManager.class,
() -> new NotificationViewHierarchyManager(context));
providers.put(NotificationEntryManager.class, () -> new NotificationEntryManager(context));
+ providers.put(KeyguardDismissUtil.class, KeyguardDismissUtil::new);
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/fingerprint/FingerprintDialogImpl.java b/packages/SystemUI/src/com/android/systemui/fingerprint/FingerprintDialogImpl.java
index 3577c0f..c238e54 100644
--- a/packages/SystemUI/src/com/android/systemui/fingerprint/FingerprintDialogImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/fingerprint/FingerprintDialogImpl.java
@@ -18,8 +18,8 @@
import android.content.Context;
import android.content.pm.PackageManager;
-import android.hardware.biometrics.BiometricDialog;
-import android.hardware.biometrics.IBiometricDialogReceiver;
+import android.hardware.biometrics.BiometricPrompt;
+import android.hardware.biometrics.IBiometricPromptReceiver;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
@@ -48,7 +48,7 @@
private FingerprintDialogView mDialogView;
private WindowManager mWindowManager;
- private IBiometricDialogReceiver mReceiver;
+ private IBiometricPromptReceiver mReceiver;
private boolean mDialogShowing;
private Handler mHandler = new Handler() {
@@ -97,7 +97,7 @@
}
@Override
- public void showFingerprintDialog(Bundle bundle, IBiometricDialogReceiver receiver) {
+ public void showFingerprintDialog(Bundle bundle, IBiometricPromptReceiver receiver) {
if (DEBUG) Log.d(TAG, "showFingerprintDialog");
// Remove these messages as they are part of the previous client
mHandler.removeMessages(MSG_FINGERPRINT_ERROR);
@@ -139,7 +139,7 @@
Log.w(TAG, "Dialog already showing");
return;
}
- mReceiver = (IBiometricDialogReceiver) args.arg2;
+ mReceiver = (IBiometricPromptReceiver) args.arg2;
mDialogView.setBundle((Bundle)args.arg1);
mWindowManager.addView(mDialogView, mDialogView.getLayoutParams());
mDialogShowing = true;
@@ -177,7 +177,7 @@
}
if (userCanceled) {
try {
- mReceiver.onDialogDismissed(BiometricDialog.DISMISSED_REASON_USER_CANCEL);
+ mReceiver.onDialogDismissed(BiometricPrompt.DISMISSED_REASON_USER_CANCEL);
} catch (RemoteException e) {
Log.e(TAG, "RemoteException when hiding dialog", e);
}
@@ -193,7 +193,7 @@
return;
}
try {
- mReceiver.onDialogDismissed(BiometricDialog.DISMISSED_REASON_NEGATIVE);
+ mReceiver.onDialogDismissed(BiometricPrompt.DISMISSED_REASON_NEGATIVE);
} catch (RemoteException e) {
Log.e(TAG, "Remote exception when handling negative button", e);
}
@@ -206,7 +206,7 @@
return;
}
try {
- mReceiver.onDialogDismissed(BiometricDialog.DISMISSED_REASON_POSITIVE);
+ mReceiver.onDialogDismissed(BiometricPrompt.DISMISSED_REASON_POSITIVE);
} catch (RemoteException e) {
Log.e(TAG, "Remote exception when handling positive button", e);
}
diff --git a/packages/SystemUI/src/com/android/systemui/fingerprint/FingerprintDialogView.java b/packages/SystemUI/src/com/android/systemui/fingerprint/FingerprintDialogView.java
index 3e1ac02..d1d6609 100644
--- a/packages/SystemUI/src/com/android/systemui/fingerprint/FingerprintDialogView.java
+++ b/packages/SystemUI/src/com/android/systemui/fingerprint/FingerprintDialogView.java
@@ -22,11 +22,12 @@
import android.graphics.PorterDuff;
import android.graphics.drawable.AnimatedVectorDrawable;
import android.graphics.drawable.Drawable;
-import android.hardware.biometrics.BiometricDialog;
+import android.hardware.biometrics.BiometricPrompt;
import android.os.Binder;
import android.os.Bundle;
import android.os.Handler;
import android.os.IBinder;
+import android.text.TextUtils;
import android.util.DisplayMetrics;
import android.util.Log;
import android.view.KeyEvent;
@@ -161,29 +162,29 @@
mLastState = STATE_NONE;
updateFingerprintIcon(STATE_FINGERPRINT);
- title.setText(mBundle.getCharSequence(BiometricDialog.KEY_TITLE));
+ title.setText(mBundle.getCharSequence(BiometricPrompt.KEY_TITLE));
title.setSelected(true);
- final CharSequence subtitleText = mBundle.getCharSequence(BiometricDialog.KEY_SUBTITLE);
- if (subtitleText == null) {
+ final CharSequence subtitleText = mBundle.getCharSequence(BiometricPrompt.KEY_SUBTITLE);
+ if (TextUtils.isEmpty(subtitleText)) {
subtitle.setVisibility(View.GONE);
} else {
subtitle.setVisibility(View.VISIBLE);
subtitle.setText(subtitleText);
}
- final CharSequence descriptionText = mBundle.getCharSequence(BiometricDialog.KEY_DESCRIPTION);
- if (descriptionText == null) {
- subtitle.setVisibility(View.VISIBLE);
+ final CharSequence descriptionText = mBundle.getCharSequence(BiometricPrompt.KEY_DESCRIPTION);
+ if (TextUtils.isEmpty(descriptionText)) {
description.setVisibility(View.GONE);
} else {
- description.setText(mBundle.getCharSequence(BiometricDialog.KEY_DESCRIPTION));
+ description.setVisibility(View.VISIBLE);
+ description.setText(descriptionText);
}
- negative.setText(mBundle.getCharSequence(BiometricDialog.KEY_NEGATIVE_TEXT));
+ negative.setText(mBundle.getCharSequence(BiometricPrompt.KEY_NEGATIVE_TEXT));
final CharSequence positiveText =
- mBundle.getCharSequence(BiometricDialog.KEY_POSITIVE_TEXT);
+ mBundle.getCharSequence(BiometricPrompt.KEY_POSITIVE_TEXT);
positive.setText(positiveText); // needs to be set for marquee to work
if (positiveText != null) {
positive.setVisibility(View.VISIBLE);
@@ -269,7 +270,7 @@
mErrorText.setTextColor(mErrorColor);
mErrorText.setContentDescription(message);
mHandler.sendMessageDelayed(mHandler.obtainMessage(FingerprintDialogImpl.MSG_CLEAR_MESSAGE),
- BiometricDialog.HIDE_DIALOG_DELAY);
+ BiometricPrompt.HIDE_DIALOG_DELAY);
}
public void showHelpMessage(String message) {
@@ -279,7 +280,7 @@
public void showErrorMessage(String error) {
showTemporaryMessage(error);
mHandler.sendMessageDelayed(mHandler.obtainMessage(FingerprintDialogImpl.MSG_HIDE_DIALOG,
- false /* userCanceled */), BiometricDialog.HIDE_DIALOG_DELAY);
+ false /* userCanceled */), BiometricPrompt.HIDE_DIALOG_DELAY);
}
private void updateFingerprintIcon(int newState) {
diff --git a/packages/SystemUI/src/com/android/systemui/pip/phone/PipTouchHandler.java b/packages/SystemUI/src/com/android/systemui/pip/phone/PipTouchHandler.java
index a0bdcd0..1805f96 100644
--- a/packages/SystemUI/src/com/android/systemui/pip/phone/PipTouchHandler.java
+++ b/packages/SystemUI/src/com/android/systemui/pip/phone/PipTouchHandler.java
@@ -295,6 +295,26 @@
final Rect toAdjustedBounds = mMenuState == MENU_STATE_FULL
? expandedAdjustedBounds
: normalAdjustedBounds;
+ final Rect toMovementBounds = mMenuState == MENU_STATE_FULL
+ ? expandedMovementBounds
+ : normalMovementBounds;
+
+ // If the PIP window needs to shift to right above shelf/IME and it's already above
+ // that, don't move the PIP window.
+ if (toAdjustedBounds.bottom < mMovementBounds.bottom
+ && animatingBounds.top < toAdjustedBounds.bottom) {
+ return;
+ }
+
+ // If the PIP window needs to shift down due to dismissal of shelf/IME but it's way
+ // above the position as if shelf/IME shows, don't move the PIP window.
+ int movementBoundsAdjustment = toMovementBounds.bottom - mMovementBounds.bottom;
+ int offsetAdjustment = fromImeAdjustment ? mImeOffset : mShelfHeight;
+ if (toAdjustedBounds.bottom >= mMovementBounds.bottom
+ && animatingBounds.top
+ < toAdjustedBounds.bottom - movementBoundsAdjustment - offsetAdjustment) {
+ return;
+ }
animateToOffset(animatingBounds, toAdjustedBounds);
}
@@ -320,10 +340,6 @@
private void animateToOffset(Rect animatingBounds, Rect toAdjustedBounds) {
final Rect bounds = new Rect(animatingBounds);
- if (toAdjustedBounds.bottom < mMovementBounds.bottom
- && bounds.top < toAdjustedBounds.bottom) {
- return;
- }
bounds.offset(0, toAdjustedBounds.bottom - bounds.top);
// In landscape mode, PIP window can go offset while launching IME. We want to align the
// the top of the PIP window with the top of the movement bounds in that case.
diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSContainerImpl.java b/packages/SystemUI/src/com/android/systemui/qs/QSContainerImpl.java
index bfbfbf6..7161463 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/QSContainerImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/QSContainerImpl.java
@@ -18,17 +18,15 @@
import android.content.Context;
import android.content.res.Configuration;
-import android.graphics.Canvas;
-import android.graphics.Path;
import android.graphics.Point;
import android.util.AttributeSet;
+import android.util.Log;
import android.view.View;
import android.widget.FrameLayout;
import com.android.settingslib.Utils;
import com.android.systemui.R;
import com.android.systemui.qs.customize.QSCustomizer;
-import com.android.systemui.statusbar.ExpandableOutlineView;
/**
* Wrapper view with background which contains {@link QSPanel} and {@link BaseStatusBarHeader}
@@ -44,7 +42,11 @@
protected float mQsExpansion;
private QSCustomizer mQSCustomizer;
private View mQSFooter;
+
private View mBackground;
+ private View mBackgroundGradient;
+ private View mStatusBarBackground;
+
private int mSideMargins;
public QSContainerImpl(Context context, AttributeSet attrs) {
@@ -60,6 +62,8 @@
mQSCustomizer = findViewById(R.id.qs_customize);
mQSFooter = findViewById(R.id.qs_footer);
mBackground = findViewById(R.id.quick_settings_background);
+ mStatusBarBackground = findViewById(R.id.quick_settings_status_bar_background);
+ mBackgroundGradient = findViewById(R.id.quick_settings_gradient_view);
mSideMargins = getResources().getDimensionPixelSize(R.dimen.notification_side_paddings);
setClickable(true);
@@ -68,6 +72,22 @@
}
@Override
+ protected void onConfigurationChanged(Configuration newConfig) {
+ super.onConfigurationChanged(newConfig);
+
+ // Hide the backgrounds when in landscape mode.
+ if (newConfig.orientation == Configuration.ORIENTATION_LANDSCAPE) {
+ mBackgroundGradient.setVisibility(View.INVISIBLE);
+ mStatusBarBackground.setVisibility(View.INVISIBLE);
+ } else {
+ mBackgroundGradient.setVisibility(View.VISIBLE);
+ mStatusBarBackground.setVisibility(View.VISIBLE);
+ }
+
+ updateResources();
+ }
+
+ @Override
public boolean performClick() {
// Want to receive clicks so missing QQS tiles doesn't cause collapse, but
// don't want to do anything with them.
@@ -101,6 +121,14 @@
updateExpansion();
}
+ private void updateResources() {
+ LayoutParams layoutParams = (LayoutParams) mQSPanel.getLayoutParams();
+ layoutParams.topMargin = mContext.getResources().getDimensionPixelSize(
+ com.android.internal.R.dimen.quick_qs_offset_height);
+
+ mQSPanel.setLayoutParams(layoutParams);
+ }
+
/**
* Overrides the height of this view (post-layout), so that the content is clipped to that
* height and the background is set to that height.
diff --git a/packages/SystemUI/src/com/android/systemui/qs/QuickStatusBarHeader.java b/packages/SystemUI/src/com/android/systemui/qs/QuickStatusBarHeader.java
index 224c367..70bfad1 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/QuickStatusBarHeader.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/QuickStatusBarHeader.java
@@ -26,6 +26,7 @@
import android.content.Intent;
import android.content.IntentFilter;
import android.content.res.Configuration;
+import android.content.res.Resources;
import android.graphics.Color;
import android.graphics.Rect;
import android.media.AudioManager;
@@ -54,8 +55,10 @@
import com.android.systemui.statusbar.phone.PhoneStatusBarView;
import com.android.systemui.statusbar.phone.StatusBarIconController;
import com.android.systemui.statusbar.phone.StatusBarIconController.TintedIconManager;
+import com.android.systemui.statusbar.policy.Clock;
import com.android.systemui.statusbar.policy.DarkIconDispatcher;
import com.android.systemui.statusbar.policy.DarkIconDispatcher.DarkReceiver;
+import com.android.systemui.statusbar.policy.DateView;
import com.android.systemui.statusbar.policy.NextAlarmController;
import java.util.Locale;
@@ -90,6 +93,7 @@
private TouchAnimator mStatusIconsAlphaAnimator;
private TouchAnimator mHeaderTextContainerAlphaAnimator;
+ private View mSystemIconsView;
private View mQuickQsStatusIcons;
private View mDate;
private View mHeaderTextContainerView;
@@ -107,6 +111,9 @@
private View mStatusSeparator;
private ImageView mRingerModeIcon;
private TextView mRingerModeTextView;
+ private BatteryMeterView mBatteryMeterView;
+ private Clock mClockView;
+ private DateView mDateView;
private NextAlarmController mAlarmController;
/** Counts how many times the long press tooltip has been shown to the user. */
@@ -138,6 +145,7 @@
mHeaderQsPanel = findViewById(R.id.quick_qs_panel);
mDate = findViewById(R.id.date);
mDate.setOnClickListener(this);
+ mSystemIconsView = findViewById(R.id.quick_status_bar_system_icons);
mQuickQsStatusIcons = findViewById(R.id.quick_qs_status_icons);
mIconManager = new TintedIconManager(findViewById(R.id.statusIcons));
@@ -164,8 +172,10 @@
// Set the correct tint for the status icons so they contrast
mIconManager.setTint(fillColor);
- BatteryMeterView battery = findViewById(R.id.battery);
- battery.setForceShowPercent(true);
+ mBatteryMeterView = findViewById(R.id.battery);
+ mBatteryMeterView.setForceShowPercent(true);
+ mClockView = findViewById(R.id.clock);
+ mDateView = findViewById(R.id.date);
}
private void updateStatusText() {
@@ -212,6 +222,13 @@
protected void onConfigurationChanged(Configuration newConfig) {
super.onConfigurationChanged(newConfig);
updateResources();
+
+ // Update color schemes in landscape to use wallpaperTextColor
+ boolean shouldUseWallpaperTextColor =
+ newConfig.orientation == Configuration.ORIENTATION_LANDSCAPE;
+ mBatteryMeterView.useWallpaperTextColor(shouldUseWallpaperTextColor);
+ mClockView.useWallpaperTextColor(shouldUseWallpaperTextColor);
+ mDateView.useWallpaperTextColor(shouldUseWallpaperTextColor);
}
@Override
@@ -221,11 +238,21 @@
}
private void updateResources() {
- // Update height, especially due to landscape mode restricting space.
+ Resources resources = mContext.getResources();
+
+ // Update height for a few views, especially due to landscape mode restricting space.
mHeaderTextContainerView.getLayoutParams().height =
- mContext.getResources().getDimensionPixelSize(R.dimen.qs_header_tooltip_height);
+ resources.getDimensionPixelSize(R.dimen.qs_header_tooltip_height);
mHeaderTextContainerView.setLayoutParams(mHeaderTextContainerView.getLayoutParams());
+ mSystemIconsView.getLayoutParams().height = resources.getDimensionPixelSize(
+ com.android.internal.R.dimen.quick_qs_offset_height);
+ mSystemIconsView.setLayoutParams(mSystemIconsView.getLayoutParams());
+
+ getLayoutParams().height =
+ resources.getDimensionPixelSize(com.android.internal.R.dimen.quick_qs_total_height);
+ setLayoutParams(getLayoutParams());
+
updateStatusIconAlphaAnimator();
updateHeaderTextContainerAlphaAnimator();
}
@@ -497,9 +524,8 @@
mHeaderQsPanel.setHost(host, null /* No customization in header */);
// Use SystemUI context to get battery meter colors, and let it use the default tint (white)
- BatteryMeterView battery = findViewById(R.id.battery);
- battery.setColorsFromContext(mHost.getContext());
- battery.onDarkChanged(new Rect(), 0, DarkIconDispatcher.DEFAULT_ICON_TINT);
+ mBatteryMeterView.setColorsFromContext(mHost.getContext());
+ mBatteryMeterView.onDarkChanged(new Rect(), 0, DarkIconDispatcher.DEFAULT_ICON_TINT);
}
public void setCallback(Callback qsPanelCallback) {
diff --git a/packages/SystemUI/src/com/android/systemui/recents/Recents.java b/packages/SystemUI/src/com/android/systemui/recents/Recents.java
index 0f85c5b..8bb3c02 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/Recents.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/Recents.java
@@ -22,6 +22,7 @@
import static com.android.systemui.statusbar.phone.StatusBar.SYSTEM_DIALOG_REASON_RECENT_APPS;
import android.app.ActivityManager;
+import android.app.trust.TrustManager;
import android.content.ComponentName;
import android.content.ContentResolver;
import android.content.Context;
@@ -51,6 +52,7 @@
import com.android.systemui.OverviewProxyService;
import com.android.systemui.R;
import com.android.systemui.RecentsComponent;
+import com.android.systemui.SystemUIApplication;
import com.android.systemui.shared.recents.IOverviewProxy;
import com.android.systemui.SystemUI;
import com.android.systemui.recents.events.EventBus;
@@ -70,6 +72,7 @@
import com.android.systemui.stackdivider.Divider;
import com.android.systemui.statusbar.CommandQueue;
+import com.android.systemui.statusbar.phone.StatusBar;
import java.io.FileDescriptor;
import java.io.PrintWriter;
import java.util.ArrayList;
@@ -107,6 +110,7 @@
private Handler mHandler;
private RecentsImpl mImpl;
+ private TrustManager mTrustManager;
private int mDraggingInRecentsCurrentUser;
// Only For system user, this is the callbacks instance we return to each secondary user
@@ -235,6 +239,8 @@
registerWithSystemUser();
}
putComponent(Recents.class, this);
+
+ mTrustManager = (TrustManager) mContext.getSystemService(Context.TRUST_SERVICE);
}
@Override
@@ -342,12 +348,28 @@
// If connected to launcher service, let it handle the toggle logic
IOverviewProxy overviewProxy = mOverviewProxyService.getProxy();
if (overviewProxy != null) {
- try {
- overviewProxy.onOverviewToggle();
- return;
- } catch (RemoteException e) {
- Log.e(TAG, "Cannot send toggle recents through proxy service.", e);
+ final Runnable toggleRecents = () -> {
+ try {
+ if (mOverviewProxyService.getProxy() != null) {
+ mOverviewProxyService.getProxy().onOverviewToggle();
+ }
+ } catch (RemoteException e) {
+ Log.e(TAG, "Cannot send toggle recents through proxy service.", e);
+ }
+ };
+ // Preload only if device for current user is unlocked
+ final StatusBar statusBar = getComponent(StatusBar.class);
+ if (statusBar != null && statusBar.isKeyguardShowing()) {
+ statusBar.executeRunnableDismissingKeyguard(() -> {
+ // Flush trustmanager before checking device locked per user
+ mTrustManager.reportKeyguardShowingChanged();
+ mHandler.post(toggleRecents);
+ }, null, true /* dismissShade */, false /* afterKeyguardGone */,
+ true /* deferred */);
+ } else {
+ toggleRecents.run();
}
+ return;
}
int growTarget = getComponent(Divider.class).getView().growsRecents();
diff --git a/packages/SystemUI/src/com/android/systemui/recents/RecentsImpl.java b/packages/SystemUI/src/com/android/systemui/recents/RecentsImpl.java
index 19da3db..6fcb1c1 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/RecentsImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/RecentsImpl.java
@@ -126,7 +126,7 @@
@Override
public void onTaskStackChangedBackground() {
// Skip background preloading recents in SystemUI if the overview services is bound
- if (Dependency.get(OverviewProxyService.class).getProxy() != null) {
+ if (Dependency.get(OverviewProxyService.class).isEnabled()) {
return;
}
@@ -300,7 +300,7 @@
public void onBootCompleted() {
// Skip preloading tasks if we are already bound to the service
- if (Dependency.get(OverviewProxyService.class).getProxy() != null) {
+ if (Dependency.get(OverviewProxyService.class).isEnabled()) {
return;
}
diff --git a/packages/SystemUI/src/com/android/systemui/recents/ScreenPinningRequest.java b/packages/SystemUI/src/com/android/systemui/recents/ScreenPinningRequest.java
index 3dd6e35..bfbba7c 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/ScreenPinningRequest.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/ScreenPinningRequest.java
@@ -107,7 +107,7 @@
final WindowManager.LayoutParams lp = new WindowManager.LayoutParams(
ViewGroup.LayoutParams.MATCH_PARENT,
ViewGroup.LayoutParams.MATCH_PARENT,
- WindowManager.LayoutParams.TYPE_NAVIGATION_BAR_PANEL,
+ WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY,
WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN
| WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE,
PixelFormat.TRANSLUCENT);
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/CommandQueue.java b/packages/SystemUI/src/com/android/systemui/statusbar/CommandQueue.java
index 65037f9..6fd0aa6 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/CommandQueue.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/CommandQueue.java
@@ -18,7 +18,7 @@
import android.content.ComponentName;
import android.graphics.Rect;
-import android.hardware.biometrics.IBiometricDialogReceiver;
+import android.hardware.biometrics.IBiometricPromptReceiver;
import android.os.Bundle;
import android.os.Handler;
import android.os.IBinder;
@@ -160,7 +160,7 @@
default void onRotationProposal(int rotation, boolean isValid) { }
- default void showFingerprintDialog(Bundle bundle, IBiometricDialogReceiver receiver) { }
+ default void showFingerprintDialog(Bundle bundle, IBiometricPromptReceiver receiver) { }
default void onFingerprintAuthenticated() { }
default void onFingerprintHelp(String message) { }
default void onFingerprintError(String error) { }
@@ -513,7 +513,7 @@
}
@Override
- public void showFingerprintDialog(Bundle bundle, IBiometricDialogReceiver receiver) {
+ public void showFingerprintDialog(Bundle bundle, IBiometricPromptReceiver receiver) {
synchronized (mLock) {
SomeArgs args = SomeArgs.obtain();
args.arg1 = bundle;
@@ -759,7 +759,7 @@
for (int i = 0; i < mCallbacks.size(); i++) {
mCallbacks.get(i).showFingerprintDialog(
(Bundle)((SomeArgs)msg.obj).arg1,
- (IBiometricDialogReceiver)((SomeArgs)msg.obj).arg2);
+ (IBiometricPromptReceiver)((SomeArgs)msg.obj).arg2);
}
break;
case MSG_FINGERPRINT_AUTHENTICATED:
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationLockscreenUserManager.java b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationLockscreenUserManager.java
index ccabb79..e24bf67 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationLockscreenUserManager.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationLockscreenUserManager.java
@@ -47,7 +47,6 @@
import java.io.FileDescriptor;
import java.io.PrintWriter;
-import java.util.List;
/**
* Handles keeping track of the current user, profiles, and various things related to hiding
@@ -352,7 +351,8 @@
final boolean allowedByUser = 0 != Settings.Secure.getIntForUser(
mContext.getContentResolver(),
Settings.Secure.LOCK_SCREEN_ALLOW_PRIVATE_NOTIFICATIONS, 0, userHandle);
- final boolean allowedByDpm = adminAllowsUnredactedNotifications(userHandle);
+ final boolean allowedByDpm = adminAllowsKeyguardFeature(userHandle,
+ DevicePolicyManager.KEYGUARD_DISABLE_UNREDACTED_NOTIFICATIONS);
final boolean allowed = allowedByUser && allowedByDpm;
mUsersAllowingPrivateNotifications.append(userHandle, allowed);
return allowed;
@@ -361,13 +361,13 @@
return mUsersAllowingPrivateNotifications.get(userHandle);
}
- private boolean adminAllowsUnredactedNotifications(int userHandle) {
+ private boolean adminAllowsKeyguardFeature(int userHandle, int feature) {
if (userHandle == UserHandle.USER_ALL) {
return true;
}
- final int dpmFlags = mDevicePolicyManager.getKeyguardDisabledFeatures(null /* admin */,
- userHandle);
- return (dpmFlags & DevicePolicyManager.KEYGUARD_DISABLE_UNREDACTED_NOTIFICATIONS) == 0;
+ final int dpmFlags =
+ mDevicePolicyManager.getKeyguardDisabledFeatures(null /* admin */, userHandle);
+ return (dpmFlags & feature) == 0;
}
/**
@@ -389,14 +389,17 @@
* "public" (secure & locked) mode?
*/
private boolean userAllowsNotificationsInPublic(int userHandle) {
- if (isCurrentProfile(userHandle)) {
+ if (isCurrentProfile(userHandle) && userHandle != mCurrentUserId) {
return true;
}
if (mUsersAllowingNotifications.indexOfKey(userHandle) < 0) {
- final boolean allowed = 0 != Settings.Secure.getIntForUser(
+ final boolean allowedByUser = 0 != Settings.Secure.getIntForUser(
mContext.getContentResolver(),
Settings.Secure.LOCK_SCREEN_SHOW_NOTIFICATIONS, 0, userHandle);
+ final boolean allowedByDpm = adminAllowsKeyguardFeature(userHandle,
+ DevicePolicyManager.KEYGUARD_DISABLE_SECURE_NOTIFICATIONS);
+ final boolean allowed = allowedByUser && allowedByDpm;
mUsersAllowingNotifications.append(userHandle, allowed);
return allowed;
}
@@ -428,7 +431,6 @@
Notification.VISIBILITY_PRIVATE;
}
-
private void updateCurrentProfilesCache() {
synchronized (mCurrentProfiles) {
mCurrentProfiles.clear();
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationViewHierarchyManager.java b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationViewHierarchyManager.java
index fd3a9d5e..1637849 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationViewHierarchyManager.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationViewHierarchyManager.java
@@ -323,8 +323,7 @@
boolean showOnKeyguard = mLockscreenUserManager.shouldShowOnKeyguard(entry
.notification);
if (suppressedSummary
- || (mLockscreenUserManager.isLockscreenPublicMode(userId)
- && !mLockscreenUserManager.shouldShowLockscreenNotifications())
+ || mLockscreenUserManager.shouldHideNotifications(userId)
|| (isLocked && !showOnKeyguard)) {
entry.row.setVisibility(View.GONE);
} else {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/StatusBarMobileView.java b/packages/SystemUI/src/com/android/systemui/statusbar/StatusBarMobileView.java
index f81671b..51b4239 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/StatusBarMobileView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/StatusBarMobileView.java
@@ -142,12 +142,14 @@
if (mState.strengthId != state.strengthId) {
mMobileDrawable.setLevel(state.strengthId);
}
- if (mState.typeId != state.typeId && state.typeId != 0) {
- mMobileType.setContentDescription(state.typeContentDescription);
- mMobileType.setImageResource(state.typeId);
- mMobileType.setVisibility(View.VISIBLE);
- } else {
- mMobileType.setVisibility(View.GONE);
+ if (mState.typeId != state.typeId) {
+ if (state.typeId != 0) {
+ mMobileType.setContentDescription(state.typeContentDescription);
+ mMobileType.setImageResource(state.typeId);
+ mMobileType.setVisibility(View.VISIBLE);
+ } else {
+ mMobileType.setVisibility(View.GONE);
+ }
}
mMobileRoaming.setVisibility(state.roaming ? View.VISIBLE : View.GONE);
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBouncer.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBouncer.java
index df2b817..60a3474 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBouncer.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBouncer.java
@@ -159,6 +159,11 @@
*/
public void onFullyShown() {
mFalsingManager.onBouncerShown();
+ if (mKeyguardView == null) {
+ Log.wtf(TAG, "onFullyShown when view was null");
+ } else {
+ mKeyguardView.onResume();
+ }
}
/**
@@ -180,7 +185,6 @@
@Override
public void run() {
mRoot.setVisibility(View.VISIBLE);
- mKeyguardView.onResume();
showPromptReason(mBouncerPromptReason);
final CharSequence customMessage = mCallback.consumeCustomMessage();
if (customMessage != null) {
@@ -296,7 +300,7 @@
public boolean isShowing() {
return (mShowingSoon || (mRoot != null && mRoot.getVisibility() == View.VISIBLE))
- && mExpansion == 0;
+ && mExpansion == 0 && !isAnimatingAway();
}
/**
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardDismissHandler.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardDismissHandler.java
new file mode 100644
index 0000000..759a0d1
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardDismissHandler.java
@@ -0,0 +1,29 @@
+/*
+ * 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.systemui.statusbar.phone;
+
+import android.annotation.Nullable;
+
+import com.android.keyguard.KeyguardHostView.OnDismissAction;
+
+
+/** Executes actions that require the screen to be unlocked. */
+public interface KeyguardDismissHandler {
+ /** Executes an action that requres the screen to be unlocked. */
+ void dismissKeyguardThenExecute(
+ OnDismissAction action, @Nullable Runnable cancelAction, boolean afterKeyguardGone);
+}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardDismissUtil.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardDismissUtil.java
new file mode 100644
index 0000000..c38b0b6
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardDismissUtil.java
@@ -0,0 +1,53 @@
+/*
+ * 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.systemui.statusbar.phone;
+
+import android.util.Log;
+
+import com.android.keyguard.KeyguardHostView.OnDismissAction;
+
+/**
+ * Executes actions that require the screen to be unlocked. Delegates the actual handling to an
+ * implementation passed via {@link #setDismissHandler}.
+ */
+public class KeyguardDismissUtil implements KeyguardDismissHandler {
+ private static final String TAG = "KeyguardDismissUtil";
+
+ private volatile KeyguardDismissHandler mDismissHandler;
+
+ /** Sets the actual {@link DismissHandler} implementation. */
+ public void setDismissHandler(KeyguardDismissHandler dismissHandler) {
+ mDismissHandler = dismissHandler;
+ }
+
+ /**
+ * Executes an action that requres the screen to be unlocked.
+ *
+ * <p>Must be called after {@link #setDismissHandler}.
+ */
+ @Override
+ public void dismissKeyguardThenExecute(
+ OnDismissAction action, Runnable cancelAction, boolean afterKeyguardGone) {
+ KeyguardDismissHandler dismissHandler = mDismissHandler;
+ if (dismissHandler == null) {
+ Log.wtf(TAG, "KeyguardDismissHandler not set.");
+ action.onDismiss();
+ return;
+ }
+ dismissHandler.dismissKeyguardThenExecute(action, cancelAction, afterKeyguardGone);
+ }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarView.java
index 9f75772..db2139d 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarView.java
@@ -39,7 +39,6 @@
import android.os.Handler;
import android.os.Message;
import android.os.SystemProperties;
-import android.os.VibrationEffect;
import android.support.annotation.ColorInt;
import android.util.AttributeSet;
import android.util.Log;
@@ -69,7 +68,6 @@
import com.android.systemui.shared.system.ActivityManagerWrapper;
import com.android.systemui.shared.system.NavigationBarCompat;
import com.android.systemui.stackdivider.Divider;
-import com.android.systemui.statusbar.VibratorHelper;
import com.android.systemui.statusbar.policy.DeadZone;
import com.android.systemui.statusbar.policy.KeyButtonDrawable;
import com.android.systemui.statusbar.policy.TintedKeyButtonDrawable;
@@ -150,7 +148,6 @@
private Divider mDivider;
private RecentsOnboarding mRecentsOnboarding;
private NotificationPanelView mPanelView;
- private final VibratorHelper mVibratorHelper;
private int mRotateBtnStyle = R.style.RotateButtonCCWStart90;
@@ -246,7 +243,6 @@
mOverviewProxyService = Dependency.get(OverviewProxyService.class);
mRecentsOnboarding = new RecentsOnboarding(context, mOverviewProxyService);
- mVibratorHelper = Dependency.get(VibratorHelper.class);
mConfiguration = new Configuration();
mConfiguration.updateFrom(context.getResources().getConfiguration());
@@ -314,9 +310,6 @@
} else if (mRecentsButtonBounds.contains(x, y)) {
mDownHitTarget = HIT_TARGET_OVERVIEW;
}
-
- // Vibrate tick whenever down occurs on navigation bar
- mVibratorHelper.vibrate(VibrationEffect.EFFECT_TICK);
break;
}
return mGestureHelper.onInterceptTouchEvent(event);
@@ -398,7 +391,7 @@
public boolean isQuickScrubEnabled() {
return SystemProperties.getBoolean("persist.quickstep.scrub.enabled", true)
- && mOverviewProxyService.getProxy() != null && isOverviewEnabled()
+ && mOverviewProxyService.isEnabled() && isOverviewEnabled()
&& ((mOverviewProxyService.getInteractionFlags() & FLAG_DISABLE_QUICK_SCRUB) == 0);
}
@@ -596,7 +589,7 @@
// recents buttons when disconnected from launcher service in screen pinning mode,
// as they are used for exiting.
final boolean pinningActive = ActivityManagerWrapper.getInstance().isScreenPinningActive();
- if (mOverviewProxyService.getProxy() != null) {
+ if (mOverviewProxyService.isEnabled()) {
// Use interaction flags to show/hide navigation buttons but will be shown if required
// to exit screen pinning.
final int flags = mOverviewProxyService.getInteractionFlags();
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationIconContainer.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationIconContainer.java
index 5517434..8c257fe 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationIconContainer.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationIconContainer.java
@@ -151,6 +151,7 @@
private ArrayMap<String, ArrayList<StatusBarIcon>> mReplacingIcons;
// Keep track of the last visible icon so collapsed container can report on its location
private IconState mLastVisibleIconState;
+ private IconState mFirstVisibleIconState;
private float mVisualOverflowStart;
// Keep track of overflow in range [0, 3]
private int mNumDots;
@@ -159,7 +160,6 @@
private int[] mAbsolutePosition = new int[2];
private View mIsolatedIconForAnimation;
-
public NotificationIconContainer(Context context, AttributeSet attrs) {
super(context, attrs);
initDimens();
@@ -192,10 +192,15 @@
paint.setColor(Color.BLUE);
canvas.drawLine(end, 0, end, height, paint);
- paint.setColor(Color.BLACK);
+ paint.setColor(Color.GREEN);
int lastIcon = (int) mLastVisibleIconState.xTranslation;
canvas.drawLine(lastIcon, 0, lastIcon, height, paint);
+ if (mFirstVisibleIconState != null) {
+ int firstIcon = (int) mFirstVisibleIconState.xTranslation;
+ canvas.drawLine(firstIcon, 0, firstIcon, height, paint);
+ }
+
paint.setColor(Color.RED);
canvas.drawLine(mVisualOverflowStart, 0, mVisualOverflowStart, height, paint);
@@ -210,6 +215,7 @@
super.onConfigurationChanged(newConfig);
initDimens();
}
+
@Override
protected void onLayout(boolean changed, int l, int t, int r, int b) {
float centerY = getHeight() / 2.0f;
@@ -364,11 +370,15 @@
float layoutEnd = getLayoutEnd();
float overflowStart = getMaxOverflowStart();
mVisualOverflowStart = 0;
+ mFirstVisibleIconState = null;
boolean hasAmbient = mSpeedBumpIndex != -1 && mSpeedBumpIndex < getChildCount();
for (int i = 0; i < childCount; i++) {
View view = getChildAt(i);
IconState iconState = mIconStates.get(view);
iconState.xTranslation = translationX;
+ if (mFirstVisibleIconState == null) {
+ mFirstVisibleIconState = iconState;
+ }
boolean forceOverflow = mSpeedBumpIndex != -1 && i >= mSpeedBumpIndex
&& iconState.iconAppearAmount > 0.0f || i >= maxVisibleIcons;
boolean noOverflowAfter = i == childCount - 1;
@@ -417,10 +427,16 @@
} else if (childCount > 0) {
View lastChild = getChildAt(childCount - 1);
mLastVisibleIconState = mIconStates.get(lastChild);
+ mFirstVisibleIconState = mIconStates.get(getChildAt(0));
}
boolean center = mDark;
if (center && translationX < getLayoutEnd()) {
- float delta = (getLayoutEnd() - translationX) / 2;
+ float initialTranslation =
+ mFirstVisibleIconState == null ? 0 : mFirstVisibleIconState.xTranslation;
+ float contentWidth = getFinalTranslationX() - initialTranslation;
+ float availableSpace = getLayoutEnd() - getActualPaddingStart();
+ float delta = (availableSpace - contentWidth) / 2;
+
if (firstOverflowIndex != -1) {
// If we have an overflow, only count those half for centering because the dots
// don't have a lot of visual weight.
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 27ca0d1..b7af84a 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java
@@ -659,6 +659,14 @@
expand(true /* animate */);
}
+ public void expandWithoutQs() {
+ if (isQsExpanded()) {
+ flingSettings(0 /* velocity */, false /* expand */);
+ } else {
+ expand(true /* animate */);
+ }
+ }
+
@Override
public void fling(float vel, boolean expand) {
GestureRecorder gr = ((PhoneStatusBarView) mBar).mBar.getGestureRecorder();
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/QuickStepController.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/QuickStepController.java
index 678d9d6..d3790d4 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/QuickStepController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/QuickStepController.java
@@ -172,8 +172,8 @@
}
private boolean handleTouchEvent(MotionEvent event) {
- if (!mNavigationBarView.isQuickScrubEnabled()
- && !mNavigationBarView.isQuickStepSwipeUpEnabled()) {
+ if (mOverviewEventSender.getProxy() == null || (!mNavigationBarView.isQuickScrubEnabled()
+ && !mNavigationBarView.isQuickStepSwipeUpEnabled())) {
mNavigationBarView.getHomeButton().setDelayTouchFeedback(false /* delay */);
return false;
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/ScrimController.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/ScrimController.java
index 28f3162..3dbac51 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/ScrimController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/ScrimController.java
@@ -68,8 +68,14 @@
private static final String TAG = "ScrimController";
private static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG);
+ /**
+ * General scrim animation duration.
+ */
public static final long ANIMATION_DURATION = 220;
-
+ /**
+ * Longer duration, currently only used when going to AOD.
+ */
+ public static final long ANIMATION_DURATION_LONG = 1000;
/**
* When both scrims have 0 alpha.
*/
@@ -85,7 +91,7 @@
/**
* Default alpha value for most scrims.
*/
- public static final float GRADIENT_SCRIM_ALPHA = 0.45f;
+ public static final float GRADIENT_SCRIM_ALPHA = 0.70f;
/**
* A scrim varies its opacity based on a busyness factor, for example
* how many notifications are currently visible.
@@ -389,7 +395,7 @@
// Darken scrim as you pull down the shade when unlocked
float behindFraction = getInterpolatedFraction();
behindFraction = (float) Math.pow(behindFraction, 0.8f);
- mCurrentBehindAlpha = behindFraction * mScrimBehindAlphaKeyguard;
+ mCurrentBehindAlpha = behindFraction * GRADIENT_SCRIM_ALPHA_BUSY;
mCurrentInFrontAlpha = 0;
} else if (mState == ScrimState.KEYGUARD) {
// Either darken of make the scrim transparent when you
@@ -528,8 +534,8 @@
if (alpha == 0f) {
scrim.setClickable(false);
} else {
- // Eat touch events (unless dozing).
- scrim.setClickable(!mState.isLowPowerState());
+ // Eat touch events (unless dozing or pulsing).
+ scrim.setClickable(mState != ScrimState.AOD && mState != ScrimState.PULSING);
}
updateScrim(scrim, alpha);
}
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 f4b6c38..d38c083 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/ScrimState.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/ScrimState.java
@@ -111,6 +111,7 @@
mCurrentInFrontAlpha = alwaysOnEnabled ? mAodFrontScrimAlpha : 1f;
mCurrentInFrontTint = Color.BLACK;
mCurrentBehindTint = Color.BLACK;
+ mAnimationDuration = ScrimController.ANIMATION_DURATION_LONG;
// DisplayPowerManager will blank the screen for us, we just need
// to set our state.
mAnimateChange = !mDisplayRequiresBlanking;
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 f7a97be..7987bfd 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java
@@ -213,6 +213,7 @@
import com.android.systemui.statusbar.notification.ActivityLaunchAnimator;
import com.android.systemui.statusbar.notification.VisualStabilityManager;
import com.android.systemui.statusbar.phone.UnlockMethodCache.OnUnlockMethodChangedListener;
+import com.android.systemui.statusbar.phone.KeyguardDismissUtil;
import com.android.systemui.statusbar.policy.BatteryController;
import com.android.systemui.statusbar.policy.BatteryController.BatteryStateChangeCallback;
import com.android.systemui.statusbar.policy.BrightnessMirrorController;
@@ -1300,6 +1301,8 @@
mKeyguardViewMediatorCallback = keyguardViewMediator.getViewMediatorCallback();
mLightBarController.setFingerprintUnlockController(mFingerprintUnlockController);
+ Dependency.get(KeyguardDismissUtil.class).setDismissHandler(
+ this::dismissKeyguardThenExecute);
Trace.endSection();
}
@@ -2047,11 +2050,19 @@
}
/**
+ * Decides if the status bar (clock + notifications + signal cluster) should be visible
+ * or not when showing the bouncer.
+ *
+ * We want to hide it when:
+ * • User swipes up on the keyguard
+ * • Locked activity that doesn't show a status bar requests the bouncer
+ *
* @param animate should the change of the icons be animated.
*/
private void updateHideIconsForBouncer(boolean animate) {
- boolean shouldHideIconsForBouncer = !mPanelExpanded && mTopHidesStatusBar && mIsOccluded
- && (mBouncerShowing || mStatusBarWindowHidden);
+ boolean hideBecauseApp = mTopHidesStatusBar && mIsOccluded;
+ boolean hideBecauseKeyguard = !mPanelExpanded && !mIsOccluded && mBouncerShowing;
+ boolean shouldHideIconsForBouncer = hideBecauseApp || hideBecauseKeyguard;
if (mHideIconsForBouncer != shouldHideIconsForBouncer) {
mHideIconsForBouncer = shouldHideIconsForBouncer;
if (!shouldHideIconsForBouncer && mBouncerWasShowingWhenHidden) {
@@ -2290,7 +2301,7 @@
return ;
}
- mNotificationPanel.expand(true /* animate */);
+ mNotificationPanel.expandWithoutQs();
if (false) postStartTracing();
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarIconControllerImpl.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarIconControllerImpl.java
index 510af03..b4e7575 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarIconControllerImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarIconControllerImpl.java
@@ -306,17 +306,6 @@
mIconGroups.forEach(l -> l.onSetIconHolder(viewIndex, holder));
}
- /**
- * For mobile essentially (an array of holders in one slot)
- */
- private void handleSet(int slotIndex, List<StatusBarIconHolder> holders) {
- for (StatusBarIconHolder holder : holders) {
- int viewIndex = getViewIndex(slotIndex, holder.getTag());
- mIconLogger.onIconVisibility(getSlotName(slotIndex), holder.isVisible());
- mIconGroups.forEach(l -> l.onSetIconHolder(viewIndex, holder));
- }
- }
-
@Override
public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
pw.println(TAG + " state:");
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java
index 6b6ea10..2727b30 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java
@@ -89,7 +89,6 @@
protected boolean mFirstUpdate = true;
protected boolean mLastShowing;
protected boolean mLastOccluded;
- private boolean mLastTracking;
private boolean mLastBouncerShowing;
private boolean mLastBouncerDismissible;
protected boolean mLastRemoteInputActive;
@@ -152,28 +151,19 @@
// • The user quickly taps on the display and we show "swipe up to unlock."
// • Keyguard will be dismissed by an action. a.k.a: FLAG_DISMISS_KEYGUARD_ACTIVITY
// • Full-screen user switcher is displayed.
- final boolean noLongerTracking = mLastTracking != tracking && !tracking;
if (mOccluded || mNotificationPanelView.isUnlockHintRunning()
|| mBouncer.willDismissWithAction()
|| mStatusBar.isFullScreenUserSwitcherState()) {
mBouncer.setExpansion(0);
} else if (mShowing && mStatusBar.isKeyguardCurrentlySecure() && !mDozing) {
mBouncer.setExpansion(expansion);
- if (expansion == 1) {
- mBouncer.onFullyHidden();
- } else if (!mBouncer.isShowing() && !mBouncer.isAnimatingAway()) {
+ if (expansion != 1 && tracking && !mBouncer.isShowing()
+ && !mBouncer.isAnimatingAway()) {
mBouncer.show(false /* resetSecuritySelection */, false /* animated */);
- } else if (noLongerTracking) {
- // Notify that falsing manager should stop its session when user stops touching,
- // even before the animation ends, to guarantee that we're not recording sensitive
- // data.
- mBouncer.onFullyShown();
- }
- if (expansion == 0 || expansion == 1) {
+ } else if (expansion == 0 || expansion == 1) {
updateStates();
}
}
- mLastTracking = tracking;
}
/**
@@ -595,6 +585,11 @@
if (bouncerShowing != mLastBouncerShowing || mFirstUpdate) {
mStatusBarWindowManager.setBouncerShowing(bouncerShowing);
mStatusBar.setBouncerShowing(bouncerShowing);
+ if (bouncerShowing) {
+ mBouncer.onFullyShown();
+ } else {
+ mBouncer.onFullyHidden();
+ }
}
KeyguardUpdateMonitor updateMonitor = KeyguardUpdateMonitor.getInstance(mContext);
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarSignalPolicy.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarSignalPolicy.java
index c5a3a0d..94ac4f62 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarSignalPolicy.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarSignalPolicy.java
@@ -414,7 +414,7 @@
@Override public String toString() {
return "MobileIconState(subId=" + subId + ", strengthId=" + strengthId + ", roaming="
- + roaming + ", visible=" + visible + ")";
+ + roaming + ", typeId=" + typeId + ", visible=" + visible + ")";
}
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/Clock.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/Clock.java
index 4c92d01..baeaaad 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/Clock.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/Clock.java
@@ -40,6 +40,7 @@
import android.view.View;
import android.widget.TextView;
+import com.android.settingslib.Utils;
import com.android.systemui.DemoMode;
import com.android.systemui.Dependency;
import com.android.systemui.FontSizeUtils;
@@ -84,6 +85,17 @@
private boolean mShowSeconds;
private Handler mSecondsHandler;
+ /**
+ * Whether we should use colors that adapt based on wallpaper/the scrim behind quick settings
+ * for text.
+ */
+ private boolean mUseWallpaperTextColor;
+
+ /**
+ * Color to be set on this {@link TextView}, when wallpaperTextColor is <b>not</b> utilized.
+ */
+ private int mNonAdaptedColor;
+
public Clock(Context context) {
this(context, null);
}
@@ -101,6 +113,7 @@
try {
mAmPmStyle = a.getInt(R.styleable.Clock_amPmStyle, AM_PM_STYLE_GONE);
mShowDark = a.getBoolean(R.styleable.Clock_showDark, true);
+ mNonAdaptedColor = getCurrentTextColor();
} finally {
a.recycle();
}
@@ -227,7 +240,10 @@
@Override
public void onDarkChanged(Rect area, float darkIntensity, int tint) {
- setTextColor(DarkIconDispatcher.getTint(area, this, tint));
+ mNonAdaptedColor = DarkIconDispatcher.getTint(area, this, tint);
+ if (!mUseWallpaperTextColor) {
+ setTextColor(mNonAdaptedColor);
+ }
}
@Override
@@ -242,6 +258,25 @@
0);
}
+ /**
+ * Sets whether the clock uses the wallpaperTextColor. If we're not using it, we'll revert back
+ * to dark-mode-based/tinted colors.
+ *
+ * @param shouldUseWallpaperTextColor whether we should use wallpaperTextColor for text color
+ */
+ public void useWallpaperTextColor(boolean shouldUseWallpaperTextColor) {
+ if (shouldUseWallpaperTextColor == mUseWallpaperTextColor) {
+ return;
+ }
+ mUseWallpaperTextColor = shouldUseWallpaperTextColor;
+
+ if (mUseWallpaperTextColor) {
+ setTextColor(Utils.getColorAttr(mContext, R.attr.wallpaperTextColor));
+ } else {
+ setTextColor(mNonAdaptedColor);
+ }
+ }
+
private void updateShowSeconds() {
if (mShowSeconds) {
// Wait until we have a display to start trying to show seconds.
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/DateView.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/DateView.java
index 74a30fa..ef630c7 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/DateView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/DateView.java
@@ -27,6 +27,7 @@
import android.util.AttributeSet;
import android.widget.TextView;
+import com.android.settingslib.Utils;
import com.android.systemui.Dependency;
import com.android.systemui.R;
@@ -42,6 +43,17 @@
private String mLastText;
private String mDatePattern;
+ /**
+ * Whether we should use colors that adapt based on wallpaper/the scrim behind quick settings
+ * for text.
+ */
+ private boolean mUseWallpaperTextColor;
+
+ /**
+ * Color to be set on this {@link TextView}, when wallpaperTextColor is <b>not</b> utilized.
+ */
+ private int mNonAdaptedTextColor;
+
private BroadcastReceiver mIntentReceiver = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
@@ -62,6 +74,7 @@
public DateView(Context context, AttributeSet attrs) {
super(context, attrs);
+ mNonAdaptedTextColor = getCurrentTextColor();
TypedArray a = context.getTheme().obtainStyledAttributes(
attrs,
R.styleable.DateView,
@@ -117,6 +130,25 @@
}
}
+ /**
+ * Sets whether the date view uses the wallpaperTextColor. If we're not using it, we'll revert
+ * back to dark-mode-based/tinted colors.
+ *
+ * @param shouldUseWallpaperTextColor whether we should use wallpaperTextColor for text color
+ */
+ public void useWallpaperTextColor(boolean shouldUseWallpaperTextColor) {
+ if (shouldUseWallpaperTextColor == mUseWallpaperTextColor) {
+ return;
+ }
+ mUseWallpaperTextColor = shouldUseWallpaperTextColor;
+
+ if (mUseWallpaperTextColor) {
+ setTextColor(Utils.getColorAttr(mContext, R.attr.wallpaperTextColor));
+ } else {
+ setTextColor(mNonAdaptedTextColor);
+ }
+ }
+
public void setDatePattern(String pattern) {
if (TextUtils.equals(pattern, mDatePattern)) {
return;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyButtonView.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyButtonView.java
index c7c18fa..1b02e15 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyButtonView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyButtonView.java
@@ -28,7 +28,6 @@
import android.os.AsyncTask;
import android.os.Bundle;
import android.os.SystemClock;
-import android.os.VibrationEffect;
import android.util.AttributeSet;
import android.util.TypedValue;
import android.view.HapticFeedbackConstants;
@@ -50,7 +49,6 @@
import com.android.systemui.R;
import com.android.systemui.plugins.statusbar.phone.NavBarButtonProvider.ButtonInterface;
import com.android.systemui.shared.system.ActivityManagerWrapper;
-import com.android.systemui.statusbar.VibratorHelper;
import static android.view.KeyEvent.KEYCODE_HOME;
import static android.view.accessibility.AccessibilityNodeInfo.ACTION_CLICK;
@@ -75,7 +73,6 @@
private OnClickListener mOnClickListener;
private final KeyButtonRipple mRipple;
private final OverviewProxyService mOverviewProxyService;
- private final VibratorHelper mVibratorHelper;
private final MetricsLogger mMetricsLogger = Dependency.get(MetricsLogger.class);
private final Runnable mCheckLongPress = new Runnable() {
@@ -121,7 +118,6 @@
mAudioManager = (AudioManager) context.getSystemService(Context.AUDIO_SERVICE);
mRipple = new KeyButtonRipple(context, this);
- mVibratorHelper = Dependency.get(VibratorHelper.class);
mOverviewProxyService = Dependency.get(OverviewProxyService.class);
setBackground(mRipple);
}
@@ -202,7 +198,7 @@
}
public boolean onTouchEvent(MotionEvent ev) {
- final boolean isProxyConnected = mOverviewProxyService.getProxy() != null;
+ final boolean showSwipeUI = mOverviewProxyService.shouldShowSwipeUpUI();
final int action = ev.getAction();
int x, y;
if (action == MotionEvent.ACTION_DOWN) {
@@ -228,7 +224,7 @@
// Provide the same haptic feedback that the system offers for virtual keys.
performHapticFeedback(HapticFeedbackConstants.VIRTUAL_KEY);
}
- if (!isProxyConnected) {
+ if (!showSwipeUI) {
playSoundEffect(SoundEffectConstants.CLICK);
}
removeCallbacks(mCheckLongPress);
@@ -260,11 +256,10 @@
final boolean doIt = isPressed() && !mLongClicked;
setPressed(false);
final boolean doHapticFeedback = (SystemClock.uptimeMillis() - mDownTime) > 150;
- if (isProxyConnected) {
+ if (showSwipeUI) {
if (doIt) {
- if (doHapticFeedback) {
- mVibratorHelper.vibrate(VibrationEffect.EFFECT_TICK);
- }
+ // Apply haptic feedback on touch up since there is none on touch down
+ performHapticFeedback(HapticFeedbackConstants.VIRTUAL_KEY);
playSoundEffect(SoundEffectConstants.CLICK);
}
} else if (doHapticFeedback && !mLongClicked) {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/SmartReplyView.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/SmartReplyView.java
index 790135f..74b3926 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/SmartReplyView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/SmartReplyView.java
@@ -20,8 +20,10 @@
import android.widget.Button;
import com.android.internal.annotations.VisibleForTesting;
+import com.android.keyguard.KeyguardHostView.OnDismissAction;
import com.android.systemui.Dependency;
import com.android.systemui.R;
+import com.android.systemui.statusbar.phone.KeyguardDismissUtil;
import java.text.BreakIterator;
import java.util.Comparator;
@@ -42,6 +44,7 @@
private static final int SQUEEZE_FAILED = -1;
private final SmartReplyConstants mConstants;
+ private final KeyguardDismissUtil mKeyguardDismissUtil;
/** Spacing to be applied between views. */
private final int mSpacing;
@@ -62,6 +65,7 @@
public SmartReplyView(Context context, AttributeSet attrs) {
super(context, attrs);
mConstants = Dependency.get(SmartReplyConstants.class);
+ mKeyguardDismissUtil = Dependency.get(KeyguardDismissUtil.class);
int spacing = 0;
int singleLineButtonPaddingHorizontal = 0;
@@ -126,12 +130,13 @@
}
@VisibleForTesting
- static Button inflateReplyButton(Context context, ViewGroup root, CharSequence choice,
+ Button inflateReplyButton(Context context, ViewGroup root, CharSequence choice,
RemoteInput remoteInput, PendingIntent pendingIntent) {
Button b = (Button) LayoutInflater.from(context).inflate(
R.layout.smart_reply_button, root, false);
b.setText(choice);
- b.setOnClickListener(view -> {
+
+ OnDismissAction action = () -> {
Bundle results = new Bundle();
results.putString(remoteInput.getResultKey(), choice.toString());
Intent intent = new Intent().addFlags(Intent.FLAG_RECEIVER_FOREGROUND);
@@ -142,6 +147,12 @@
} catch (PendingIntent.CanceledException e) {
Log.w(TAG, "Unable to send smart reply", e);
}
+ return false; // do not defer
+ };
+
+ b.setOnClickListener(view -> {
+ mKeyguardDismissUtil.dismissKeyguardThenExecute(
+ action, null /* cancelAction */, false /* afterKeyguardGone */);
});
return b;
}
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 375e860..d282f25 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/stack/NotificationStackScrollLayout.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/stack/NotificationStackScrollLayout.java
@@ -3023,6 +3023,11 @@
public void setAnimationsEnabled(boolean animationsEnabled) {
mAnimationsEnabled = animationsEnabled;
updateNotificationAnimationStates();
+ if (!animationsEnabled) {
+ mSwipedOutViews.clear();
+ mChildrenToRemoveAnimated.clear();
+ clearTemporaryViewsInGroup(this);
+ }
}
private void updateNotificationAnimationStates() {
@@ -3090,6 +3095,21 @@
@Override
public void changeViewPosition(View child, int newIndex) {
int currentIndex = indexOfChild(child);
+
+ if (currentIndex == -1) {
+ boolean isTransient = false;
+ if (child instanceof ExpandableNotificationRow
+ && ((ExpandableNotificationRow)child).getTransientContainer() != null) {
+ isTransient = true;
+ }
+ Log.e(TAG, "Attempting to re-position "
+ + (isTransient ? "transient" : "")
+ + " view {"
+ + child
+ + "}");
+ return;
+ }
+
if (child != null && child.getParent() == this && currentIndex != newIndex) {
mChangePositionInProgress = true;
((ExpandableView)child).setChangingPosition(true);
@@ -3569,17 +3589,17 @@
private void clearTemporaryViews() {
// lets make sure nothing is in the overlay / transient anymore
- clearTemporaryViews(this);
+ clearTemporaryViewsInGroup(this);
for (int i = 0; i < getChildCount(); i++) {
ExpandableView child = (ExpandableView) getChildAt(i);
if (child instanceof ExpandableNotificationRow) {
ExpandableNotificationRow row = (ExpandableNotificationRow) child;
- clearTemporaryViews(row.getChildrenContainer());
+ clearTemporaryViewsInGroup(row.getChildrenContainer());
}
}
}
- private void clearTemporaryViews(ViewGroup viewGroup) {
+ private void clearTemporaryViewsInGroup(ViewGroup viewGroup) {
while (viewGroup != null && viewGroup.getTransientViewCount() != 0) {
viewGroup.removeTransientView(viewGroup.getTransientView(0));
}
@@ -3922,12 +3942,11 @@
requestChildrenUpdate();
applyCurrentBackgroundBounds();
updateWillNotDraw();
- updateAntiBurnInTranslation();
notifyHeightChangeListener(mShelf);
}
private void updateAntiBurnInTranslation() {
- setTranslationX(mAmbientState.isDark() ? mAntiBurnInOffsetX : 0);
+ setTranslationX(mAntiBurnInOffsetX * mDarkAmount);
}
/**
@@ -3948,6 +3967,7 @@
updateContentHeight();
}
updateBackgroundDimming();
+ updateAntiBurnInTranslation();
}
public float getDarkAmount() {
diff --git a/packages/SystemUI/tests/src/com/android/systemui/SysuiBaseFragmentTest.java b/packages/SystemUI/tests/src/com/android/systemui/SysuiBaseFragmentTest.java
index 8905d72..b6335f3 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/SysuiBaseFragmentTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/SysuiBaseFragmentTest.java
@@ -21,6 +21,7 @@
import android.app.Instrumentation;
import android.support.test.InstrumentationRegistry;
import android.testing.BaseFragmentTest;
+import android.testing.DexmakerShareClassLoaderRule;
import com.android.systemui.utils.leaks.LeakCheckedTest;
import com.android.systemui.utils.leaks.LeakCheckedTest.SysuiLeakCheck;
@@ -36,6 +37,10 @@
@Rule
public final SysuiLeakCheck mLeakCheck = new SysuiLeakCheck();
+ @Rule
+ public final DexmakerShareClassLoaderRule mDexmakerShareClassLoaderRule =
+ new DexmakerShareClassLoaderRule();
+
protected final TestableDependency mDependency = new TestableDependency(mContext);
protected SysuiTestableContext mSysuiContext;
private Instrumentation mRealInstrumentation;
@@ -46,7 +51,6 @@
@Before
public void SysuiSetup() {
- System.setProperty("dexmaker.share_classloader", "true");
SystemUIFactory.createFromConfig(mContext);
// TODO: Figure out another way to give reference to a SysuiTestableContext.
mSysuiContext = (SysuiTestableContext) mContext;
diff --git a/packages/SystemUI/tests/src/com/android/systemui/SysuiTestCase.java b/packages/SystemUI/tests/src/com/android/systemui/SysuiTestCase.java
index 4c7c1d1..7475cd7 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/SysuiTestCase.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/SysuiTestCase.java
@@ -19,21 +19,18 @@
import static org.mockito.Mockito.when;
import android.app.Instrumentation;
-import android.content.Context;
import android.os.Handler;
import android.os.Looper;
import android.os.MessageQueue;
import android.os.ParcelFileDescriptor;
import android.support.test.InstrumentationRegistry;
-import android.support.test.filters.SmallTest;
+import android.testing.DexmakerShareClassLoaderRule;
import android.testing.LeakCheck;
import android.util.Log;
import org.junit.After;
import org.junit.Before;
import org.junit.Rule;
-import org.mockito.invocation.InvocationOnMock;
-import org.mockito.stubbing.Answer;
import java.io.FileInputStream;
import java.io.IOException;
@@ -51,12 +48,14 @@
@Rule
public SysuiTestableContext mContext = new SysuiTestableContext(
InstrumentationRegistry.getContext(), getLeakCheck());
+ @Rule
+ public final DexmakerShareClassLoaderRule mDexmakerShareClassLoaderRule =
+ new DexmakerShareClassLoaderRule();
public TestableDependency mDependency = new TestableDependency(mContext);
private Instrumentation mRealInstrumentation;
@Before
public void SysuiSetup() throws Exception {
- System.setProperty("dexmaker.share_classloader", "true");
mContext.setTheme(R.style.Theme_SystemUI);
SystemUIFactory.createFromConfig(mContext);
diff --git a/packages/SystemUI/tests/src/com/android/systemui/keyguard/KeyguardSliceProviderTest.java b/packages/SystemUI/tests/src/com/android/systemui/keyguard/KeyguardSliceProviderTest.java
index 5812da2..7d49c4d 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/keyguard/KeyguardSliceProviderTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/keyguard/KeyguardSliceProviderTest.java
@@ -44,6 +44,7 @@
import java.util.Arrays;
import java.util.concurrent.TimeUnit;
+import java.util.HashSet;
import androidx.slice.SliceItem;
import androidx.slice.SliceProvider;
@@ -66,7 +67,7 @@
MockitoAnnotations.initMocks(this);
mProvider = new TestableKeyguardSliceProvider();
mProvider.attachInfo(getContext(), null);
- SliceProvider.setSpecs(Arrays.asList(SliceSpecs.LIST));
+ SliceProvider.setSpecs(new HashSet<>(Arrays.asList(SliceSpecs.LIST)));
}
@Test
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/KeyguardBouncerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/KeyguardBouncerTest.java
index 67453d5..c6b6546 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/KeyguardBouncerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/KeyguardBouncerTest.java
@@ -167,11 +167,19 @@
@Test
public void testOnFullyShown_notifiesFalsingManager() {
+ mBouncer.ensureView();
mBouncer.onFullyShown();
verify(mFalsingManager).onBouncerShown();
}
@Test
+ public void testOnFullyShown_notifiesKeyguardView() {
+ mBouncer.ensureView();
+ mBouncer.onFullyShown();
+ verify(mKeyguardHostView).onResume();
+ }
+
+ @Test
public void testOnFullyHidden_notifiesFalsingManager() {
mBouncer.onFullyHidden();
verify(mFalsingManager).onBouncerHidden();
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/ScrimControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/ScrimControllerTest.java
index a88f31a..1e8e14d 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/ScrimControllerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/ScrimControllerTest.java
@@ -53,6 +53,8 @@
import org.junit.Test;
import org.junit.runner.RunWith;
+import java.util.Arrays;
+import java.util.HashSet;
import java.util.function.Consumer;
@RunWith(AndroidTestingRunner.class)
@@ -437,6 +439,22 @@
assertScrimVisibility(VISIBILITY_FULLY_TRANSPARENT, VISIBILITY_FULLY_OPAQUE);
}
+ @Test
+ public void testEatsTouchEvent() {
+ HashSet<ScrimState> eatsTouches =
+ new HashSet<>(Arrays.asList(ScrimState.AOD, ScrimState.PULSING));
+ for (ScrimState state : ScrimState.values()) {
+ if (state == ScrimState.UNINITIALIZED) {
+ continue;
+ }
+ mScrimController.transitionTo(state);
+ mScrimController.finishAnimationsImmediately();
+ Assert.assertEquals("Should be clickable unless AOD or PULSING, was: " + state,
+ mScrimBehind.getViewAlpha() != 0 && !eatsTouches.contains(state),
+ mScrimBehind.isClickable());
+ }
+ }
+
/**
* Conserves old notification density after leaving state and coming back.
*
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarTest.java
index b31a2dc..e68c7c8 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarTest.java
@@ -166,8 +166,8 @@
mMetricsLogger = new FakeMetricsLogger();
mDependency.injectTestDependency(MetricsLogger.class, mMetricsLogger);
- mNotificationLogger = new NotificationLogger();
mDependency.injectTestDependency(NotificationLogger.class, mNotificationLogger);
+ mNotificationLogger = new NotificationLogger();
IPowerManager powerManagerService = mock(IPowerManager.class);
HandlerThread handlerThread = new HandlerThread("TestThread");
@@ -524,9 +524,9 @@
mStatusBar.disable(StatusBarManager.DISABLE_NONE, StatusBarManager.DISABLE2_NONE, false);
verify(mNotificationPanelView).setQsExpansionEnabled(true);
mStatusBar.animateExpandNotificationsPanel();
- verify(mNotificationPanelView).expand(anyBoolean());
+ verify(mNotificationPanelView).expandWithoutQs();
mStatusBar.animateExpandSettingsPanel(null);
- verify(mNotificationPanelView).expand(anyBoolean());
+ verify(mNotificationPanelView).expandWithQs();
}
@Test
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/SmartReplyViewTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/SmartReplyViewTest.java
index a9b2c96..56882c6 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/SmartReplyViewTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/SmartReplyViewTest.java
@@ -18,6 +18,7 @@
import static junit.framework.Assert.assertEquals;
import static junit.framework.Assert.assertFalse;
+import static junit.framework.Assert.assertNull;
import static junit.framework.Assert.assertTrue;
import static junit.framework.Assert.fail;
@@ -34,8 +35,12 @@
import android.widget.Button;
import android.widget.LinearLayout;
+import com.android.keyguard.KeyguardHostView.OnDismissAction;
import com.android.systemui.R;
import com.android.systemui.SysuiTestCase;
+import com.android.systemui.statusbar.phone.KeyguardDismissUtil;
+
+import java.util.concurrent.atomic.AtomicReference;
import org.junit.After;
import org.junit.Before;
@@ -65,6 +70,8 @@
public void setUp() {
mReceiver = new BlockingQueueIntentReceiver();
mContext.registerReceiver(mReceiver, new IntentFilter(TEST_ACTION));
+ mDependency.get(KeyguardDismissUtil.class).setDismissHandler(
+ (action, cancelAction, afterKeyguardGone) -> action.onDismiss());
mView = SmartReplyView.inflate(mContext, null);
@@ -95,6 +102,42 @@
}
@Test
+ public void testSendSmartReply_keyguardCancelled() throws InterruptedException {
+ mDependency.get(KeyguardDismissUtil.class).setDismissHandler(
+ (action, cancelAction, afterKeyguardGone) -> {
+ if (cancelAction != null) {
+ cancelAction.run();
+ }
+ });
+ setRepliesFromRemoteInput(TEST_CHOICES);
+
+ mView.getChildAt(2).performClick();
+
+ assertNull(mReceiver.waitForIntent());
+ }
+
+ @Test
+ public void testSendSmartReply_waitsForKeyguard() throws InterruptedException {
+ AtomicReference<OnDismissAction> actionRef = new AtomicReference<>();
+ mDependency.get(KeyguardDismissUtil.class).setDismissHandler(
+ (action, cancelAction, afterKeyguardGone) -> actionRef.set(action));
+ setRepliesFromRemoteInput(TEST_CHOICES);
+
+ mView.getChildAt(2).performClick();
+
+ // No intent until the screen is unlocked.
+ assertNull(mReceiver.waitForIntent());
+
+ actionRef.get().onDismiss();
+
+ // Now the intent should arrive.
+ Intent resultIntent = mReceiver.waitForIntent();
+ assertEquals(TEST_CHOICES[2],
+ RemoteInput.getResultsFromIntent(resultIntent).get(TEST_RESULT_KEY));
+ assertEquals(RemoteInput.SOURCE_CHOICE, RemoteInput.getResultsSource(resultIntent));
+ }
+
+ @Test
public void testMeasure_empty() {
mView.measure(WIDTH_SPEC, HEIGHT_SPEC);
assertEquals(500, mView.getMeasuredWidthAndState());
@@ -301,7 +344,7 @@
Button previous = null;
for (CharSequence choice : choices) {
- Button current = SmartReplyView.inflateReplyButton(mContext, mView, choice, null, null);
+ Button current = mView.inflateReplyButton(mContext, mView, choice, null, null);
current.setPadding(paddingHorizontal, current.getPaddingTop(), paddingHorizontal,
current.getPaddingBottom());
if (previous != null) {
diff --git a/packages/overlays/DisplayCutoutEmulationCornerOverlay/res/values-land/config.xml b/packages/overlays/DisplayCutoutEmulationCornerOverlay/res/values-land/config.xml
new file mode 100644
index 0000000..bd52901
--- /dev/null
+++ b/packages/overlays/DisplayCutoutEmulationCornerOverlay/res/values-land/config.xml
@@ -0,0 +1,22 @@
+<!--
+ ~ 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>
+ <!-- Can't link to other dimensions here, but this should be status_bar_height_landscape -->
+ <dimen name="quick_qs_offset_height">28dp</dimen>
+ <!-- Total height of QQS in landscape; quick_qs_offset_height + 128 -->
+ <dimen name="quick_qs_total_height">156dp</dimen>
+</resources>
\ No newline at end of file
diff --git a/packages/overlays/DisplayCutoutEmulationDoubleOverlay/res/values-land/config.xml b/packages/overlays/DisplayCutoutEmulationDoubleOverlay/res/values-land/config.xml
new file mode 100644
index 0000000..bd52901
--- /dev/null
+++ b/packages/overlays/DisplayCutoutEmulationDoubleOverlay/res/values-land/config.xml
@@ -0,0 +1,22 @@
+<!--
+ ~ 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>
+ <!-- Can't link to other dimensions here, but this should be status_bar_height_landscape -->
+ <dimen name="quick_qs_offset_height">28dp</dimen>
+ <!-- Total height of QQS in landscape; quick_qs_offset_height + 128 -->
+ <dimen name="quick_qs_total_height">156dp</dimen>
+</resources>
\ No newline at end of file
diff --git a/packages/overlays/DisplayCutoutEmulationNarrowOverlay/res/values-land/config.xml b/packages/overlays/DisplayCutoutEmulationNarrowOverlay/res/values-land/config.xml
new file mode 100644
index 0000000..bd52901
--- /dev/null
+++ b/packages/overlays/DisplayCutoutEmulationNarrowOverlay/res/values-land/config.xml
@@ -0,0 +1,22 @@
+<!--
+ ~ 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>
+ <!-- Can't link to other dimensions here, but this should be status_bar_height_landscape -->
+ <dimen name="quick_qs_offset_height">28dp</dimen>
+ <!-- Total height of QQS in landscape; quick_qs_offset_height + 128 -->
+ <dimen name="quick_qs_total_height">156dp</dimen>
+</resources>
\ No newline at end of file
diff --git a/packages/overlays/DisplayCutoutEmulationTallOverlay/res/values-land/config.xml b/packages/overlays/DisplayCutoutEmulationTallOverlay/res/values-land/config.xml
new file mode 100644
index 0000000..bd52901
--- /dev/null
+++ b/packages/overlays/DisplayCutoutEmulationTallOverlay/res/values-land/config.xml
@@ -0,0 +1,22 @@
+<!--
+ ~ 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>
+ <!-- Can't link to other dimensions here, but this should be status_bar_height_landscape -->
+ <dimen name="quick_qs_offset_height">28dp</dimen>
+ <!-- Total height of QQS in landscape; quick_qs_offset_height + 128 -->
+ <dimen name="quick_qs_total_height">156dp</dimen>
+</resources>
\ No newline at end of file
diff --git a/packages/overlays/DisplayCutoutEmulationWideOverlay/res/values-land/config.xml b/packages/overlays/DisplayCutoutEmulationWideOverlay/res/values-land/config.xml
new file mode 100644
index 0000000..bd52901
--- /dev/null
+++ b/packages/overlays/DisplayCutoutEmulationWideOverlay/res/values-land/config.xml
@@ -0,0 +1,22 @@
+<!--
+ ~ 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>
+ <!-- Can't link to other dimensions here, but this should be status_bar_height_landscape -->
+ <dimen name="quick_qs_offset_height">28dp</dimen>
+ <!-- Total height of QQS in landscape; quick_qs_offset_height + 128 -->
+ <dimen name="quick_qs_total_height">156dp</dimen>
+</resources>
\ No newline at end of file
diff --git a/proto/src/metrics_constants.proto b/proto/src/metrics_constants.proto
index c66c7b0..a3dcd45 100644
--- a/proto/src/metrics_constants.proto
+++ b/proto/src/metrics_constants.proto
@@ -5572,6 +5572,12 @@
// OS: P
ACTION_SETTINGS_SLICE_CHANGED = 1372;
+ // OPEN: Settings > Network & Internet > Wi-Fi > Wi-Fi Preferences > Turn on Wi-Fi automatically
+ // note: Wifi Scanning must be off for this dialog to show
+ // CATEGORY: SETTINGS
+ // OS: P
+ WIFI_SCANNING_NEEDED_DIALOG = 1373;
+
// ---- End P Constants, all P constants go above this line ----
// Add new aosp constants above this line.
// END OF AOSP CONSTANTS
diff --git a/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java b/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java
index 3ee85b9..08aa063 100644
--- a/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java
+++ b/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java
@@ -2721,7 +2721,7 @@
}
}
- private AccessibilityWindowInfo populateReportedWindow(WindowInfo window) {
+ private AccessibilityWindowInfo populateReportedWindowLocked(WindowInfo window) {
final int windowId = findWindowIdLocked(window.token);
if (windowId < 0) {
return null;
@@ -3140,10 +3140,14 @@
mAccessibilityFocusedWindowId != INVALID_WINDOW_ID;
if (windowCount > 0) {
for (int i = 0; i < windowCount; i++) {
- WindowInfo windowInfo = windows.get(i);
- AccessibilityWindowInfo window = (mWindowsForAccessibilityCallback != null)
- ? mWindowsForAccessibilityCallback.populateReportedWindow(windowInfo)
- : null;
+ final WindowInfo windowInfo = windows.get(i);
+ final AccessibilityWindowInfo window;
+ if (mWindowsForAccessibilityCallback != null) {
+ window = mWindowsForAccessibilityCallback
+ .populateReportedWindowLocked(windowInfo);
+ } else {
+ window = null;
+ }
if (window != null) {
// Flip layers in list to be consistent with AccessibilityService#getWindows
@@ -3173,7 +3177,7 @@
// active window once we decided which it is.
final int accessibilityWindowCount = mWindows.size();
for (int i = 0; i < accessibilityWindowCount; i++) {
- AccessibilityWindowInfo window = mWindows.get(i);
+ final AccessibilityWindowInfo window = mWindows.get(i);
if (window.getId() == mActiveWindowId) {
window.setActive(true);
}
@@ -3192,7 +3196,10 @@
}
if (shouldClearAccessibilityFocus) {
- clearAccessibilityFocus(mAccessibilityFocusedWindowId);
+ mMainHandler.sendMessage(obtainMessage(
+ AccessibilityManagerService::clearAccessibilityFocus,
+ AccessibilityManagerService.this,
+ box(mAccessibilityFocusedWindowId)));
}
}
diff --git a/services/autofill/java/com/android/server/autofill/Session.java b/services/autofill/java/com/android/server/autofill/Session.java
index e14584f..e20c180 100644
--- a/services/autofill/java/com/android/server/autofill/Session.java
+++ b/services/autofill/java/com/android/server/autofill/Session.java
@@ -1400,6 +1400,7 @@
* the current values of all fields in the screen.
*/
if (saveInfo == null) {
+ if (sVerbose) Slog.w(TAG, "showSaveLocked(): no saveInfo from service");
return true;
}
diff --git a/services/autofill/java/com/android/server/autofill/ui/FillUi.java b/services/autofill/java/com/android/server/autofill/ui/FillUi.java
index 7c0671f..d29ca05 100644
--- a/services/autofill/java/com/android/server/autofill/ui/FillUi.java
+++ b/services/autofill/java/com/android/server/autofill/ui/FillUi.java
@@ -656,6 +656,8 @@
private final WindowManager mWm;
private final View mContentView;
private boolean mShowing;
+ // Used on dump only
+ private WindowManager.LayoutParams mShowParams;
/**
* Constructor.
@@ -672,16 +674,13 @@
* Shows the window.
*/
public void show(WindowManager.LayoutParams params) {
+ mShowParams = params;
if (sVerbose) {
Slog.v(TAG, "show(): showing=" + mShowing + ", params=" + paramsToString(params));
}
try {
- // Okay here is a bit of voodoo - we want to show the window as system
- // controlled one so it covers app windows - adjust the params accordingly.
- params.type = WindowManager.LayoutParams.TYPE_SYSTEM_DIALOG;
- params.token = null;
params.packageName = "android";
- params.flags |= WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN;
+ params.setTitle("Autofill UI"); // Title is set for debugging purposes
if (!mShowing) {
params.accessibilityTitle = mContentView.getContext()
.getString(R.string.autofill_picker_accessibility_title);
@@ -760,6 +759,9 @@
pw.println();
pw.print(prefix2); pw.print("showing: "); pw.println(mWindow.mShowing);
pw.print(prefix2); pw.print("view: "); pw.println(mWindow.mContentView);
+ if (mWindow.mShowParams != null) {
+ pw.print(prefix2); pw.print("params: "); pw.println(mWindow.mShowParams);
+ }
pw.print(prefix2); pw.print("screen coordinates: ");
if (mWindow.mContentView == null) {
pw.println("N/A");
diff --git a/services/backup/java/com/android/server/backup/transport/TransportClient.java b/services/backup/java/com/android/server/backup/transport/TransportClient.java
index fa881a9..e4dcb25 100644
--- a/services/backup/java/com/android/server/backup/transport/TransportClient.java
+++ b/services/backup/java/com/android/server/backup/transport/TransportClient.java
@@ -439,8 +439,17 @@
synchronized (mStateLock) {
log(Priority.ERROR, "Service disconnected: client UNUSABLE");
setStateLocked(State.UNUSABLE, null);
- // After unbindService() no calls back to mConnection
- mContext.unbindService(mConnection);
+ try {
+ // After unbindService() no calls back to mConnection
+ mContext.unbindService(mConnection);
+ } catch (IllegalArgumentException e) {
+ // TODO: Investigate why this is happening
+ // We're UNUSABLE, so any calls to mConnection will be no-op, so it's safe to
+ // swallow this one
+ log(
+ Priority.WARN,
+ "Exception trying to unbind onServiceDisconnected(): " + e.getMessage());
+ }
}
}
diff --git a/services/core/java/com/android/server/ConnectivityService.java b/services/core/java/com/android/server/ConnectivityService.java
index a1ef1ed..59cb135 100644
--- a/services/core/java/com/android/server/ConnectivityService.java
+++ b/services/core/java/com/android/server/ConnectivityService.java
@@ -934,7 +934,7 @@
// Used only for testing.
// TODO: Delete this and either:
- // 1. Give Fake SettingsProvider the ability to send settings change notifications (requires
+ // 1. Give FakeSettingsProvider the ability to send settings change notifications (requires
// changing ContentResolver to make registerContentObserver non-final).
// 2. Give FakeSettingsProvider an alternative notification mechanism and have the test use it
// by subclassing SettingsObserver.
@@ -943,6 +943,12 @@
mHandler.sendEmptyMessage(EVENT_CONFIGURE_MOBILE_DATA_ALWAYS_ON);
}
+ // See FakeSettingsProvider comment above.
+ @VisibleForTesting
+ void updatePrivateDnsSettings() {
+ mHandler.sendEmptyMessage(EVENT_PRIVATE_DNS_SETTINGS_CHANGED);
+ }
+
private void handleMobileDataAlwaysOn() {
final boolean enable = toBool(Settings.Global.getInt(
mContext.getContentResolver(), Settings.Global.MOBILE_DATA_ALWAYS_ON, 1));
@@ -972,8 +978,8 @@
}
private void registerPrivateDnsSettingsCallbacks() {
- for (Uri u : DnsManager.getPrivateDnsSettingsUris()) {
- mSettingsObserver.observe(u, EVENT_PRIVATE_DNS_SETTINGS_CHANGED);
+ for (Uri uri : DnsManager.getPrivateDnsSettingsUris()) {
+ mSettingsObserver.observe(uri, EVENT_PRIVATE_DNS_SETTINGS_CHANGED);
}
}
@@ -1026,8 +1032,12 @@
if (network == null) {
return null;
}
+ return getNetworkAgentInfoForNetId(network.netId);
+ }
+
+ private NetworkAgentInfo getNetworkAgentInfoForNetId(int netId) {
synchronized (mNetworkForNetId) {
- return mNetworkForNetId.get(network.netId);
+ return mNetworkForNetId.get(netId);
}
}
@@ -1167,9 +1177,7 @@
}
NetworkAgentInfo nai;
if (vpnNetId != NETID_UNSET) {
- synchronized (mNetworkForNetId) {
- nai = mNetworkForNetId.get(vpnNetId);
- }
+ nai = getNetworkAgentInfoForNetId(vpnNetId);
if (nai != null) return nai.network;
}
nai = getDefaultNetwork();
@@ -2155,41 +2163,21 @@
default:
return false;
case NetworkMonitor.EVENT_NETWORK_TESTED: {
- final NetworkAgentInfo nai;
- synchronized (mNetworkForNetId) {
- nai = mNetworkForNetId.get(msg.arg2);
- }
+ final NetworkAgentInfo nai = getNetworkAgentInfoForNetId(msg.arg2);
if (nai == null) break;
final boolean valid = (msg.arg1 == NetworkMonitor.NETWORK_TEST_RESULT_VALID);
final boolean wasValidated = nai.lastValidated;
final boolean wasDefault = isDefaultNetwork(nai);
- final PrivateDnsConfig privateDnsCfg = (msg.obj instanceof PrivateDnsConfig)
- ? (PrivateDnsConfig) msg.obj : null;
final String redirectUrl = (msg.obj instanceof String) ? (String) msg.obj : "";
- final boolean reevaluationRequired;
- final String logMsg;
- if (valid) {
- reevaluationRequired = updatePrivateDns(nai, privateDnsCfg);
- logMsg = (DBG && (privateDnsCfg != null))
- ? " with " + privateDnsCfg.toString() : "";
- } else {
- reevaluationRequired = false;
- logMsg = (DBG && !TextUtils.isEmpty(redirectUrl))
- ? " with redirect to " + redirectUrl : "";
- }
if (DBG) {
+ final String logMsg = !TextUtils.isEmpty(redirectUrl)
+ ? " with redirect to " + redirectUrl
+ : "";
log(nai.name() + " validation " + (valid ? "passed" : "failed") + logMsg);
}
- // If there is a change in Private DNS configuration,
- // trigger reevaluation of the network to test it.
- if (reevaluationRequired) {
- nai.networkMonitor.sendMessage(
- NetworkMonitor.CMD_FORCE_REEVALUATION, Process.SYSTEM_UID);
- break;
- }
if (valid != nai.lastValidated) {
if (wasDefault) {
metricsLogger().defaultNetworkMetrics().logDefaultNetworkValidity(
@@ -2218,10 +2206,7 @@
case NetworkMonitor.EVENT_PROVISIONING_NOTIFICATION: {
final int netId = msg.arg2;
final boolean visible = toBool(msg.arg1);
- final NetworkAgentInfo nai;
- synchronized (mNetworkForNetId) {
- nai = mNetworkForNetId.get(netId);
- }
+ final NetworkAgentInfo nai = getNetworkAgentInfoForNetId(netId);
// If captive portal status has changed, update capabilities or disconnect.
if (nai != null && (visible != nai.lastCaptivePortalDetected)) {
final int oldScore = nai.getCurrentScore();
@@ -2252,18 +2237,10 @@
break;
}
case NetworkMonitor.EVENT_PRIVATE_DNS_CONFIG_RESOLVED: {
- final NetworkAgentInfo nai;
- synchronized (mNetworkForNetId) {
- nai = mNetworkForNetId.get(msg.arg2);
- }
+ final NetworkAgentInfo nai = getNetworkAgentInfoForNetId(msg.arg2);
if (nai == null) break;
- final PrivateDnsConfig cfg = (PrivateDnsConfig) msg.obj;
- final boolean reevaluationRequired = updatePrivateDns(nai, cfg);
- if (nai.lastValidated && reevaluationRequired) {
- nai.networkMonitor.sendMessage(
- NetworkMonitor.CMD_FORCE_REEVALUATION, Process.SYSTEM_UID);
- }
+ updatePrivateDns(nai, (PrivateDnsConfig) msg.obj);
break;
}
}
@@ -2301,61 +2278,38 @@
}
}
+ private boolean networkRequiresValidation(NetworkAgentInfo nai) {
+ return NetworkMonitor.isValidationRequired(
+ mDefaultRequest.networkCapabilities, nai.networkCapabilities);
+ }
+
private void handlePrivateDnsSettingsChanged() {
final PrivateDnsConfig cfg = mDnsManager.getPrivateDnsConfig();
for (NetworkAgentInfo nai : mNetworkAgentInfos.values()) {
- // Private DNS only ever applies to networks that might provide
- // Internet access and therefore also require validation.
- if (!NetworkMonitor.isValidationRequired(
- mDefaultRequest.networkCapabilities, nai.networkCapabilities)) {
- continue;
- }
-
- // Notify the NetworkMonitor thread in case it needs to cancel or
- // schedule DNS resolutions. If a DNS resolution is required the
- // result will be sent back to us.
- nai.networkMonitor.notifyPrivateDnsSettingsChanged(cfg);
-
- if (!cfg.inStrictMode()) {
- // No strict mode hostname DNS resolution needed, so just update
- // DNS settings directly. In opportunistic and "off" modes this
- // just reprograms netd with the network-supplied DNS servers
- // (and of course the boolean of whether or not to attempt TLS).
- //
- // TODO: Consider code flow parity with strict mode, i.e. having
- // NetworkMonitor relay the PrivateDnsConfig back to us and then
- // performing this call at that time.
- updatePrivateDns(nai, cfg);
- }
+ handlePerNetworkPrivateDnsConfig(nai, cfg);
}
}
- private boolean updatePrivateDns(NetworkAgentInfo nai, PrivateDnsConfig newCfg) {
- final boolean reevaluationRequired = true;
- final boolean dontReevaluate = false;
+ private void handlePerNetworkPrivateDnsConfig(NetworkAgentInfo nai, PrivateDnsConfig cfg) {
+ // Private DNS only ever applies to networks that might provide
+ // Internet access and therefore also require validation.
+ if (!networkRequiresValidation(nai)) return;
- final PrivateDnsConfig oldCfg = mDnsManager.updatePrivateDns(nai.network, newCfg);
+ // Notify the NetworkMonitor thread in case it needs to cancel or
+ // schedule DNS resolutions. If a DNS resolution is required the
+ // result will be sent back to us.
+ nai.networkMonitor.notifyPrivateDnsSettingsChanged(cfg);
+
+ // With Private DNS bypass support, we can proceed to update the
+ // Private DNS config immediately, even if we're in strict mode
+ // and have not yet resolved the provider name into a set of IPs.
+ updatePrivateDns(nai, cfg);
+ }
+
+ private void updatePrivateDns(NetworkAgentInfo nai, PrivateDnsConfig newCfg) {
+ mDnsManager.updatePrivateDns(nai.network, newCfg);
updateDnses(nai.linkProperties, null, nai.network.netId);
-
- if (newCfg == null) {
- if (oldCfg == null) return dontReevaluate;
- return oldCfg.useTls ? reevaluationRequired : dontReevaluate;
- }
-
- if (oldCfg == null) {
- return newCfg.useTls ? reevaluationRequired : dontReevaluate;
- }
-
- if (oldCfg.useTls != newCfg.useTls) {
- return reevaluationRequired;
- }
-
- if (newCfg.inStrictMode() && !Objects.equals(oldCfg.hostname, newCfg.hostname)) {
- return reevaluationRequired;
- }
-
- return dontReevaluate;
}
private void updateLingerState(NetworkAgentInfo nai, long now) {
@@ -3300,7 +3254,7 @@
if (isNetworkWithLinkPropertiesBlocked(lp, uid, false)) {
return;
}
- nai.networkMonitor.sendMessage(NetworkMonitor.CMD_FORCE_REEVALUATION, uid);
+ nai.networkMonitor.forceReevaluation(uid);
}
private ProxyInfo getDefaultProxy() {
@@ -4919,7 +4873,7 @@
}
public void handleUpdateLinkProperties(NetworkAgentInfo nai, LinkProperties newLp) {
- if (mNetworkForNetId.get(nai.network.netId) != nai) {
+ if (getNetworkAgentInfoForNetId(nai.network.netId) != nai) {
// Ignore updates for disconnected networks
return;
}
@@ -5495,6 +5449,7 @@
if (!networkAgent.everConnected && state == NetworkInfo.State.CONNECTED) {
networkAgent.everConnected = true;
+ handlePerNetworkPrivateDnsConfig(networkAgent, mDnsManager.getPrivateDnsConfig());
updateLinkProperties(networkAgent, null);
notifyIfacesChangedForNetworkStats();
@@ -5911,4 +5866,4 @@
pw.println(" Get airplane mode.");
}
}
-}
\ No newline at end of file
+}
diff --git a/services/core/java/com/android/server/InputMethodManagerService.java b/services/core/java/com/android/server/InputMethodManagerService.java
index 40f9476..f678eed 100644
--- a/services/core/java/com/android/server/InputMethodManagerService.java
+++ b/services/core/java/com/android/server/InputMethodManagerService.java
@@ -263,17 +263,19 @@
private static final class DebugFlag {
private static final Object LOCK = new Object();
private final String mKey;
+ private final boolean mDefaultValue;
@GuardedBy("LOCK")
private boolean mValue;
public DebugFlag(String key, boolean defaultValue) {
mKey = key;
+ mDefaultValue = defaultValue;
mValue = SystemProperties.getBoolean(key, defaultValue);
}
void refresh() {
synchronized (LOCK) {
- mValue = SystemProperties.getBoolean(mKey, true);
+ mValue = SystemProperties.getBoolean(mKey, mDefaultValue);
}
}
diff --git a/services/core/java/com/android/server/LockGuard.java b/services/core/java/com/android/server/LockGuard.java
index b744917..5ce16c4 100644
--- a/services/core/java/com/android/server/LockGuard.java
+++ b/services/core/java/com/android/server/LockGuard.java
@@ -16,10 +16,14 @@
package com.android.server;
+import android.annotation.Nullable;
+import android.text.TextUtils;
import android.util.ArrayMap;
import android.util.ArraySet;
import android.util.Slog;
+import com.android.internal.os.BackgroundThread;
+
import java.io.FileDescriptor;
import java.io.PrintWriter;
@@ -60,8 +64,6 @@
public class LockGuard {
private static final String TAG = "LockGuard";
- public static final boolean ENABLED = false;
-
/**
* Well-known locks ordered by fixed index. Locks with a specific index
* should never be acquired while holding a lock of a lower index.
@@ -73,8 +75,9 @@
public static final int INDEX_STORAGE = 4;
public static final int INDEX_WINDOW = 5;
public static final int INDEX_ACTIVITY = 6;
+ public static final int INDEX_DPMS = 7;
- private static Object[] sKnownFixed = new Object[INDEX_ACTIVITY + 1];
+ private static Object[] sKnownFixed = new Object[INDEX_DPMS + 1];
private static ArrayMap<Object, LockInfo> sKnown = new ArrayMap<>(0, true);
@@ -84,6 +87,9 @@
/** Child locks that can be acquired while this lock is already held */
public ArraySet<Object> children = new ArraySet<>(0, true);
+
+ /** If true, do wtf instead of a warning log. */
+ public boolean doWtf;
}
private static LockInfo findOrCreateLockInfo(Object lock) {
@@ -114,9 +120,9 @@
if (child == null) continue;
if (Thread.holdsLock(child)) {
- Slog.w(TAG, "Calling thread " + Thread.currentThread().getName() + " is holding "
- + lockToString(child) + " while trying to acquire "
- + lockToString(lock), new Throwable());
+ doLog(lock, "Calling thread " + Thread.currentThread().getName()
+ + " is holding " + lockToString(child) + " while trying to acquire "
+ + lockToString(lock));
triggered = true;
}
}
@@ -145,13 +151,30 @@
for (int i = 0; i < index; i++) {
final Object lock = sKnownFixed[i];
if (lock != null && Thread.holdsLock(lock)) {
- Slog.w(TAG, "Calling thread " + Thread.currentThread().getName() + " is holding "
- + lockToString(i) + " while trying to acquire "
- + lockToString(index), new Throwable());
+
+ // Note in this case sKnownFixed may not contain a lock at the given index,
+ // which is okay and in that case we just don't do a WTF.
+ final Object targetMayBeNull = sKnownFixed[index];
+ doLog(targetMayBeNull, "Calling thread " + Thread.currentThread().getName()
+ + " is holding " + lockToString(i) + " while trying to acquire "
+ + lockToString(index));
}
}
}
+ private static void doLog(@Nullable Object lock, String message) {
+ if (lock != null && findOrCreateLockInfo(lock).doWtf) {
+
+ // Don't want to call into ActivityManager with any lock held, so let's just call it
+ // from a new thread. We don't want to use known threads (e.g. BackgroundThread) either
+ // because they may be stuck too.
+ final Throwable stackTrace = new RuntimeException(message);
+ new Thread(() -> Slog.wtf(TAG, stackTrace)).start();
+ return;
+ }
+ Slog.w(TAG, message, new Throwable());
+ }
+
/**
* Report the given lock with a well-known label.
*/
@@ -165,19 +188,33 @@
* Report the given lock with a well-known index.
*/
public static Object installLock(Object lock, int index) {
+ return installLock(lock, index, /*doWtf=*/ false);
+ }
+
+ /**
+ * Report the given lock with a well-known index.
+ */
+ public static Object installLock(Object lock, int index, boolean doWtf) {
sKnownFixed[index] = lock;
+ final LockInfo info = findOrCreateLockInfo(lock);
+ info.doWtf = doWtf;
+ info.label = "Lock-" + lockToString(index);
return lock;
}
public static Object installNewLock(int index) {
+ return installNewLock(index, /*doWtf=*/ false);
+ }
+
+ public static Object installNewLock(int index, boolean doWtf) {
final Object lock = new Object();
- installLock(lock, index);
+ installLock(lock, index, doWtf);
return lock;
}
private static String lockToString(Object lock) {
final LockInfo info = sKnown.get(lock);
- if (info != null) {
+ if (info != null && !TextUtils.isEmpty(info.label)) {
return info.label;
} else {
return "0x" + Integer.toHexString(System.identityHashCode(lock));
@@ -193,6 +230,7 @@
case INDEX_STORAGE: return "STORAGE";
case INDEX_WINDOW: return "WINDOW";
case INDEX_ACTIVITY: return "ACTIVITY";
+ case INDEX_DPMS: return "DPMS";
default: return Integer.toString(index);
}
}
diff --git a/services/core/java/com/android/server/ThreadPriorityBooster.java b/services/core/java/com/android/server/ThreadPriorityBooster.java
index cc9ac0d..53e8ce4 100644
--- a/services/core/java/com/android/server/ThreadPriorityBooster.java
+++ b/services/core/java/com/android/server/ThreadPriorityBooster.java
@@ -25,6 +25,8 @@
*/
public class ThreadPriorityBooster {
+ private static final boolean ENABLE_LOCK_GUARD = false;
+
private volatile int mBoostToPriority;
private final int mLockGuardIndex;
@@ -50,7 +52,7 @@
}
}
state.regionCounter++;
- if (LockGuard.ENABLED) {
+ if (ENABLE_LOCK_GUARD) {
LockGuard.guard(mLockGuardIndex);
}
}
diff --git a/services/core/java/com/android/server/am/ActiveServices.java b/services/core/java/com/android/server/am/ActiveServices.java
index f57e9ac..067566d 100644
--- a/services/core/java/com/android/server/am/ActiveServices.java
+++ b/services/core/java/com/android/server/am/ActiveServices.java
@@ -2283,7 +2283,7 @@
+ " app=" + app);
if (app != null && app.thread != null) {
try {
- app.addPackage(r.appInfo.packageName, r.appInfo.versionCode, mAm.mProcessStats);
+ app.addPackage(r.appInfo.packageName, r.appInfo.longVersionCode, mAm.mProcessStats);
realStartServiceLocked(r, app, execInFg);
return null;
} catch (TransactionTooLargeException e) {
@@ -2645,6 +2645,8 @@
Message msg = mAm.mHandler.obtainMessage(
ActivityManagerService.SERVICE_FOREGROUND_CRASH_MSG);
msg.obj = r.app;
+ msg.getData().putCharSequence(
+ ActivityManagerService.SERVICE_RECORD_KEY, r.toString());
mAm.mHandler.sendMessage(msg);
}
}
@@ -3009,7 +3011,7 @@
mPendingServices.remove(i);
i--;
- proc.addPackage(sr.appInfo.packageName, sr.appInfo.versionCode,
+ proc.addPackage(sr.appInfo.packageName, sr.appInfo.longVersionCode,
mAm.mProcessStats);
realStartServiceLocked(sr, proc, sr.createdFromFg);
didSomething = true;
@@ -3563,13 +3565,15 @@
if (app != null) {
mAm.mAppErrors.appNotResponding(app, null, null, false,
- "Context.startForegroundService() did not then call Service.startForeground()");
+ "Context.startForegroundService() did not then call Service.startForeground(): "
+ + r);
}
}
- void serviceForegroundCrash(ProcessRecord app) {
+ void serviceForegroundCrash(ProcessRecord app, CharSequence serviceRecord) {
mAm.crashApplication(app.uid, app.pid, app.info.packageName, app.userId,
- "Context.startForegroundService() did not then call Service.startForeground()");
+ "Context.startForegroundService() did not then call Service.startForeground(): "
+ + serviceRecord);
}
void scheduleServiceTimeoutLocked(ProcessRecord proc) {
diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java
index db52b97..adf3480 100644
--- a/services/core/java/com/android/server/am/ActivityManagerService.java
+++ b/services/core/java/com/android/server/am/ActivityManagerService.java
@@ -27,6 +27,7 @@
import static android.Manifest.permission.READ_FRAME_BUFFER;
import static android.Manifest.permission.REMOVE_TASKS;
import static android.Manifest.permission.START_TASKS_FROM_RECENTS;
+import static android.Manifest.permission.STOP_APP_SWITCHES;
import static android.app.ActivityManager.LOCK_TASK_MODE_NONE;
import static android.app.ActivityManager.RESIZE_MODE_PRESERVE_WINDOW;
import static android.app.ActivityManager.SPLIT_SCREEN_CREATE_MODE_TOP_OR_LEFT;
@@ -1919,6 +1920,8 @@
static final int FIRST_COMPAT_MODE_MSG = 300;
static final int FIRST_SUPERVISOR_STACK_MSG = 100;
+ static final String SERVICE_RECORD_KEY = "servicerecord";
+
static ServiceThread sKillThread = null;
static KillHandler sKillHandler = null;
@@ -2167,7 +2170,8 @@
mServices.serviceForegroundTimeout((ServiceRecord)msg.obj);
} break;
case SERVICE_FOREGROUND_CRASH_MSG: {
- mServices.serviceForegroundCrash((ProcessRecord)msg.obj);
+ mServices.serviceForegroundCrash(
+ (ProcessRecord) msg.obj, msg.getData().getCharSequence(SERVICE_RECORD_KEY));
} break;
case DISPATCH_PENDING_INTENT_CANCEL_MSG: {
RemoteCallbackList<IResultReceiver> callbacks
@@ -13338,12 +13342,7 @@
@Override
public void stopAppSwitches() {
- if (checkCallingPermission(android.Manifest.permission.STOP_APP_SWITCHES)
- != PackageManager.PERMISSION_GRANTED) {
- throw new SecurityException("viewquires permission "
- + android.Manifest.permission.STOP_APP_SWITCHES);
- }
-
+ enforceCallerIsRecentsOrHasPermission(STOP_APP_SWITCHES, "stopAppSwitches");
synchronized(this) {
mAppSwitchesAllowedTime = SystemClock.uptimeMillis()
+ APP_SWITCH_DELAY_TIME;
@@ -13353,12 +13352,7 @@
}
public void resumeAppSwitches() {
- if (checkCallingPermission(android.Manifest.permission.STOP_APP_SWITCHES)
- != PackageManager.PERMISSION_GRANTED) {
- throw new SecurityException("Requires permission "
- + android.Manifest.permission.STOP_APP_SWITCHES);
- }
-
+ enforceCallerIsRecentsOrHasPermission(STOP_APP_SWITCHES, "resumeAppSwitches");
synchronized(this) {
// Note that we don't execute any pending app switches... we will
// let those wait until either the timeout, or the next start
@@ -13385,9 +13379,11 @@
return true;
}
- int perm = checkComponentPermission(
- android.Manifest.permission.STOP_APP_SWITCHES, sourcePid,
- sourceUid, -1, true);
+ if (mRecentTasks.isCallerRecents(sourceUid)) {
+ return true;
+ }
+
+ int perm = checkComponentPermission(STOP_APP_SWITCHES, sourcePid, sourceUid, -1, true);
if (perm == PackageManager.PERMISSION_GRANTED) {
return true;
}
@@ -13398,9 +13394,7 @@
// If the actual IPC caller is different from the logical source, then
// also see if they are allowed to control app switches.
if (callingUid != -1 && callingUid != sourceUid) {
- perm = checkComponentPermission(
- android.Manifest.permission.STOP_APP_SWITCHES, callingPid,
- callingUid, -1, true);
+ perm = checkComponentPermission(STOP_APP_SWITCHES, callingPid, callingUid, -1, true);
if (perm == PackageManager.PERMISSION_GRANTED) {
return true;
}
diff --git a/services/core/java/com/android/server/am/ActivityRecord.java b/services/core/java/com/android/server/am/ActivityRecord.java
index 1af4114..e539bf8 100644
--- a/services/core/java/com/android/server/am/ActivityRecord.java
+++ b/services/core/java/com/android/server/am/ActivityRecord.java
@@ -93,8 +93,6 @@
import static com.android.server.am.ActivityManagerDebugConfig.POSTFIX_VISIBILITY;
import static com.android.server.am.ActivityManagerDebugConfig.TAG_AM;
import static com.android.server.am.ActivityManagerDebugConfig.TAG_WITH_CLASS_NAME;
-import static com.android.server.am.ActivityStack.ActivityState.DESTROYED;
-import static com.android.server.am.ActivityStack.ActivityState.DESTROYING;
import static com.android.server.am.ActivityStack.ActivityState.INITIALIZING;
import static com.android.server.am.ActivityStack.ActivityState.PAUSED;
import static com.android.server.am.ActivityStack.ActivityState.PAUSING;
@@ -154,6 +152,7 @@
import android.graphics.Bitmap;
import android.graphics.GraphicBuffer;
import android.graphics.Rect;
+import android.os.Binder;
import android.os.Build;
import android.os.Bundle;
import android.os.Debug;
@@ -2880,7 +2879,7 @@
final ActivityManagerService service = stackSupervisor.mService;
final ActivityInfo aInfo = stackSupervisor.resolveActivity(intent, resolvedType, 0, null,
- userId);
+ userId, Binder.getCallingUid());
if (aInfo == null) {
throw new XmlPullParserException("restoreActivity resolver error. Intent=" + intent +
" resolvedType=" + resolvedType);
diff --git a/services/core/java/com/android/server/am/ActivityStackSupervisor.java b/services/core/java/com/android/server/am/ActivityStackSupervisor.java
index ea089e0..e9a1358 100644
--- a/services/core/java/com/android/server/am/ActivityStackSupervisor.java
+++ b/services/core/java/com/android/server/am/ActivityStackSupervisor.java
@@ -1264,10 +1264,11 @@
}
ResolveInfo resolveIntent(Intent intent, String resolvedType, int userId) {
- return resolveIntent(intent, resolvedType, userId, 0);
+ return resolveIntent(intent, resolvedType, userId, 0, Binder.getCallingUid());
}
- ResolveInfo resolveIntent(Intent intent, String resolvedType, int userId, int flags) {
+ ResolveInfo resolveIntent(Intent intent, String resolvedType, int userId, int flags,
+ int filterCallingUid) {
synchronized (mService) {
try {
Trace.traceBegin(TRACE_TAG_ACTIVITY_MANAGER, "resolveIntent");
@@ -1278,7 +1279,7 @@
modifiedFlags |= PackageManager.MATCH_INSTANT;
}
return mService.getPackageManagerInternalLocked().resolveIntent(
- intent, resolvedType, modifiedFlags, userId, true);
+ intent, resolvedType, modifiedFlags, userId, true, filterCallingUid);
} finally {
Trace.traceEnd(TRACE_TAG_ACTIVITY_MANAGER);
@@ -1287,8 +1288,8 @@
}
ActivityInfo resolveActivity(Intent intent, String resolvedType, int startFlags,
- ProfilerInfo profilerInfo, int userId) {
- final ResolveInfo rInfo = resolveIntent(intent, resolvedType, userId);
+ ProfilerInfo profilerInfo, int userId, int filterCallingUid) {
+ final ResolveInfo rInfo = resolveIntent(intent, resolvedType, userId, 0, filterCallingUid);
return resolveActivity(intent, rInfo, startFlags, profilerInfo);
}
@@ -1579,7 +1580,7 @@
// to run in multiple processes, because this is actually
// part of the framework so doesn't make sense to track as a
// separate apk in the process.
- app.addPackage(r.info.packageName, r.info.applicationInfo.versionCode,
+ app.addPackage(r.info.packageName, r.info.applicationInfo.longVersionCode,
mService.mProcessStats);
}
realStartActivityLocked(r, app, andResume, checkConfig);
diff --git a/services/core/java/com/android/server/am/ActivityStartController.java b/services/core/java/com/android/server/am/ActivityStartController.java
index fb78838..86a3fce 100644
--- a/services/core/java/com/android/server/am/ActivityStartController.java
+++ b/services/core/java/com/android/server/am/ActivityStartController.java
@@ -23,7 +23,6 @@
import static com.android.server.am.ActivityManagerDebugConfig.TAG_WITH_CLASS_NAME;
import static com.android.server.am.ActivityManagerService.ALLOW_FULL_ONLY;
-import android.app.ActivityOptions;
import android.app.IApplicationThread;
import android.content.ComponentName;
import android.content.ContentResolver;
@@ -33,7 +32,6 @@
import android.content.pm.PackageManager;
import android.content.pm.ResolveInfo;
import android.os.Binder;
-import android.os.Bundle;
import android.os.FactoryTest;
import android.os.Handler;
import android.os.IBinder;
@@ -322,7 +320,7 @@
// Collect information about the target of the Intent.
ActivityInfo aInfo = mSupervisor.resolveActivity(intent, resolvedTypes[i], 0,
- null, userId);
+ null, userId, realCallingUid);
// TODO: New, check if this is correct
aInfo = mService.getActivityInfoForUser(aInfo, userId);
diff --git a/services/core/java/com/android/server/am/ActivityStartInterceptor.java b/services/core/java/com/android/server/am/ActivityStartInterceptor.java
index 2ac389d..6ca8a92 100644
--- a/services/core/java/com/android/server/am/ActivityStartInterceptor.java
+++ b/services/core/java/com/android/server/am/ActivityStartInterceptor.java
@@ -32,8 +32,10 @@
import static android.content.Intent.FLAG_ACTIVITY_TASK_ON_HOME;
import static android.content.pm.ApplicationInfo.FLAG_SUSPENDED;
+import static com.android.server.pm.PackageManagerService.PLATFORM_PACKAGE_NAME;
+
+import android.Manifest;
import android.app.ActivityOptions;
-import android.app.AppGlobals;
import android.app.KeyguardManager;
import android.app.admin.DevicePolicyManagerInternal;
import android.content.Context;
@@ -41,6 +43,7 @@
import android.content.Intent;
import android.content.IntentSender;
import android.content.pm.ActivityInfo;
+import android.content.pm.PackageManagerInternal;
import android.content.pm.ResolveInfo;
import android.content.pm.UserInfo;
import android.os.Binder;
@@ -51,6 +54,7 @@
import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.app.HarmfulAppWarningActivity;
+import com.android.internal.app.SuspendedAppActivity;
import com.android.internal.app.UnlaunchableAppActivity;
import com.android.server.LocalServices;
@@ -151,7 +155,7 @@
mInTask = inTask;
mActivityOptions = activityOptions;
- if (interceptSuspendPackageIfNeed()) {
+ if (interceptSuspendedPackageIfNeeded()) {
// Skip the rest of interceptions as the package is suspended by device admin so
// no user action can undo this.
return true;
@@ -204,12 +208,7 @@
return true;
}
- private boolean interceptSuspendPackageIfNeed() {
- // Do not intercept if the admin did not suspend the package
- if (mAInfo == null || mAInfo.applicationInfo == null ||
- (mAInfo.applicationInfo.flags & FLAG_SUSPENDED) == 0) {
- return false;
- }
+ private boolean interceptSuspendedByAdminPackage() {
DevicePolicyManagerInternal devicePolicyManager = LocalServices
.getService(DevicePolicyManagerInternal.class);
if (devicePolicyManager == null) {
@@ -232,6 +231,55 @@
return true;
}
+ private Intent createSuspendedAppInterceptIntent(String suspendedPackage,
+ String suspendingPackage, String dialogMessage, int userId) {
+ final Intent interceptIntent = new Intent(mServiceContext, SuspendedAppActivity.class)
+ .putExtra(Intent.EXTRA_PACKAGE_NAME, suspendedPackage)
+ .putExtra(SuspendedAppActivity.EXTRA_DIALOG_MESSAGE, dialogMessage)
+ .putExtra(Intent.EXTRA_USER_ID, userId)
+ .setFlags(Intent.FLAG_ACTIVITY_NEW_TASK
+ | Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS);
+
+ final Intent moreDetailsIntent = new Intent(Intent.ACTION_SHOW_SUSPENDED_APP_DETAILS)
+ .setPackage(suspendingPackage);
+ final String requiredPermission = Manifest.permission.SEND_SHOW_SUSPENDED_APP_DETAILS;
+ final ResolveInfo resolvedInfo = mSupervisor.resolveIntent(moreDetailsIntent, null, userId);
+ if (resolvedInfo != null && resolvedInfo.activityInfo != null
+ && requiredPermission.equals(resolvedInfo.activityInfo.permission)) {
+ moreDetailsIntent.putExtra(Intent.EXTRA_PACKAGE_NAME, suspendedPackage)
+ .setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
+ interceptIntent.putExtra(SuspendedAppActivity.EXTRA_MORE_DETAILS_INTENT,
+ moreDetailsIntent);
+ }
+ return interceptIntent;
+ }
+
+ private boolean interceptSuspendedPackageIfNeeded() {
+ // Do not intercept if the package is not suspended
+ if (mAInfo == null || mAInfo.applicationInfo == null ||
+ (mAInfo.applicationInfo.flags & FLAG_SUSPENDED) == 0) {
+ return false;
+ }
+ final PackageManagerInternal pmi = mService.getPackageManagerInternalLocked();
+ if (pmi == null) {
+ return false;
+ }
+ final String suspendedPackage = mAInfo.applicationInfo.packageName;
+ final String suspendingPackage = pmi.getSuspendingPackage(suspendedPackage, mUserId);
+ if (PLATFORM_PACKAGE_NAME.equals(suspendingPackage)) {
+ return interceptSuspendedByAdminPackage();
+ }
+ final String dialogMessage = pmi.getSuspendedDialogMessage(suspendedPackage, mUserId);
+ mIntent = createSuspendedAppInterceptIntent(suspendedPackage, suspendingPackage,
+ dialogMessage, mUserId);
+ mCallingPid = mRealCallingPid;
+ mCallingUid = mRealCallingUid;
+ mResolvedType = null;
+ mRInfo = mSupervisor.resolveIntent(mIntent, mResolvedType, 0);
+ mAInfo = mSupervisor.resolveActivity(mIntent, mRInfo, mStartFlags, null /*profilerInfo*/);
+ return true;
+ }
+
private boolean interceptWorkProfileChallengeIfNeeded() {
final Intent interceptingIntent = interceptWithConfirmCredentialsIfNeeded(mAInfo, mUserId);
if (interceptingIntent == null) {
@@ -293,9 +341,9 @@
private boolean interceptHarmfulAppIfNeeded() {
CharSequence harmfulAppWarning;
try {
- harmfulAppWarning = AppGlobals.getPackageManager().getHarmfulAppWarning(
- mAInfo.packageName, mUserId);
- } catch (RemoteException e) {
+ harmfulAppWarning = mService.getPackageManager()
+ .getHarmfulAppWarning(mAInfo.packageName, mUserId);
+ } catch (RemoteException ex) {
return false;
}
diff --git a/services/core/java/com/android/server/am/ActivityStarter.java b/services/core/java/com/android/server/am/ActivityStarter.java
index 1b7e1ed..5337566 100644
--- a/services/core/java/com/android/server/am/ActivityStarter.java
+++ b/services/core/java/com/android/server/am/ActivityStarter.java
@@ -28,10 +28,10 @@
import static android.app.ActivityManager.START_TASK_TO_FRONT;
import static android.app.WindowConfiguration.WINDOWING_MODE_FREEFORM;
import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN;
+import static android.app.WindowConfiguration.WINDOWING_MODE_PINNED;
import static android.app.WindowConfiguration.WINDOWING_MODE_SPLIT_SCREEN_PRIMARY;
import static android.app.WindowConfiguration.WINDOWING_MODE_SPLIT_SCREEN_SECONDARY;
import static android.app.WindowConfiguration.WINDOWING_MODE_UNDEFINED;
-import static android.content.Intent.ACTION_INSTALL_INSTANT_APP_PACKAGE;
import static android.content.Intent.FLAG_ACTIVITY_CLEAR_TASK;
import static android.content.Intent.FLAG_ACTIVITY_CLEAR_TOP;
import static android.content.Intent.FLAG_ACTIVITY_LAUNCH_ADJACENT;
@@ -903,14 +903,22 @@
final int clearTaskFlags = FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_CLEAR_TASK;
boolean clearedTask = (mLaunchFlags & clearTaskFlags) == clearTaskFlags
&& mReuseTask != null;
- if (startedActivityStack.inPinnedWindowingMode()
- && (result == START_TASK_TO_FRONT || result == START_DELIVERED_TO_TOP
- || clearedTask)) {
- // The activity was already running in the pinned stack so it wasn't started, but either
- // brought to the front or the new intent was delivered to it since it was already in
- // front. Notify anyone interested in this piece of information.
- mService.mTaskChangeNotificationController.notifyPinnedActivityRestartAttempt(
- clearedTask);
+ if (result == START_TASK_TO_FRONT || result == START_DELIVERED_TO_TOP || clearedTask) {
+ // The activity was already running so it wasn't started, but either brought to the
+ // front or the new intent was delivered to it since it was already in front. Notify
+ // anyone interested in this piece of information.
+ switch (startedActivityStack.getWindowingMode()) {
+ case WINDOWING_MODE_PINNED:
+ mService.mTaskChangeNotificationController.notifyPinnedActivityRestartAttempt(
+ clearedTask);
+ break;
+ case WINDOWING_MODE_SPLIT_SCREEN_PRIMARY:
+ final ActivityStack homeStack = mSupervisor.mHomeStack;
+ if (homeStack != null && homeStack.shouldBeVisible(null /* starting */)) {
+ mService.mWindowManager.showRecentApps();
+ }
+ break;
+ }
}
}
@@ -966,7 +974,8 @@
if (profileLockedAndParentUnlockingOrUnlocked) {
rInfo = mSupervisor.resolveIntent(intent, resolvedType, userId,
PackageManager.MATCH_DIRECT_BOOT_AWARE
- | PackageManager.MATCH_DIRECT_BOOT_UNAWARE);
+ | PackageManager.MATCH_DIRECT_BOOT_UNAWARE,
+ Binder.getCallingUid());
}
}
}
diff --git a/services/core/java/com/android/server/am/ProcessRecord.java b/services/core/java/com/android/server/am/ProcessRecord.java
index 03acb84..b7fde1d 100644
--- a/services/core/java/com/android/server/am/ProcessRecord.java
+++ b/services/core/java/com/android/server/am/ProcessRecord.java
@@ -496,7 +496,7 @@
uid = _uid;
userId = UserHandle.getUserId(_uid);
processName = _processName;
- pkgList.put(_info.packageName, new ProcessStats.ProcessStateHolder(_info.versionCode));
+ pkgList.put(_info.packageName, new ProcessStats.ProcessStateHolder(_info.longVersionCode));
maxAdj = ProcessList.UNKNOWN_ADJ;
curRawAdj = setRawAdj = ProcessList.INVALID_ADJ;
curAdj = setAdj = verifiedAdj = ProcessList.INVALID_ADJ;
@@ -521,7 +521,7 @@
origBase.makeInactive();
}
baseProcessTracker = tracker.getProcessStateLocked(info.packageName, uid,
- info.versionCode, processName);
+ info.longVersionCode, processName);
baseProcessTracker.makeActive();
for (int i=0; i<pkgList.size(); i++) {
ProcessStats.ProcessStateHolder holder = pkgList.valueAt(i);
@@ -529,7 +529,7 @@
holder.state.makeInactive();
}
holder.state = tracker.getProcessStateLocked(pkgList.keyAt(i), uid,
- info.versionCode, processName);
+ info.longVersionCode, processName);
if (holder.state != baseProcessTracker) {
holder.state.makeActive();
}
@@ -828,9 +828,9 @@
}
pkgList.clear();
ProcessState ps = tracker.getProcessStateLocked(
- info.packageName, uid, info.versionCode, processName);
+ info.packageName, uid, info.longVersionCode, processName);
ProcessStats.ProcessStateHolder holder = new ProcessStats.ProcessStateHolder(
- info.versionCode);
+ info.longVersionCode);
holder.state = ps;
pkgList.put(info.packageName, holder);
if (ps != baseProcessTracker) {
@@ -839,7 +839,7 @@
}
} else if (N != 1) {
pkgList.clear();
- pkgList.put(info.packageName, new ProcessStats.ProcessStateHolder(info.versionCode));
+ pkgList.put(info.packageName, new ProcessStats.ProcessStateHolder(info.longVersionCode));
}
}
diff --git a/services/core/java/com/android/server/audio/AudioService.java b/services/core/java/com/android/server/audio/AudioService.java
index 3e82c25..8212463 100644
--- a/services/core/java/com/android/server/audio/AudioService.java
+++ b/services/core/java/com/android/server/audio/AudioService.java
@@ -588,7 +588,7 @@
AudioSystem.DEVICE_OUT_HDMI_ARC |
AudioSystem.DEVICE_OUT_SPDIF |
AudioSystem.DEVICE_OUT_AUX_LINE;
- int mFullVolumeDevices = AudioSystem.DEVICE_OUT_HEARING_AID;
+ int mFullVolumeDevices = 0;
private final boolean mMonitorRotation;
@@ -4765,6 +4765,8 @@
index = getAbsoluteVolumeIndex((getIndex(device) + 5)/10);
} else if ((device & mFullVolumeDevices) != 0) {
index = (mIndexMax + 5)/10;
+ } else if ((device & AudioSystem.DEVICE_OUT_HEARING_AID) != 0) {
+ index = (mIndexMax + 5)/10;
} else {
index = (getIndex(device) + 5)/10;
}
@@ -4785,6 +4787,8 @@
index = getAbsoluteVolumeIndex((getIndex(device) + 5)/10);
} else if ((device & mFullVolumeDevices) != 0) {
index = (mIndexMax + 5)/10;
+ } else if ((device & AudioSystem.DEVICE_OUT_HEARING_AID) != 0) {
+ index = (mIndexMax + 5)/10;
} else {
index = (mIndexMap.valueAt(i) + 5)/10;
}
diff --git a/services/core/java/com/android/server/connectivity/DnsManager.java b/services/core/java/com/android/server/connectivity/DnsManager.java
index 5579849..2a361a0 100644
--- a/services/core/java/com/android/server/connectivity/DnsManager.java
+++ b/services/core/java/com/android/server/connectivity/DnsManager.java
@@ -61,6 +61,51 @@
* This class it NOT designed for concurrent access. Furthermore, all non-static
* methods MUST be called from ConnectivityService's thread.
*
+ * [ Private DNS ]
+ * The code handling Private DNS is spread across several components, but this
+ * seems like the least bad place to collect all the observations.
+ *
+ * Private DNS handling and updating occurs in response to several different
+ * events. Each is described here with its corresponding intended handling.
+ *
+ * [A] Event: A new network comes up.
+ * Mechanics:
+ * [1] ConnectivityService gets notifications from NetworkAgents.
+ * [2] in updateNetworkInfo(), the first time the NetworkAgent goes into
+ * into CONNECTED state, the Private DNS configuration is retrieved,
+ * programmed, and strict mode hostname resolution (if applicable) is
+ * enqueued in NetworkAgent's NetworkMonitor, via a call to
+ * handlePerNetworkPrivateDnsConfig().
+ * [3] Re-resolution of strict mode hostnames that fail to return any
+ * IP addresses happens inside NetworkMonitor; it sends itself a
+ * delayed CMD_EVALUATE_PRIVATE_DNS message in a simple backoff
+ * schedule.
+ * [4] Successfully resolved hostnames are sent to ConnectivityService
+ * inside an EVENT_PRIVATE_DNS_CONFIG_RESOLVED message. The resolved
+ * IP addresses are programmed into netd via:
+ *
+ * updatePrivateDns() -> updateDnses()
+ *
+ * both of which make calls into DnsManager.
+ * [5] Upon a successful hostname resolution NetworkMonitor initiates a
+ * validation attempt in the form of a lookup for a one-time hostname
+ * that uses Private DNS.
+ *
+ * [B] Event: Private DNS settings are changed.
+ * Mechanics:
+ * [1] ConnectivityService gets notifications from its SettingsObserver.
+ * [2] handlePrivateDnsSettingsChanged() is called, which calls
+ * handlePerNetworkPrivateDnsConfig() and the process proceeds
+ * as if from A.3 above.
+ *
+ * [C] Event: An application calls ConnectivityManager#reportBadNetwork().
+ * Mechanics:
+ * [1] NetworkMonitor is notified and initiates a reevaluation, which
+ * always bypasses Private DNS.
+ * [2] Once completed, NetworkMonitor checks if strict mode is in operation
+ * and if so enqueues another evaluation of Private DNS, as if from
+ * step A.5 above.
+ *
* @hide
*/
public class DnsManager {
diff --git a/services/core/java/com/android/server/connectivity/NetworkMonitor.java b/services/core/java/com/android/server/connectivity/NetworkMonitor.java
index 8a2e71c..2845383 100644
--- a/services/core/java/com/android/server/connectivity/NetworkMonitor.java
+++ b/services/core/java/com/android/server/connectivity/NetworkMonitor.java
@@ -34,6 +34,7 @@
import android.net.ProxyInfo;
import android.net.TrafficStats;
import android.net.Uri;
+import android.net.dns.ResolvUtil;
import android.net.metrics.IpConnectivityLog;
import android.net.metrics.NetworkEvent;
import android.net.metrics.ValidationProbeEvent;
@@ -64,6 +65,7 @@
import com.android.internal.util.Protocol;
import com.android.internal.util.State;
import com.android.internal.util.StateMachine;
+import com.android.server.connectivity.DnsManager.PrivateDnsConfig;
import java.io.IOException;
import java.net.HttpURLConnection;
@@ -77,6 +79,7 @@
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Random;
+import java.util.UUID;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;
@@ -165,7 +168,7 @@
* Force evaluation even if it has succeeded in the past.
* arg1 = UID responsible for requesting this reeval. Will be billed for data.
*/
- public static final int CMD_FORCE_REEVALUATION = BASE + 8;
+ private static final int CMD_FORCE_REEVALUATION = BASE + 8;
/**
* Message to self indicating captive portal app finished.
@@ -205,9 +208,15 @@
* Private DNS. If a DNS resolution is required, e.g. for DNS-over-TLS in
* strict mode, then an event is sent back to ConnectivityService with the
* result of the resolution attempt.
+ *
+ * A separate message is used to trigger (re)evaluation of the Private DNS
+ * configuration, so that the message can be handled as needed in different
+ * states, including being ignored until after an ongoing captive portal
+ * validation phase is completed.
*/
private static final int CMD_PRIVATE_DNS_SETTINGS_CHANGED = BASE + 13;
public static final int EVENT_PRIVATE_DNS_CONFIG_RESOLVED = BASE + 14;
+ private static final int CMD_EVALUATE_PRIVATE_DNS = BASE + 15;
// Start mReevaluateDelayMs at this value and double.
private static final int INITIAL_REEVALUATE_DELAY_MS = 1000;
@@ -215,6 +224,7 @@
// Before network has been evaluated this many times, ignore repeated reevaluate requests.
private static final int IGNORE_REEVALUATE_ATTEMPTS = 5;
private int mReevaluateToken = 0;
+ private static final int NO_UID = 0;
private static final int INVALID_UID = -1;
private int mUidResponsibleForReeval = INVALID_UID;
// Stop blaming UID that requested re-evaluation after this many attempts.
@@ -224,6 +234,8 @@
private static final int NUM_VALIDATION_LOG_LINES = 20;
+ private String mPrivateDnsProviderHostname = "";
+
public static boolean isValidationRequired(
NetworkCapabilities dfltNetCap, NetworkCapabilities nc) {
// TODO: Consider requiring validation for DUN networks.
@@ -261,13 +273,12 @@
public boolean systemReady = false;
- private DnsManager.PrivateDnsConfig mPrivateDnsCfg = null;
-
private final State mDefaultState = new DefaultState();
private final State mValidatedState = new ValidatedState();
private final State mMaybeNotifyState = new MaybeNotifyState();
private final State mEvaluatingState = new EvaluatingState();
private final State mCaptivePortalState = new CaptivePortalState();
+ private final State mEvaluatingPrivateDnsState = new EvaluatingPrivateDnsState();
private CustomIntentReceiver mLaunchCaptivePortalAppBroadcastReceiver = null;
@@ -293,6 +304,10 @@
// Add suffix indicating which NetworkMonitor we're talking about.
super(TAG + networkAgentInfo.name());
+ // Logs with a tag of the form given just above, e.g.
+ // <timestamp> 862 2402 D NetworkMonitor/NetworkAgentInfo [WIFI () - 100]: ...
+ setDbg(VDBG);
+
mContext = context;
mMetricsLog = logger;
mConnectivityServiceHandler = handler;
@@ -305,10 +320,11 @@
mDefaultRequest = defaultRequest;
addState(mDefaultState);
- addState(mValidatedState, mDefaultState);
addState(mMaybeNotifyState, mDefaultState);
addState(mEvaluatingState, mMaybeNotifyState);
addState(mCaptivePortalState, mMaybeNotifyState);
+ addState(mEvaluatingPrivateDnsState, mDefaultState);
+ addState(mValidatedState, mDefaultState);
setInitialState(mDefaultState);
mIsCaptivePortalCheckEnabled = getIsCaptivePortalCheckEnabled();
@@ -321,6 +337,17 @@
start();
}
+ public void forceReevaluation(int responsibleUid) {
+ sendMessage(CMD_FORCE_REEVALUATION, responsibleUid, 0);
+ }
+
+ public void notifyPrivateDnsSettingsChanged(PrivateDnsConfig newCfg) {
+ // Cancel any outstanding resolutions.
+ removeMessages(CMD_PRIVATE_DNS_SETTINGS_CHANGED);
+ // Send the update to the proper thread.
+ sendMessage(CMD_PRIVATE_DNS_SETTINGS_CHANGED, newCfg);
+ }
+
@Override
protected void log(String s) {
if (DBG) Log.d(TAG + "/" + mNetworkAgentInfo.name(), s);
@@ -349,6 +376,12 @@
mDefaultRequest.networkCapabilities, mNetworkAgentInfo.networkCapabilities);
}
+
+ private void notifyNetworkTestResultInvalid(Object obj) {
+ mConnectivityServiceHandler.sendMessage(obtainMessage(
+ EVENT_NETWORK_TESTED, NETWORK_TEST_RESULT_INVALID, mNetId, obj));
+ }
+
// DefaultState is the parent of all States. It exists only to handle CMD_* messages but
// does not entail any real state (hence no enter() or exit() routines).
private class DefaultState extends State {
@@ -392,41 +425,66 @@
switch (message.arg1) {
case APP_RETURN_DISMISSED:
- sendMessage(CMD_FORCE_REEVALUATION, 0 /* no UID */, 0);
+ sendMessage(CMD_FORCE_REEVALUATION, NO_UID, 0);
break;
case APP_RETURN_WANTED_AS_IS:
mDontDisplaySigninNotification = true;
// TODO: Distinguish this from a network that actually validates.
- // Displaying the "!" on the system UI icon may still be a good idea.
- transitionTo(mValidatedState);
+ // Displaying the "x" on the system UI icon may still be a good idea.
+ transitionTo(mEvaluatingPrivateDnsState);
break;
case APP_RETURN_UNWANTED:
mDontDisplaySigninNotification = true;
mUserDoesNotWant = true;
- mConnectivityServiceHandler.sendMessage(obtainMessage(
- EVENT_NETWORK_TESTED, NETWORK_TEST_RESULT_INVALID,
- mNetId, null));
+ notifyNetworkTestResultInvalid(null);
// TODO: Should teardown network.
mUidResponsibleForReeval = 0;
transitionTo(mEvaluatingState);
break;
}
return HANDLED;
- case CMD_PRIVATE_DNS_SETTINGS_CHANGED:
- if (isValidationRequired()) {
- // This performs a blocking DNS resolution of the
- // strict mode hostname, if required.
- resolvePrivateDnsConfig((DnsManager.PrivateDnsConfig) message.obj);
- if ((mPrivateDnsCfg != null) && mPrivateDnsCfg.inStrictMode()) {
- mConnectivityServiceHandler.sendMessage(obtainMessage(
- EVENT_PRIVATE_DNS_CONFIG_RESOLVED, 0, mNetId,
- new DnsManager.PrivateDnsConfig(mPrivateDnsCfg)));
- }
+ case CMD_PRIVATE_DNS_SETTINGS_CHANGED: {
+ final PrivateDnsConfig cfg = (PrivateDnsConfig) message.obj;
+ if (!isValidationRequired() || cfg == null || !cfg.inStrictMode()) {
+ // No DNS resolution required.
+ //
+ // We don't force any validation in opportunistic mode
+ // here. Opportunistic mode nameservers are validated
+ // separately within netd.
+ //
+ // Reset Private DNS settings state.
+ mPrivateDnsProviderHostname = "";
+ break;
}
- return HANDLED;
+
+ mPrivateDnsProviderHostname = cfg.hostname;
+
+ // DNS resolutions via Private DNS strict mode block for a
+ // few seconds (~4.2) checking for any IP addresses to
+ // arrive and validate. Initiating a (re)evaluation now
+ // should not significantly alter the validation outcome.
+ //
+ // No matter what: enqueue a validation request; one of
+ // three things can happen with this request:
+ // [1] ignored (EvaluatingState or CaptivePortalState)
+ // [2] transition to EvaluatingPrivateDnsState
+ // (DefaultState and ValidatedState)
+ // [3] handled (EvaluatingPrivateDnsState)
+ //
+ // The Private DNS configuration to be evaluated will:
+ // [1] be skipped (not in strict mode), or
+ // [2] validate (huzzah), or
+ // [3] encounter some problem (invalid hostname,
+ // no resolved IP addresses, IPs unreachable,
+ // port 853 unreachable, port 853 is not running a
+ // DNS-over-TLS server, et cetera).
+ sendMessage(CMD_EVALUATE_PRIVATE_DNS);
+ break;
+ }
default:
- return HANDLED;
+ break;
}
+ return HANDLED;
}
}
@@ -440,7 +498,7 @@
maybeLogEvaluationResult(
networkEventType(validationStage(), EvaluationResult.VALIDATED));
mConnectivityServiceHandler.sendMessage(obtainMessage(EVENT_NETWORK_TESTED,
- NETWORK_TEST_RESULT_VALID, mNetId, mPrivateDnsCfg));
+ NETWORK_TEST_RESULT_VALID, mNetId, null));
mValidations++;
}
@@ -449,10 +507,14 @@
switch (message.what) {
case CMD_NETWORK_CONNECTED:
transitionTo(mValidatedState);
- return HANDLED;
+ break;
+ case CMD_EVALUATE_PRIVATE_DNS:
+ transitionTo(mEvaluatingPrivateDnsState);
+ break;
default:
return NOT_HANDLED;
}
+ return HANDLED;
}
}
@@ -569,11 +631,11 @@
case CMD_REEVALUATE:
if (message.arg1 != mReevaluateToken || mUserDoesNotWant)
return HANDLED;
- // Don't bother validating networks that don't satisify the default request.
+ // Don't bother validating networks that don't satisfy the default request.
// This includes:
// - VPNs which can be considered explicitly desired by the user and the
// user's desire trumps whether the network validates.
- // - Networks that don't provide internet access. It's unclear how to
+ // - Networks that don't provide Internet access. It's unclear how to
// validate such networks.
// - Untrusted networks. It's unsafe to prompt the user to sign-in to
// such networks and the user didn't express interest in connecting to
@@ -588,7 +650,6 @@
// expensive metered network, or unwanted leaking of the User Agent string.
if (!isValidationRequired()) {
validationLog("Network would not satisfy default request, not validating");
- mPrivateDnsCfg = null;
transitionTo(mValidatedState);
return HANDLED;
}
@@ -601,20 +662,18 @@
// if this is found to cause problems.
CaptivePortalProbeResult probeResult = isCaptivePortal();
if (probeResult.isSuccessful()) {
- resolvePrivateDnsConfig();
- transitionTo(mValidatedState);
+ // Transit EvaluatingPrivateDnsState to get to Validated
+ // state (even if no Private DNS validation required).
+ transitionTo(mEvaluatingPrivateDnsState);
} else if (probeResult.isPortal()) {
- mConnectivityServiceHandler.sendMessage(obtainMessage(EVENT_NETWORK_TESTED,
- NETWORK_TEST_RESULT_INVALID, mNetId, probeResult.redirectUrl));
+ notifyNetworkTestResultInvalid(probeResult.redirectUrl);
mLastPortalProbeResult = probeResult;
transitionTo(mCaptivePortalState);
} else {
final Message msg = obtainMessage(CMD_REEVALUATE, ++mReevaluateToken, 0);
sendMessageDelayed(msg, mReevaluateDelayMs);
logNetworkEvent(NetworkEvent.NETWORK_VALIDATION_FAILED);
- mConnectivityServiceHandler.sendMessage(obtainMessage(
- EVENT_NETWORK_TESTED, NETWORK_TEST_RESULT_INVALID, mNetId,
- probeResult.redirectUrl));
+ notifyNetworkTestResultInvalid(probeResult.redirectUrl);
if (mAttempts >= BLAME_FOR_EVALUATION_ATTEMPTS) {
// Don't continue to blame UID forever.
TrafficStats.clearThreadStatsUid();
@@ -700,6 +759,110 @@
}
}
+ private class EvaluatingPrivateDnsState extends State {
+ private int mPrivateDnsReevalDelayMs;
+ private PrivateDnsConfig mPrivateDnsConfig;
+
+ @Override
+ public void enter() {
+ mPrivateDnsReevalDelayMs = INITIAL_REEVALUATE_DELAY_MS;
+ mPrivateDnsConfig = null;
+ sendMessage(CMD_EVALUATE_PRIVATE_DNS);
+ }
+
+ @Override
+ public boolean processMessage(Message msg) {
+ switch (msg.what) {
+ case CMD_EVALUATE_PRIVATE_DNS:
+ if (inStrictMode()) {
+ if (!isStrictModeHostnameResolved()) {
+ resolveStrictModeHostname();
+
+ if (isStrictModeHostnameResolved()) {
+ notifyPrivateDnsConfigResolved();
+ } else {
+ handlePrivateDnsEvaluationFailure();
+ break;
+ }
+ }
+
+ // Look up a one-time hostname, to bypass caching.
+ //
+ // Note that this will race with ConnectivityService
+ // code programming the DNS-over-TLS server IP addresses
+ // into netd (if invoked, above). If netd doesn't know
+ // the IP addresses yet, or if the connections to the IP
+ // addresses haven't yet been validated, netd will block
+ // for up to a few seconds before failing the lookup.
+ if (!sendPrivateDnsProbe()) {
+ handlePrivateDnsEvaluationFailure();
+ break;
+ }
+ }
+
+ // All good!
+ transitionTo(mValidatedState);
+ break;
+ default:
+ return NOT_HANDLED;
+ }
+ return HANDLED;
+ }
+
+ private boolean inStrictMode() {
+ return !TextUtils.isEmpty(mPrivateDnsProviderHostname);
+ }
+
+ private boolean isStrictModeHostnameResolved() {
+ return (mPrivateDnsConfig != null) &&
+ mPrivateDnsConfig.hostname.equals(mPrivateDnsProviderHostname) &&
+ (mPrivateDnsConfig.ips.length > 0);
+ }
+
+ private void resolveStrictModeHostname() {
+ try {
+ // Do a blocking DNS resolution using the network-assigned nameservers.
+ mPrivateDnsConfig = new PrivateDnsConfig(
+ mPrivateDnsProviderHostname,
+ mNetwork.getAllByName(mPrivateDnsProviderHostname));
+ } catch (UnknownHostException uhe) {
+ mPrivateDnsConfig = null;
+ }
+ }
+
+ private void notifyPrivateDnsConfigResolved() {
+ mConnectivityServiceHandler.sendMessage(obtainMessage(
+ EVENT_PRIVATE_DNS_CONFIG_RESOLVED, 0, mNetId, mPrivateDnsConfig));
+ }
+
+ private void handlePrivateDnsEvaluationFailure() {
+ notifyNetworkTestResultInvalid(null);
+
+ // Queue up a re-evaluation with backoff.
+ //
+ // TODO: Consider abandoning this state after a few attempts and
+ // transitioning back to EvaluatingState, to perhaps give ourselves
+ // the opportunity to (re)detect a captive portal or something.
+ sendMessageDelayed(CMD_EVALUATE_PRIVATE_DNS, mPrivateDnsReevalDelayMs);
+ mPrivateDnsReevalDelayMs *= 2;
+ if (mPrivateDnsReevalDelayMs > MAX_REEVALUATE_DELAY_MS) {
+ mPrivateDnsReevalDelayMs = MAX_REEVALUATE_DELAY_MS;
+ }
+ }
+
+ private boolean sendPrivateDnsProbe() {
+ // q.v. system/netd/server/dns/DnsTlsTransport.cpp
+ final String ONE_TIME_HOSTNAME_SUFFIX = "-dnsotls-ds.metric.gstatic.com";
+ final String host = UUID.randomUUID().toString().substring(0, 8) +
+ ONE_TIME_HOSTNAME_SUFFIX;
+ try {
+ final InetAddress[] ips = mNetworkAgentInfo.network().getAllByName(host);
+ return (ips != null && ips.length > 0);
+ } catch (UnknownHostException uhe) {}
+ return false;
+ }
+ }
+
// Limits the list of IP addresses returned by getAllByName or tried by openConnection to at
// most one per address family. This ensures we only wait up to 20 seconds for TCP connections
// to complete, regardless of how many IP addresses a host has.
@@ -710,7 +873,9 @@
@Override
public InetAddress[] getAllByName(String host) throws UnknownHostException {
- List<InetAddress> addrs = Arrays.asList(super.getAllByName(host));
+ // Always bypass Private DNS.
+ final List<InetAddress> addrs = Arrays.asList(
+ ResolvUtil.blockingResolveAllLocally(this, host));
// Ensure the address family of the first address is tried first.
LinkedHashMap<Class, InetAddress> addressByFamily = new LinkedHashMap<>();
@@ -1065,44 +1230,6 @@
return null;
}
- public void notifyPrivateDnsSettingsChanged(DnsManager.PrivateDnsConfig newCfg) {
- // Cancel any outstanding resolutions.
- removeMessages(CMD_PRIVATE_DNS_SETTINGS_CHANGED);
- // Send the update to the proper thread.
- sendMessage(CMD_PRIVATE_DNS_SETTINGS_CHANGED, newCfg);
- }
-
- private void resolvePrivateDnsConfig() {
- resolvePrivateDnsConfig(DnsManager.getPrivateDnsConfig(mContext.getContentResolver()));
- }
-
- private void resolvePrivateDnsConfig(DnsManager.PrivateDnsConfig cfg) {
- // Nothing to do.
- if (cfg == null) {
- mPrivateDnsCfg = null;
- return;
- }
-
- // No DNS resolution required.
- if (!cfg.inStrictMode()) {
- mPrivateDnsCfg = cfg;
- return;
- }
-
- if ((mPrivateDnsCfg != null) && mPrivateDnsCfg.inStrictMode() &&
- (mPrivateDnsCfg.ips.length > 0) && mPrivateDnsCfg.hostname.equals(cfg.hostname)) {
- // We have already resolved this strict mode hostname. Assume that
- // Private DNS services won't be changing serving IP addresses very
- // frequently and save ourselves one re-resolve.
- return;
- }
-
- mPrivateDnsCfg = cfg;
- final DnsManager.PrivateDnsConfig resolvedCfg = DnsManager.tryBlockingResolveOf(
- mNetwork, mPrivateDnsCfg.hostname);
- if (resolvedCfg != null) mPrivateDnsCfg = resolvedCfg;
- }
-
/**
* @param responseReceived - whether or not we received a valid HTTP response to our request.
* If false, isCaptivePortal and responseTimestampMs are ignored
diff --git a/services/core/java/com/android/server/display/DisplayManagerService.java b/services/core/java/com/android/server/display/DisplayManagerService.java
index c7ae1f4..93e0bd5 100644
--- a/services/core/java/com/android/server/display/DisplayManagerService.java
+++ b/services/core/java/com/android/server/display/DisplayManagerService.java
@@ -61,12 +61,15 @@
import android.os.PowerManager;
import android.os.Process;
import android.os.RemoteException;
+import android.os.ResultReceiver;
import android.os.ServiceManager;
+import android.os.ShellCallback;
import android.os.SystemClock;
import android.os.SystemProperties;
import android.os.Trace;
import android.os.UserHandle;
import android.os.UserManager;
+import android.provider.Settings;
import android.text.TextUtils;
import android.util.IntArray;
import android.util.Slog;
@@ -1030,7 +1033,7 @@
}
private void setBrightnessConfigurationForUserInternal(
- @NonNull BrightnessConfiguration c, @UserIdInt int userId,
+ @Nullable BrightnessConfiguration c, @UserIdInt int userId,
@Nullable String packageName) {
final int userSerial = getUserManager().getUserSerialNumber(userId);
synchronized (mSyncRoot) {
@@ -1983,6 +1986,29 @@
}
}
+ @Override // Binder call
+ public void onShellCommand(FileDescriptor in, FileDescriptor out,
+ FileDescriptor err, String[] args, ShellCallback callback,
+ ResultReceiver resultReceiver) {
+ final long token = Binder.clearCallingIdentity();
+ try {
+ DisplayManagerShellCommand command = new DisplayManagerShellCommand(this);
+ command.exec(this, in, out, err, args, callback, resultReceiver);
+ } finally {
+ Binder.restoreCallingIdentity(token);
+ }
+ }
+
+ void setBrightness(int brightness) {
+ Settings.System.putIntForUser(mContext.getContentResolver(),
+ Settings.System.SCREEN_BRIGHTNESS, brightness, UserHandle.USER_CURRENT);
+ }
+
+ void resetBrightnessConfiguration() {
+ setBrightnessConfigurationForUserInternal(null, mContext.getUserId(),
+ mContext.getPackageName());
+ }
+
private boolean validatePackageName(int uid, String packageName) {
if (packageName != null) {
String[] packageNames = mContext.getPackageManager().getPackagesForUid(uid);
diff --git a/services/core/java/com/android/server/display/DisplayManagerShellCommand.java b/services/core/java/com/android/server/display/DisplayManagerShellCommand.java
new file mode 100644
index 0000000..27cad1e
--- /dev/null
+++ b/services/core/java/com/android/server/display/DisplayManagerShellCommand.java
@@ -0,0 +1,92 @@
+/*
+ * 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.server.display;
+
+import android.content.Intent;
+import android.os.RemoteException;
+import android.os.ResultReceiver;
+import android.os.ShellCallback;
+import android.os.ShellCommand;
+import android.util.Slog;
+
+import java.io.PrintWriter;
+import java.lang.NumberFormatException;
+
+class DisplayManagerShellCommand extends ShellCommand {
+ private static final String TAG = "DisplayManagerShellCommand";
+
+ private final DisplayManagerService.BinderService mService;
+
+ DisplayManagerShellCommand(DisplayManagerService.BinderService service) {
+ mService = service;
+ }
+
+ @Override
+ public int onCommand(String cmd) {
+ if (cmd == null) {
+ return handleDefaultCommands(cmd);
+ }
+ final PrintWriter pw = getOutPrintWriter();
+ switch(cmd) {
+ case "set-brightness":
+ return setBrightness();
+ case "reset-brightness-configuration":
+ return resetBrightnessConfiguration();
+ default:
+ return handleDefaultCommands(cmd);
+ }
+ }
+
+ @Override
+ public void onHelp() {
+ final PrintWriter pw = getOutPrintWriter();
+ pw.println("Display manager commands:");
+ pw.println(" help");
+ pw.println(" Print this help text.");
+ pw.println();
+ pw.println(" set-brightness BRIGHTNESS");
+ pw.println(" Sets the current brightness to BRIGHTNESS (a number between 0 and 1).");
+ pw.println(" reset-brightness-configuration");
+ pw.println(" Reset the brightness to its default configuration.");
+ pw.println();
+ Intent.printIntentArgsHelp(pw , "");
+ }
+
+ private int setBrightness() {
+ String brightnessText = getNextArg();
+ if (brightnessText == null) {
+ getErrPrintWriter().println("Error: no brightness specified");
+ return 1;
+ }
+ float brightness = -1;
+ try {
+ brightness = Float.parseFloat(brightnessText);
+ } catch (NumberFormatException e) {
+ }
+ if (brightness < 0 || brightness > 1) {
+ getErrPrintWriter().println("Error: brightness should be a number between 0 and 1");
+ return 1;
+ }
+ mService.setBrightness((int) brightness * 255);
+ return 0;
+ }
+
+ private int resetBrightnessConfiguration() {
+ mService.resetBrightnessConfiguration();
+ return 0;
+ }
+}
diff --git a/services/core/java/com/android/server/display/LocalDisplayAdapter.java b/services/core/java/com/android/server/display/LocalDisplayAdapter.java
index 5ca9abc..b9a279a 100644
--- a/services/core/java/com/android/server/display/LocalDisplayAdapter.java
+++ b/services/core/java/com/android/server/display/LocalDisplayAdapter.java
@@ -436,6 +436,10 @@
com.android.internal.R.bool.config_localDisplaysMirrorContent)) {
mInfo.flags |= DisplayDeviceInfo.FLAG_OWN_CONTENT_ONLY;
}
+
+ if (res.getBoolean(com.android.internal.R.bool.config_localDisplaysPrivate)) {
+ mInfo.flags |= DisplayDeviceInfo.FLAG_PRIVATE;
+ }
}
}
return mInfo;
diff --git a/services/core/java/com/android/server/fingerprint/AuthenticationClient.java b/services/core/java/com/android/server/fingerprint/AuthenticationClient.java
index 8be2c9e..afd1a94 100644
--- a/services/core/java/com/android/server/fingerprint/AuthenticationClient.java
+++ b/services/core/java/com/android/server/fingerprint/AuthenticationClient.java
@@ -18,8 +18,8 @@
import android.content.Context;
import android.hardware.biometrics.fingerprint.V2_1.IBiometricsFingerprint;
-import android.hardware.biometrics.BiometricDialog;
-import android.hardware.biometrics.IBiometricDialogReceiver;
+import android.hardware.biometrics.BiometricPrompt;
+import android.hardware.biometrics.IBiometricPromptReceiver;
import android.hardware.fingerprint.Fingerprint;
import android.hardware.fingerprint.FingerprintManager;
import android.hardware.fingerprint.IFingerprintServiceReceiver;
@@ -46,8 +46,8 @@
public static final int LOCKOUT_PERMANENT = 2;
// Callback mechanism received from the client
- // (BiometricDialog -> FingerprintManager -> FingerprintService -> AuthenticationClient)
- private IBiometricDialogReceiver mDialogReceiverFromClient;
+ // (BiometricPrompt -> FingerprintManager -> FingerprintService -> AuthenticationClient)
+ private IBiometricPromptReceiver mDialogReceiverFromClient;
private Bundle mBundle;
private IStatusBarService mStatusBarService;
private boolean mInLockout;
@@ -55,13 +55,13 @@
protected boolean mDialogDismissed;
// Receives events from SystemUI and handles them before forwarding them to FingerprintDialog
- protected IBiometricDialogReceiver mDialogReceiver = new IBiometricDialogReceiver.Stub() {
+ protected IBiometricPromptReceiver mDialogReceiver = new IBiometricPromptReceiver.Stub() {
@Override // binder call
public void onDialogDismissed(int reason) {
if (mBundle != null && mDialogReceiverFromClient != null) {
try {
mDialogReceiverFromClient.onDialogDismissed(reason);
- if (reason == BiometricDialog.DISMISSED_REASON_USER_CANCEL) {
+ if (reason == BiometricPrompt.DISMISSED_REASON_USER_CANCEL) {
onError(FingerprintManager.FINGERPRINT_ERROR_USER_CANCELED,
0 /* vendorCode */);
}
@@ -88,7 +88,7 @@
public AuthenticationClient(Context context, long halDeviceId, IBinder token,
IFingerprintServiceReceiver receiver, int targetUserId, int groupId, long opId,
boolean restricted, String owner, Bundle bundle,
- IBiometricDialogReceiver dialogReceiver, IStatusBarService statusBarService) {
+ IBiometricPromptReceiver dialogReceiver, IStatusBarService statusBarService) {
super(context, halDeviceId, token, receiver, targetUserId, groupId, restricted, owner);
mOpId = opId;
mBundle = bundle;
@@ -299,7 +299,7 @@
// If the user already cancelled authentication (via some interaction with the
// dialog, we do not need to hide it since it's already hidden.
// If the device is in lockout, don't hide the dialog - it will automatically hide
- // after BiometricDialog.HIDE_DIALOG_DELAY
+ // after BiometricPrompt.HIDE_DIALOG_DELAY
if (mBundle != null && !mDialogDismissed && !mInLockout) {
try {
mStatusBarService.hideFingerprintDialog();
diff --git a/services/core/java/com/android/server/fingerprint/FingerprintService.java b/services/core/java/com/android/server/fingerprint/FingerprintService.java
index 92d3772..4e95bdf 100644
--- a/services/core/java/com/android/server/fingerprint/FingerprintService.java
+++ b/services/core/java/com/android/server/fingerprint/FingerprintService.java
@@ -38,7 +38,7 @@
import android.content.IntentFilter;
import android.content.pm.PackageManager;
import android.content.pm.UserInfo;
-import android.hardware.biometrics.IBiometricDialogReceiver;
+import android.hardware.biometrics.IBiometricPromptReceiver;
import android.hardware.biometrics.fingerprint.V2_1.IBiometricsFingerprint;
import android.hardware.biometrics.fingerprint.V2_1.IBiometricsFingerprintClientCallback;
import android.hardware.fingerprint.Fingerprint;
@@ -849,7 +849,7 @@
private void startAuthentication(IBinder token, long opId, int callingUserId, int groupId,
IFingerprintServiceReceiver receiver, int flags, boolean restricted,
- String opPackageName, Bundle bundle, IBiometricDialogReceiver dialogReceiver) {
+ String opPackageName, Bundle bundle, IBiometricPromptReceiver dialogReceiver) {
updateActiveGroup(groupId, opPackageName);
if (DEBUG) Slog.v(TAG, "startAuthentication(" + opPackageName + ")");
@@ -1160,7 +1160,7 @@
public void authenticate(final IBinder token, final long opId, final int groupId,
final IFingerprintServiceReceiver receiver, final int flags,
final String opPackageName, final Bundle bundle,
- final IBiometricDialogReceiver dialogReceiver) {
+ final IBiometricPromptReceiver dialogReceiver) {
final int callingUid = Binder.getCallingUid();
final int callingPid = Binder.getCallingPid();
final int callingUserId = UserHandle.getCallingUserId();
diff --git a/services/core/java/com/android/server/location/ExponentialBackOff.java b/services/core/java/com/android/server/location/ExponentialBackOff.java
new file mode 100644
index 0000000..8c77b21
--- /dev/null
+++ b/services/core/java/com/android/server/location/ExponentialBackOff.java
@@ -0,0 +1,32 @@
+package com.android.server.location;
+
+/**
+ * A simple implementation of exponential backoff.
+ */
+class ExponentialBackOff {
+ private static final int MULTIPLIER = 2;
+ private final long mInitIntervalMillis;
+ private final long mMaxIntervalMillis;
+ private long mCurrentIntervalMillis;
+
+ ExponentialBackOff(long initIntervalMillis, long maxIntervalMillis) {
+ mInitIntervalMillis = initIntervalMillis;
+ mMaxIntervalMillis = maxIntervalMillis;
+
+ mCurrentIntervalMillis = mInitIntervalMillis / MULTIPLIER;
+ }
+
+ long nextBackoffMillis() {
+ if (mCurrentIntervalMillis > mMaxIntervalMillis) {
+ return mMaxIntervalMillis;
+ }
+
+ mCurrentIntervalMillis *= MULTIPLIER;
+ return mCurrentIntervalMillis;
+ }
+
+ void reset() {
+ mCurrentIntervalMillis = mInitIntervalMillis / MULTIPLIER;
+ }
+}
+
diff --git a/services/core/java/com/android/server/location/GnssLocationProvider.java b/services/core/java/com/android/server/location/GnssLocationProvider.java
index 5955c9c..58bca19 100644
--- a/services/core/java/com/android/server/location/GnssLocationProvider.java
+++ b/services/core/java/com/android/server/location/GnssLocationProvider.java
@@ -76,14 +76,18 @@
import android.telephony.gsm.GsmCellLocation;
import android.text.TextUtils;
import android.util.Log;
-import android.util.NtpTrustedTime;
-import com.android.internal.app.IAppOpsService;
+
import com.android.internal.app.IBatteryStats;
import com.android.internal.location.GpsNetInitiatedHandler;
import com.android.internal.location.GpsNetInitiatedHandler.GpsNiNotification;
import com.android.internal.location.ProviderProperties;
import com.android.internal.location.ProviderRequest;
import com.android.internal.location.gnssmetrics.GnssMetrics;
+import com.android.server.location.GnssSatelliteBlacklistHelper.GnssSatelliteBlacklistCallback;
+import com.android.server.location.NtpTimeHelper.InjectNtpTimeCallback;
+
+import libcore.io.IoUtils;
+
import java.io.File;
import java.io.FileDescriptor;
import java.io.FileInputStream;
@@ -93,21 +97,19 @@
import java.net.UnknownHostException;
import java.util.ArrayList;
import java.util.Arrays;
-import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Properties;
-import libcore.io.IoUtils;
-
/**
* A GNSS implementation of LocationProvider used by LocationManager.
*
* {@hide}
*/
-public class GnssLocationProvider implements LocationProviderInterface {
+public class GnssLocationProvider implements LocationProviderInterface, InjectNtpTimeCallback,
+ GnssSatelliteBlacklistCallback {
private static final String TAG = "GnssLocationProvider";
@@ -208,7 +210,6 @@
private static final int UPDATE_LOCATION = 7; // Handle external location from network listener
private static final int ADD_LISTENER = 8;
private static final int REMOVE_LISTENER = 9;
- private static final int INJECT_NTP_TIME_FINISHED = 10;
private static final int DOWNLOAD_XTRA_DATA_FINISHED = 11;
private static final int SUBSCRIPTION_OR_SIM_CHANGED = 12;
private static final int INITIALIZE_HANDLER = 13;
@@ -310,7 +311,7 @@
}
}
- private Object mLock = new Object();
+ private final Object mLock = new Object();
// current status
private int mStatus = LocationProvider.TEMPORARILY_UNAVAILABLE;
@@ -329,9 +330,6 @@
// Typical hot TTTF is ~5 seconds, so 10 seconds seems sane.
private static final int GPS_POLLING_THRESHOLD_INTERVAL = 10 * 1000;
- // how often to request NTP time, in milliseconds
- // current setting 24 hours
- private static final long NTP_INTERVAL = 24 * 60 * 60 * 1000;
// how long to wait if we have a network error in NTP or XTRA downloading
// the initial value of the exponential backoff
// current setting - 5 minutes
@@ -344,8 +342,8 @@
// Timeout when holding wakelocks for downloading XTRA data.
private static final long DOWNLOAD_XTRA_DATA_TIMEOUT_MS = 60 * 1000;
- private BackOff mNtpBackOff = new BackOff(RETRY_INTERVAL, MAX_RETRY_INTERVAL);
- private BackOff mXtraBackOff = new BackOff(RETRY_INTERVAL, MAX_RETRY_INTERVAL);
+ private final ExponentialBackOff mXtraBackOff = new ExponentialBackOff(RETRY_INTERVAL,
+ MAX_RETRY_INTERVAL);
// true if we are enabled, protected by this
private boolean mEnabled;
@@ -357,12 +355,8 @@
// flags to trigger NTP or XTRA data download when network becomes available
// initialized to true so we do NTP and XTRA when the network comes up after booting
- private int mInjectNtpTimePending = STATE_PENDING_NETWORK;
private int mDownloadXtraDataPending = STATE_PENDING_NETWORK;
- // set to true if the GPS engine requested on-demand NTP time requests
- private boolean mOnDemandTimeInjection;
-
// true if GPS is navigating
private boolean mNavigating;
@@ -417,14 +411,15 @@
private boolean mSuplEsEnabled = false;
private final Context mContext;
- private final NtpTrustedTime mNtpTime;
private final ILocationManager mILocationManager;
private final LocationExtras mLocationExtras = new LocationExtras();
private final GnssStatusListenerHelper mListenerHelper;
+ private final GnssSatelliteBlacklistHelper mGnssSatelliteBlacklistHelper;
private final GnssMeasurementsProvider mGnssMeasurementsProvider;
private final GnssNavigationMessageProvider mGnssNavigationMessageProvider;
private final LocationChangeListener mNetworkLocationListener = new NetworkLocationListener();
private final LocationChangeListener mFusedLocationListener = new FusedLocationListener();
+ private final NtpTimeHelper mNtpTimeHelper;
// Handler for processing events
private Handler mHandler;
@@ -517,9 +512,7 @@
new ConnectivityManager.NetworkCallback() {
@Override
public void onAvailable(Network network) {
- if (mInjectNtpTimePending == STATE_PENDING_NETWORK) {
- requestUtcTime();
- }
+ mNtpTimeHelper.onNetworkAvailable();
if (mDownloadXtraDataPending == STATE_PENDING_NETWORK) {
if (mSupportsXtra) {
// Download only if supported, (prevents an unneccesary on-boot
@@ -588,6 +581,16 @@
}
};
+ /**
+ * Implements {@link GnssSatelliteBlacklistCallback#onUpdateSatelliteBlacklist}.
+ */
+ @Override
+ public void onUpdateSatelliteBlacklist(int[] constellations, int[] svids) {
+ mHandler.post(()->{
+ native_set_satellite_blacklist(constellations, svids);
+ });
+ }
+
private void subscriptionOrSimChanged(Context context) {
if (DEBUG) Log.d(TAG, "received SIM related action: ");
TelephonyManager phone = (TelephonyManager)
@@ -762,7 +765,6 @@
public GnssLocationProvider(Context context, ILocationManager ilocationManager,
Looper looper) {
mContext = context;
- mNtpTime = NtpTrustedTime.getInstance(context);
mILocationManager = ilocationManager;
// Create a wake lock
@@ -880,6 +882,11 @@
}
};
mGnssMetrics = new GnssMetrics(mBatteryStats);
+
+ mNtpTimeHelper = new NtpTimeHelper(mContext, looper, this);
+ mGnssSatelliteBlacklistHelper = new GnssSatelliteBlacklistHelper(mContext,
+ looper, this);
+ mHandler.post(mGnssSatelliteBlacklistHelper::updateSatelliteBlacklist);
}
/**
@@ -895,6 +902,15 @@
return PROPERTIES;
}
+
+ /**
+ * Implements {@link InjectNtpTimeCallback#injectTime}
+ */
+ @Override
+ public void injectTime(long time, long timeReference, int uncertainty) {
+ native_inject_time(time, timeReference, uncertainty);
+ }
+
private void handleUpdateNetworkState(Network network) {
// retrieve NetworkInfo for this UID
NetworkInfo info = mConnMgr.getNetworkInfo(network);
@@ -1014,79 +1030,7 @@
Log.e(TAG, "Invalid status to release SUPL connection: " + agpsDataConnStatus);
}
}
-
- private void handleInjectNtpTime() {
- if (mInjectNtpTimePending == STATE_DOWNLOADING) {
- // already downloading data
- return;
- }
- if (!isDataNetworkConnected()) {
- // try again when network is up
- mInjectNtpTimePending = STATE_PENDING_NETWORK;
- return;
- }
- mInjectNtpTimePending = STATE_DOWNLOADING;
-
- // hold wake lock while task runs
- mWakeLock.acquire();
- Log.i(TAG, "WakeLock acquired by handleInjectNtpTime()");
- AsyncTask.THREAD_POOL_EXECUTOR.execute(new Runnable() {
- @Override
- public void run() {
- long delay;
-
- // force refresh NTP cache when outdated
- boolean refreshSuccess = true;
- if (mNtpTime.getCacheAge() >= NTP_INTERVAL) {
- refreshSuccess = mNtpTime.forceRefresh();
- }
-
- // only update when NTP time is fresh
- if (mNtpTime.getCacheAge() < NTP_INTERVAL) {
- long time = mNtpTime.getCachedNtpTime();
- long timeReference = mNtpTime.getCachedNtpTimeReference();
- long certainty = mNtpTime.getCacheCertainty();
-
- if (DEBUG) {
- long now = System.currentTimeMillis();
- Log.d(TAG, "NTP server returned: "
- + time + " (" + new Date(time)
- + ") reference: " + timeReference
- + " certainty: " + certainty
- + " system time offset: " + (time - now));
- }
-
- native_inject_time(time, timeReference, (int) certainty);
- delay = NTP_INTERVAL;
- mNtpBackOff.reset();
- } else {
- Log.e(TAG, "requestTime failed");
- delay = mNtpBackOff.nextBackoffMillis();
- }
-
- sendMessage(INJECT_NTP_TIME_FINISHED, 0, null);
-
- if (DEBUG) {
- String message = String.format(
- "onDemandTimeInjection=%s, refreshSuccess=%s, delay=%s",
- mOnDemandTimeInjection,
- refreshSuccess,
- delay);
- Log.d(TAG, message);
- }
- if (mOnDemandTimeInjection || !refreshSuccess) {
- // send delayed message for next NTP injection
- // since this is delayed and not urgent we do not hold a wake lock here
- mHandler.sendEmptyMessageDelayed(INJECT_NTP_TIME, delay);
- }
-
- // release wake lock held by task
- mWakeLock.release();
- Log.i(TAG, "WakeLock released by handleInjectNtpTime()");
- }
- });
- }
-
+
private void handleRequestLocation(boolean independentFromGnss) {
if (isRequestLocationRateLimited()) {
if (DEBUG) {
@@ -2006,7 +1950,7 @@
mEngineCapabilities = capabilities;
if (hasCapability(GPS_CAPABILITY_ON_DEMAND_TIME)) {
- mOnDemandTimeInjection = true;
+ mNtpTimeHelper.enablePeriodicTimeInjection();
requestUtcTime();
}
@@ -2467,7 +2411,7 @@
handleReleaseSuplConnection(msg.arg1);
break;
case INJECT_NTP_TIME:
- handleInjectNtpTime();
+ mNtpTimeHelper.retrieveAndInjectNtpTime();
break;
case REQUEST_LOCATION:
handleRequestLocation((boolean) msg.obj);
@@ -2475,9 +2419,6 @@
case DOWNLOAD_XTRA_DATA:
handleDownloadXtraData();
break;
- case INJECT_NTP_TIME_FINISHED:
- mInjectNtpTimePending = STATE_IDLE;
- break;
case DOWNLOAD_XTRA_DATA_FINISHED:
mDownloadXtraDataPending = STATE_IDLE;
break;
@@ -2808,8 +2749,6 @@
return "REQUEST_LOCATION";
case DOWNLOAD_XTRA_DATA:
return "DOWNLOAD_XTRA_DATA";
- case INJECT_NTP_TIME_FINISHED:
- return "INJECT_NTP_TIME_FINISHED";
case DOWNLOAD_XTRA_DATA_FINISHED:
return "DOWNLOAD_XTRA_DATA_FINISHED";
case UPDATE_LOCATION:
@@ -2856,36 +2795,6 @@
pw.append(s);
}
- /**
- * A simple implementation of exponential backoff.
- */
- private static final class BackOff {
- private static final int MULTIPLIER = 2;
- private final long mInitIntervalMillis;
- private final long mMaxIntervalMillis;
- private long mCurrentIntervalMillis;
-
- public BackOff(long initIntervalMillis, long maxIntervalMillis) {
- mInitIntervalMillis = initIntervalMillis;
- mMaxIntervalMillis = maxIntervalMillis;
-
- mCurrentIntervalMillis = mInitIntervalMillis / MULTIPLIER;
- }
-
- public long nextBackoffMillis() {
- if (mCurrentIntervalMillis > mMaxIntervalMillis) {
- return mMaxIntervalMillis;
- }
-
- mCurrentIntervalMillis *= MULTIPLIER;
- return mCurrentIntervalMillis;
- }
-
- public void reset() {
- mCurrentIntervalMillis = mInitIntervalMillis / MULTIPLIER;
- }
- }
-
// preallocated to avoid memory allocation in reportNmea()
private byte[] mNmeaBuffer = new byte[120];
@@ -3008,6 +2917,8 @@
private static native boolean native_set_emergency_supl_pdn(int emergencySuplPdn);
+ private static native boolean native_set_satellite_blacklist(int[] constellations, int[] svIds);
+
// GNSS Batching
private static native int native_get_batch_size();
@@ -3022,3 +2933,4 @@
private static native void native_cleanup_batching();
}
+
diff --git a/services/core/java/com/android/server/location/GnssSatelliteBlacklistHelper.java b/services/core/java/com/android/server/location/GnssSatelliteBlacklistHelper.java
new file mode 100644
index 0000000..77951aa
--- /dev/null
+++ b/services/core/java/com/android/server/location/GnssSatelliteBlacklistHelper.java
@@ -0,0 +1,102 @@
+package com.android.server.location;
+
+import android.content.ContentResolver;
+import android.content.Context;
+import android.database.ContentObserver;
+import android.os.Handler;
+import android.os.Looper;
+import android.os.UserHandle;
+import android.provider.Settings;
+import android.util.Log;
+
+import com.android.internal.annotations.VisibleForTesting;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * Detects blacklist change and updates the blacklist.
+ */
+class GnssSatelliteBlacklistHelper {
+
+ private static final String TAG = "GnssBlacklistHelper";
+ private static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG);
+ private static final String BLACKLIST_DELIMITER = ",";
+
+ private final Context mContext;
+ private final GnssSatelliteBlacklistCallback mCallback;
+
+ interface GnssSatelliteBlacklistCallback {
+ void onUpdateSatelliteBlacklist(int[] constellations, int[] svids);
+ }
+
+ GnssSatelliteBlacklistHelper(Context context, Looper looper,
+ GnssSatelliteBlacklistCallback callback) {
+ mContext = context;
+ mCallback = callback;
+ ContentObserver contentObserver = new ContentObserver(new Handler(looper)) {
+ @Override
+ public void onChange(boolean selfChange) {
+ updateSatelliteBlacklist();
+ }
+ };
+ mContext.getContentResolver().registerContentObserver(
+ Settings.Global.getUriFor(
+ Settings.Global.GNSS_SATELLITE_BLACKLIST),
+ true,
+ contentObserver, UserHandle.USER_ALL);
+ }
+
+ void updateSatelliteBlacklist() {
+ ContentResolver resolver = mContext.getContentResolver();
+ String blacklist = Settings.Global.getString(
+ resolver,
+ Settings.Global.GNSS_SATELLITE_BLACKLIST);
+ if (blacklist == null) {
+ blacklist = "";
+ }
+ if (DEBUG) {
+ Log.d(TAG, String.format("Update GNSS satellite blacklist: %s", blacklist));
+ }
+
+ List<Integer> blacklistValues;
+ try {
+ blacklistValues = parseSatelliteBlacklist(blacklist);
+ } catch (NumberFormatException e) {
+ Log.e(TAG, "Exception thrown when parsing blacklist string.", e);
+ return;
+ }
+
+ if (blacklistValues.size() % 2 != 0) {
+ Log.e(TAG, "blacklist string has odd number of values."
+ + "Aborting updateSatelliteBlacklist");
+ return;
+ }
+
+ int length = blacklistValues.size() / 2;
+ int[] constellations = new int[length];
+ int[] svids = new int[length];
+ for (int i = 0; i < length; i++) {
+ constellations[i] = blacklistValues.get(i * 2);
+ svids[i] = blacklistValues.get(i * 2 + 1);
+ }
+ mCallback.onUpdateSatelliteBlacklist(constellations, svids);
+ }
+
+ @VisibleForTesting
+ static List<Integer> parseSatelliteBlacklist(String blacklist) throws NumberFormatException {
+ String[] strings = blacklist.split(BLACKLIST_DELIMITER);
+ List<Integer> parsed = new ArrayList<>(strings.length);
+ for (String string : strings) {
+ string = string.trim();
+ if (!"".equals(string)) {
+ int value = Integer.parseInt(string);
+ if (value < 0) {
+ throw new NumberFormatException("Negative value is invalid.");
+ }
+ parsed.add(value);
+ }
+ }
+ return parsed;
+ }
+}
diff --git a/services/core/java/com/android/server/location/NtpTimeHelper.java b/services/core/java/com/android/server/location/NtpTimeHelper.java
new file mode 100644
index 0000000..296b500
--- /dev/null
+++ b/services/core/java/com/android/server/location/NtpTimeHelper.java
@@ -0,0 +1,191 @@
+package com.android.server.location;
+
+import android.content.Context;
+import android.net.ConnectivityManager;
+import android.net.NetworkInfo;
+import android.os.Handler;
+import android.os.Looper;
+import android.os.PowerManager;
+import android.os.PowerManager.WakeLock;
+import android.util.Log;
+import android.util.NtpTrustedTime;
+
+import com.android.internal.annotations.GuardedBy;
+import com.android.internal.annotations.VisibleForTesting;
+
+import java.util.Date;
+
+/**
+ * Handles inject NTP time to GNSS.
+ *
+ * <p>The client is responsible to call {@link #onNetworkAvailable()} when network is available
+ * for retrieving NTP Time.
+ */
+class NtpTimeHelper {
+
+ private static final String TAG = "NtpTimeHelper";
+ private static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG);
+
+ // states for injecting ntp
+ private static final int STATE_PENDING_NETWORK = 0;
+ private static final int STATE_RETRIEVING_AND_INJECTING = 1;
+ private static final int STATE_IDLE = 2;
+
+ // how often to request NTP time, in milliseconds
+ // current setting 24 hours
+ @VisibleForTesting
+ static final long NTP_INTERVAL = 24 * 60 * 60 * 1000;
+
+ // how long to wait if we have a network error in NTP
+ // the initial value of the exponential backoff
+ // current setting - 5 minutes
+ @VisibleForTesting
+ static final long RETRY_INTERVAL = 5 * 60 * 1000;
+ // how long to wait if we have a network error in NTP
+ // the max value of the exponential backoff
+ // current setting - 4 hours
+ private static final long MAX_RETRY_INTERVAL = 4 * 60 * 60 * 1000;
+
+ private static final long WAKELOCK_TIMEOUT_MILLIS = 60 * 1000;
+ private static final String WAKELOCK_KEY = "NtpTimeHelper";
+
+ private final ExponentialBackOff mNtpBackOff = new ExponentialBackOff(RETRY_INTERVAL,
+ MAX_RETRY_INTERVAL);
+
+ private final ConnectivityManager mConnMgr;
+ private final NtpTrustedTime mNtpTime;
+ private final WakeLock mWakeLock;
+ private final Handler mHandler;
+
+ @GuardedBy("this")
+ private final InjectNtpTimeCallback mCallback;
+
+ // flags to trigger NTP when network becomes available
+ // initialized to STATE_PENDING_NETWORK so we do NTP when the network comes up after booting
+ @GuardedBy("this")
+ private int mInjectNtpTimeState = STATE_PENDING_NETWORK;
+
+ // set to true if the GPS engine requested on-demand NTP time requests
+ @GuardedBy("this")
+ private boolean mOnDemandTimeInjection;
+
+ interface InjectNtpTimeCallback {
+ void injectTime(long time, long timeReference, int uncertainty);
+ }
+
+ @VisibleForTesting
+ NtpTimeHelper(Context context, Looper looper, InjectNtpTimeCallback callback,
+ NtpTrustedTime ntpTime) {
+ mConnMgr = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
+ mCallback = callback;
+ mNtpTime = ntpTime;
+ mHandler = new Handler(looper);
+ PowerManager powerManager = (PowerManager) context.getSystemService(Context.POWER_SERVICE);
+ mWakeLock = powerManager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, WAKELOCK_KEY);
+ }
+
+ NtpTimeHelper(Context context, Looper looper, InjectNtpTimeCallback callback) {
+ this(context, looper, callback, NtpTrustedTime.getInstance(context));
+ }
+
+ synchronized void enablePeriodicTimeInjection() {
+ mOnDemandTimeInjection = true;
+ }
+
+ synchronized void onNetworkAvailable() {
+ if (mInjectNtpTimeState == STATE_PENDING_NETWORK) {
+ retrieveAndInjectNtpTime();
+ }
+ }
+
+ /**
+ * @return {@code true} if there is a network available for outgoing connections,
+ * {@code false} otherwise.
+ */
+ private boolean isNetworkConnected() {
+ NetworkInfo activeNetworkInfo = mConnMgr.getActiveNetworkInfo();
+ return activeNetworkInfo != null && activeNetworkInfo.isConnected();
+ }
+
+ synchronized void retrieveAndInjectNtpTime() {
+ if (mInjectNtpTimeState == STATE_RETRIEVING_AND_INJECTING) {
+ // already downloading data
+ return;
+ }
+ if (!isNetworkConnected()) {
+ // try again when network is up
+ mInjectNtpTimeState = STATE_PENDING_NETWORK;
+ return;
+ }
+ mInjectNtpTimeState = STATE_RETRIEVING_AND_INJECTING;
+
+ // hold wake lock while task runs
+ mWakeLock.acquire(WAKELOCK_TIMEOUT_MILLIS);
+ new Thread(this::blockingGetNtpTimeAndInject).start();
+ }
+
+ /** {@link NtpTrustedTime#forceRefresh} is a blocking network operation. */
+ private void blockingGetNtpTimeAndInject() {
+ long delay;
+
+ // force refresh NTP cache when outdated
+ boolean refreshSuccess = true;
+ if (mNtpTime.getCacheAge() >= NTP_INTERVAL) {
+ // Blocking network operation.
+ refreshSuccess = mNtpTime.forceRefresh();
+ }
+
+ synchronized (this) {
+ mInjectNtpTimeState = STATE_IDLE;
+
+ // only update when NTP time is fresh
+ // If refreshSuccess is false, cacheAge does not drop down.
+ if (mNtpTime.getCacheAge() < NTP_INTERVAL) {
+ long time = mNtpTime.getCachedNtpTime();
+ long timeReference = mNtpTime.getCachedNtpTimeReference();
+ long certainty = mNtpTime.getCacheCertainty();
+
+ if (DEBUG) {
+ long now = System.currentTimeMillis();
+ Log.d(TAG, "NTP server returned: "
+ + time + " (" + new Date(time)
+ + ") reference: " + timeReference
+ + " certainty: " + certainty
+ + " system time offset: " + (time - now));
+ }
+
+ // Ok to cast to int, as can't rollover in practice
+ mHandler.post(() -> mCallback.injectTime(time, timeReference, (int) certainty));
+
+ delay = NTP_INTERVAL;
+ mNtpBackOff.reset();
+ } else {
+ Log.e(TAG, "requestTime failed");
+ delay = mNtpBackOff.nextBackoffMillis();
+ }
+
+ if (DEBUG) {
+ Log.d(TAG, String.format(
+ "onDemandTimeInjection=%s, refreshSuccess=%s, delay=%s",
+ mOnDemandTimeInjection,
+ refreshSuccess,
+ delay));
+ }
+ // TODO(b/73893222): reconcile Capabilities bit 'on demand' name vs. de facto periodic
+ // injection.
+ if (mOnDemandTimeInjection || !refreshSuccess) {
+ /* Schedule next NTP injection.
+ * Since this is delayed, the wake lock is released right away, and will be held
+ * again when the delayed task runs.
+ */
+ mHandler.postDelayed(this::retrieveAndInjectNtpTime, delay);
+ }
+ }
+ try {
+ // release wake lock held by task
+ mWakeLock.release();
+ } catch (Exception e) {
+ // This happens when the WakeLock is already released.
+ }
+ }
+}
diff --git a/services/core/java/com/android/server/locksettings/recoverablekeystore/PlatformKeyManager.java b/services/core/java/com/android/server/locksettings/recoverablekeystore/PlatformKeyManager.java
index e5ff5b8..52394d2 100644
--- a/services/core/java/com/android/server/locksettings/recoverablekeystore/PlatformKeyManager.java
+++ b/services/core/java/com/android/server/locksettings/recoverablekeystore/PlatformKeyManager.java
@@ -375,6 +375,8 @@
throws NoSuchAlgorithmException, KeyStoreException {
String encryptAlias = getEncryptAlias(userId, generationId);
String decryptAlias = getDecryptAlias(userId, generationId);
+ // SecretKey implementation doesn't provide reliable way to destroy the secret
+ // so it may live in memory for some time.
SecretKey secretKey = generateAesKey();
// Store decryption key first since it is more likely to fail.
@@ -398,8 +400,6 @@
.build());
setGenerationId(userId, generationId);
-
- // TODO: Use a reliable way to destroy the temporary secretKey in memory.
}
/**
diff --git a/services/core/java/com/android/server/locksettings/recoverablekeystore/RecoverableKeyGenerator.java b/services/core/java/com/android/server/locksettings/recoverablekeystore/RecoverableKeyGenerator.java
index 7ebe8bf..396862d 100644
--- a/services/core/java/com/android/server/locksettings/recoverablekeystore/RecoverableKeyGenerator.java
+++ b/services/core/java/com/android/server/locksettings/recoverablekeystore/RecoverableKeyGenerator.java
@@ -29,7 +29,6 @@
import javax.crypto.SecretKey;
import javax.crypto.spec.SecretKeySpec;
-// TODO: Rename RecoverableKeyGenerator to RecoverableKeyManager as it can import a key too now
/**
* Generates/imports keys and stores them both in AndroidKeyStore and on disk, in wrapped form.
*
diff --git a/services/core/java/com/android/server/locksettings/recoverablekeystore/RecoverableKeyStoreManager.java b/services/core/java/com/android/server/locksettings/recoverablekeystore/RecoverableKeyStoreManager.java
index a6ee7e1..c484251 100644
--- a/services/core/java/com/android/server/locksettings/recoverablekeystore/RecoverableKeyStoreManager.java
+++ b/services/core/java/com/android/server/locksettings/recoverablekeystore/RecoverableKeyStoreManager.java
@@ -47,12 +47,12 @@
import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.util.HexDump;
import com.android.internal.util.Preconditions;
-import com.android.server.locksettings.recoverablekeystore.certificate.CertUtils;
-import com.android.server.locksettings.recoverablekeystore.certificate.SigXml;
-import com.android.server.locksettings.recoverablekeystore.storage.ApplicationKeyStorage;
import com.android.server.locksettings.recoverablekeystore.certificate.CertParsingException;
+import com.android.server.locksettings.recoverablekeystore.certificate.CertUtils;
import com.android.server.locksettings.recoverablekeystore.certificate.CertValidationException;
import com.android.server.locksettings.recoverablekeystore.certificate.CertXml;
+import com.android.server.locksettings.recoverablekeystore.certificate.SigXml;
+import com.android.server.locksettings.recoverablekeystore.storage.ApplicationKeyStorage;
import com.android.server.locksettings.recoverablekeystore.storage.RecoverableKeyStoreDb;
import com.android.server.locksettings.recoverablekeystore.storage.RecoverySessionStorage;
import com.android.server.locksettings.recoverablekeystore.storage.RecoverySnapshotStorage;
@@ -298,20 +298,6 @@
initRecoveryService(rootCertificateAlias, recoveryServiceCertFile);
}
- private PublicKey parseEcPublicKey(@NonNull byte[] bytes) throws ServiceSpecificException {
- try {
- KeyFactory kf = KeyFactory.getInstance("EC");
- X509EncodedKeySpec pkSpec = new X509EncodedKeySpec(bytes);
- return kf.generatePublic(pkSpec);
- } catch (NoSuchAlgorithmException e) {
- Log.wtf(TAG, "EC algorithm not available. AOSP must support this.", e);
- throw new ServiceSpecificException(ERROR_SERVICE_INTERNAL_ERROR, e.getMessage());
- } catch (InvalidKeySpecException e) {
- throw new ServiceSpecificException(
- ERROR_BAD_CERTIFICATE_FORMAT, "Not a valid X509 certificate.");
- }
- }
-
/**
* Gets all data necessary to recover application keys on new device.
*
@@ -750,8 +736,6 @@
int uid = Binder.getCallingUid();
int userId = UserHandle.getCallingUserId();
- // TODO: Refactor RecoverableKeyGenerator to wrap the PlatformKey logic
-
PlatformEncryptionKey encryptionKey;
try {
encryptionKey = mPlatformKeyManager.getEncryptKey(userId);
diff --git a/services/core/java/com/android/server/locksettings/recoverablekeystore/storage/RecoverableKeyStoreDb.java b/services/core/java/com/android/server/locksettings/recoverablekeystore/storage/RecoverableKeyStoreDb.java
index 53c972f..7c4360e 100644
--- a/services/core/java/com/android/server/locksettings/recoverablekeystore/storage/RecoverableKeyStoreDb.java
+++ b/services/core/java/com/android/server/locksettings/recoverablekeystore/storage/RecoverableKeyStoreDb.java
@@ -291,7 +291,7 @@
}
/**
- * Sets the {@code generationId} of the platform key for the account owned by {@code userId}.
+ * Sets the {@code generationId} of the platform key for user {@code userId}.
*
* @return The primary key ID of the relation.
*/
@@ -630,7 +630,6 @@
* @hide
*/
public long setActiveRootOfTrust(int userId, int uid, @Nullable String rootAlias) {
- // TODO: Call getDefaultCertificateAliasIfEmpty() here too?
SQLiteDatabase db = mKeyStoreDbHelper.getWritableDatabase();
ContentValues values = new ContentValues();
values.put(RecoveryServiceMetadataEntry.COLUMN_NAME_ACTIVE_ROOT_OF_TRUST, rootAlias);
diff --git a/services/core/java/com/android/server/media/MediaSessionService.java b/services/core/java/com/android/server/media/MediaSessionService.java
index 6413ba9..a3c6c80 100644
--- a/services/core/java/com/android/server/media/MediaSessionService.java
+++ b/services/core/java/com/android/server/media/MediaSessionService.java
@@ -1515,6 +1515,24 @@
final int uid = Binder.getCallingUid();
final long token = Binder.clearCallingIdentity();
try {
+ int controllerUserId = UserHandle.getUserId(controllerUid);
+ int controllerUidFromPackageName;
+ try {
+ controllerUidFromPackageName = getContext().getPackageManager()
+ .getPackageUidAsUser(controllerPackageName, controllerUserId);
+ } catch (NameNotFoundException e) {
+ if (DEBUG) {
+ Log.d(TAG, "Package " + controllerPackageName + " doesn't exist");
+ }
+ return false;
+ }
+ if (controllerUidFromPackageName != controllerUid) {
+ if (DEBUG) {
+ Log.d(TAG, "Package name " + controllerPackageName
+ + " doesn't match with the uid " + controllerUid);
+ }
+ return false;
+ }
return hasMediaControlPermission(UserHandle.getUserId(uid), controllerPackageName,
controllerPid, controllerUid);
} finally {
diff --git a/services/core/java/com/android/server/net/NetworkPolicyManagerService.java b/services/core/java/com/android/server/net/NetworkPolicyManagerService.java
index 29d2e55..224d085 100644
--- a/services/core/java/com/android/server/net/NetworkPolicyManagerService.java
+++ b/services/core/java/com/android/server/net/NetworkPolicyManagerService.java
@@ -362,6 +362,7 @@
private static final int MSG_RESET_FIREWALL_RULES_BY_UID = 15;
private static final int MSG_SUBSCRIPTION_OVERRIDE = 16;
private static final int MSG_METERED_RESTRICTED_PACKAGES_CHANGED = 17;
+ private static final int MSG_SET_NETWORK_TEMPLATE_ENABLED = 18;
private static final int UID_MSG_STATE_CHANGED = 100;
private static final int UID_MSG_GONE = 101;
@@ -1566,6 +1567,13 @@
* {@link NetworkTemplate}.
*/
private void setNetworkTemplateEnabled(NetworkTemplate template, boolean enabled) {
+ // Don't call setNetworkTemplateEnabledInner() directly because we may have a lock
+ // held. Call it via the handler.
+ mHandler.obtainMessage(MSG_SET_NETWORK_TEMPLATE_ENABLED, enabled ? 1 : 0, 0, template)
+ .sendToTarget();
+ }
+
+ private void setNetworkTemplateEnabledInner(NetworkTemplate template, boolean enabled) {
// TODO: reach into ConnectivityManager to proactively disable bringing
// up this network, since we know that traffic will be blocked.
@@ -4182,6 +4190,12 @@
setMeteredRestrictedPackagesInternal(packageNames, userId);
return true;
}
+ case MSG_SET_NETWORK_TEMPLATE_ENABLED: {
+ final NetworkTemplate template = (NetworkTemplate) msg.obj;
+ final boolean enabled = msg.arg1 != 0;
+ setNetworkTemplateEnabledInner(template, enabled);
+ return true;
+ }
default: {
return false;
}
diff --git a/services/core/java/com/android/server/om/OverlayManagerSettings.java b/services/core/java/com/android/server/om/OverlayManagerSettings.java
index 863045c..e176351 100644
--- a/services/core/java/com/android/server/om/OverlayManagerSettings.java
+++ b/services/core/java/com/android/server/om/OverlayManagerSettings.java
@@ -179,15 +179,19 @@
List<OverlayInfo> getOverlaysForTarget(@NonNull final String targetPackageName,
final int userId) {
+ // Static RROs targeting "android" are loaded from AssetManager, and so they should be
+ // ignored in OverlayManagerService.
return selectWhereTarget(targetPackageName, userId)
- .filter((i) -> !i.isStatic())
+ .filter((i) -> !(i.isStatic() && "android".equals(i.getTargetPackageName())))
.map(SettingsItem::getOverlayInfo)
.collect(Collectors.toList());
}
ArrayMap<String, List<OverlayInfo>> getOverlaysForUser(final int userId) {
+ // Static RROs targeting "android" are loaded from AssetManager, and so they should be
+ // ignored in OverlayManagerService.
return selectWhereUser(userId)
- .filter((i) -> !i.isStatic())
+ .filter((i) -> !(i.isStatic() && "android".equals(i.getTargetPackageName())))
.map(SettingsItem::getOverlayInfo)
.collect(Collectors.groupingBy(info -> info.targetPackageName, ArrayMap::new,
Collectors.toList()));
diff --git a/services/core/java/com/android/server/pm/LauncherAppsService.java b/services/core/java/com/android/server/pm/LauncherAppsService.java
index 8e78703f..595de9e 100644
--- a/services/core/java/com/android/server/pm/LauncherAppsService.java
+++ b/services/core/java/com/android/server/pm/LauncherAppsService.java
@@ -39,6 +39,7 @@
import android.content.pm.ShortcutInfo;
import android.content.pm.ShortcutServiceInternal;
import android.content.pm.ShortcutServiceInternal.ShortcutChangeListener;
+import android.content.pm.UserInfo;
import android.graphics.Rect;
import android.net.Uri;
import android.os.Binder;
@@ -49,6 +50,7 @@
import android.os.RemoteCallbackList;
import android.os.RemoteException;
import android.os.UserHandle;
+import android.os.UserManager;
import android.os.UserManagerInternal;
import android.provider.Settings;
import android.util.Log;
@@ -101,6 +103,7 @@
private static final boolean DEBUG = false;
private static final String TAG = "LauncherAppsService";
private final Context mContext;
+ private final UserManager mUm;
private final UserManagerInternal mUserManagerInternal;
private final ActivityManagerInternal mActivityManagerInternal;
private final ShortcutServiceInternal mShortcutServiceInternal;
@@ -113,6 +116,7 @@
public LauncherAppsImpl(Context context) {
mContext = context;
+ mUm = (UserManager) mContext.getSystemService(Context.USER_SERVICE);
mUserManagerInternal = Preconditions.checkNotNull(
LocalServices.getService(UserManagerInternal.class));
mActivityManagerInternal = Preconditions.checkNotNull(
@@ -233,6 +237,22 @@
* group.
*/
private boolean canAccessProfile(int targetUserId, String message) {
+ final int callingUserId = injectCallingUserId();
+
+ if (targetUserId == callingUserId) return true;
+
+ long ident = injectClearCallingIdentity();
+ try {
+ final UserInfo callingUserInfo = mUm.getUserInfo(callingUserId);
+ if (callingUserInfo != null && callingUserInfo.isManagedProfile()) {
+ Slog.w(TAG, message + " for another profile "
+ + targetUserId + " from " + callingUserId + " not allowed");
+ return false;
+ }
+ } finally {
+ injectRestoreCallingIdentity(ident);
+ }
+
return mUserManagerInternal.isProfileAccessible(injectCallingUserId(), targetUserId,
message, true);
}
diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java
index 2c98da3..26d4037 100644
--- a/services/core/java/com/android/server/pm/PackageManagerService.java
+++ b/services/core/java/com/android/server/pm/PackageManagerService.java
@@ -274,6 +274,7 @@
import com.android.internal.annotations.GuardedBy;
import com.android.internal.app.IMediaContainerService;
import com.android.internal.app.ResolverActivity;
+import com.android.internal.app.SuspendedAppActivity;
import com.android.internal.content.NativeLibraryHelper;
import com.android.internal.content.PackageHelper;
import com.android.internal.logging.MetricsLogger;
@@ -3946,7 +3947,7 @@
ai.uid = UserHandle.getUid(userId, ps.appId);
ai.primaryCpuAbi = ps.primaryCpuAbiString;
ai.secondaryCpuAbi = ps.secondaryCpuAbiString;
- ai.versionCode = ps.versionCode;
+ ai.setVersionCode(ps.versionCode);
ai.flags = ps.pkgFlags;
ai.privateFlags = ps.pkgPrivateFlags;
pi.applicationInfo = PackageParser.generateApplicationInfo(ai, flags, state, userId);
@@ -5943,8 +5944,8 @@
@Override
public ResolveInfo resolveIntent(Intent intent, String resolvedType,
int flags, int userId) {
- return resolveIntentInternal(
- intent, resolvedType, flags, userId, false /*resolveForStart*/);
+ return resolveIntentInternal(intent, resolvedType, flags, userId, false,
+ Binder.getCallingUid());
}
/**
@@ -5953,19 +5954,19 @@
* since we need to allow the system to start any installed application.
*/
private ResolveInfo resolveIntentInternal(Intent intent, String resolvedType,
- int flags, int userId, boolean resolveForStart) {
+ int flags, int userId, boolean resolveForStart, int filterCallingUid) {
try {
Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "resolveIntent");
if (!sUserManager.exists(userId)) return null;
final int callingUid = Binder.getCallingUid();
- flags = updateFlagsForResolve(flags, userId, intent, callingUid, resolveForStart);
+ flags = updateFlagsForResolve(flags, userId, intent, filterCallingUid, resolveForStart);
mPermissionManager.enforceCrossUserPermission(callingUid, userId,
false /*requireFullPermission*/, false /*checkShell*/, "resolve intent");
Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "queryIntentActivities");
final List<ResolveInfo> query = queryIntentActivitiesInternal(intent, resolvedType,
- flags, callingUid, userId, resolveForStart, true /*allowDynamicSplits*/);
+ flags, filterCallingUid, userId, resolveForStart, true /*allowDynamicSplits*/);
Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER);
final ResolveInfo bestChoice =
@@ -6773,7 +6774,7 @@
// the instant application, we'll do the right thing.
final ApplicationInfo ai = localInstantApp.activityInfo.applicationInfo;
auxiliaryResponse = new AuxiliaryResolveInfo(null /* failureActivity */,
- ai.packageName, ai.versionCode, null /* splitName */);
+ ai.packageName, ai.longVersionCode, null /* splitName */);
}
}
if (intent.isWebIntent() && auxiliaryResponse == null) {
@@ -6957,7 +6958,7 @@
installerInfo.auxiliaryInfo = new AuxiliaryResolveInfo(
installFailureActivity,
info.activityInfo.packageName,
- info.activityInfo.applicationInfo.versionCode,
+ info.activityInfo.applicationInfo.longVersionCode,
info.activityInfo.splitName);
// add a non-generic filter
installerInfo.filter = new IntentFilter();
@@ -7703,7 +7704,7 @@
installerInfo.auxiliaryInfo = new AuxiliaryResolveInfo(
null /* installFailureActivity */,
info.serviceInfo.packageName,
- info.serviceInfo.applicationInfo.versionCode,
+ info.serviceInfo.applicationInfo.longVersionCode,
info.serviceInfo.splitName);
// add a non-generic filter
installerInfo.filter = new IntentFilter();
@@ -7821,7 +7822,7 @@
installerInfo.auxiliaryInfo = new AuxiliaryResolveInfo(
null /*failureActivity*/,
info.providerInfo.packageName,
- info.providerInfo.applicationInfo.versionCode,
+ info.providerInfo.applicationInfo.longVersionCode,
info.providerInfo.splitName);
// add a non-generic filter
installerInfo.filter = new IntentFilter();
@@ -8700,7 +8701,7 @@
disabledPkgSetting /* pkgSetting */, null /* disabledPkgSetting */,
null /* originalPkgSetting */, null, parseFlags, scanFlags,
(pkg == mPlatformPackage), user);
- applyPolicy(pkg, parseFlags, scanFlags);
+ applyPolicy(pkg, parseFlags, scanFlags, mPlatformPackage);
scanPackageOnlyLI(request, mFactoryTest, -1L);
}
}
@@ -10019,7 +10020,7 @@
scanFlags = adjustScanFlags(scanFlags, pkgSetting, disabledPkgSetting, user, pkg);
synchronized (mPackages) {
- applyPolicy(pkg, parseFlags, scanFlags);
+ applyPolicy(pkg, parseFlags, scanFlags, mPlatformPackage);
assertPackageIsValid(pkg, parseFlags, scanFlags);
SharedUserSetting sharedUserSetting = null;
@@ -10699,7 +10700,7 @@
* ideally be static, but, it requires locks to read system state.
*/
private static void applyPolicy(PackageParser.Package pkg, final @ParseFlags int parseFlags,
- final @ScanFlags int scanFlags) {
+ final @ScanFlags int scanFlags, PackageParser.Package platformPkg) {
if ((scanFlags & SCAN_AS_SYSTEM) != 0) {
pkg.applicationInfo.flags |= ApplicationInfo.FLAG_SYSTEM;
if (pkg.applicationInfo.isDirectBootAware()) {
@@ -10785,6 +10786,15 @@
pkg.applicationInfo.privateFlags |= ApplicationInfo.PRIVATE_FLAG_PRODUCT;
}
+ // Check if the package is signed with the same key as the platform package.
+ if (PLATFORM_PACKAGE_NAME.equals(pkg.packageName) ||
+ (platformPkg != null && compareSignatures(
+ platformPkg.mSigningDetails.signatures,
+ pkg.mSigningDetails.signatures) == PackageManager.SIGNATURE_MATCH)) {
+ pkg.applicationInfo.privateFlags |=
+ ApplicationInfo.PRIVATE_FLAG_SIGNED_WITH_PLATFORM_KEY;
+ }
+
if (!isSystemApp(pkg)) {
// Only system apps can use these features.
pkg.mOriginalPackages = null;
@@ -13997,8 +14007,8 @@
@Override
public String[] setPackagesSuspendedAsUser(String[] packageNames, boolean suspended,
- PersistableBundle appExtras, PersistableBundle launcherExtras, String callingPackage,
- int userId) {
+ PersistableBundle appExtras, PersistableBundle launcherExtras, String dialogMessage,
+ String callingPackage, int userId) {
try {
mContext.enforceCallingOrSelfPermission(android.Manifest.permission.SUSPEND_APPS, null);
} catch (SecurityException e) {
@@ -14046,7 +14056,7 @@
unactionedPackages.add(packageName);
continue;
}
- pkgSetting.setSuspended(suspended, callingPackage, appExtras,
+ pkgSetting.setSuspended(suspended, callingPackage, dialogMessage, appExtras,
launcherExtras, userId);
changedPackagesList.add(packageName);
}
@@ -14168,7 +14178,7 @@
for (int user : userIds) {
final PackageUserState pus = ps.readUserState(user);
if (pus.suspended && packageName.equals(pus.suspendingPackage)) {
- ps.setSuspended(false, null, null, null, user);
+ ps.setSuspended(false, null, null, null, null, user);
}
}
}
@@ -18902,6 +18912,7 @@
false /*hidden*/,
false /*suspended*/,
null, /*suspendingPackage*/
+ null, /*dialogMessage*/
null, /*suspendedAppExtras*/
null, /*suspendedLauncherExtras*/
false /*instantApp*/,
@@ -23786,6 +23797,30 @@
}
@Override
+ public boolean isPackageSuspended(String packageName, int userId) {
+ synchronized (mPackages) {
+ final PackageSetting ps = mSettings.mPackages.get(packageName);
+ return (ps != null) ? ps.getSuspended(userId) : false;
+ }
+ }
+
+ @Override
+ public String getSuspendingPackage(String suspendedPackage, int userId) {
+ synchronized (mPackages) {
+ final PackageSetting ps = mSettings.mPackages.get(suspendedPackage);
+ return (ps != null) ? ps.readUserState(userId).suspendingPackage : null;
+ }
+ }
+
+ @Override
+ public String getSuspendedDialogMessage(String suspendedPackage, int userId) {
+ synchronized (mPackages) {
+ final PackageSetting ps = mSettings.mPackages.get(suspendedPackage);
+ return (ps != null) ? ps.readUserState(userId).dialogMessage : null;
+ }
+ }
+
+ @Override
public int getPackageUid(String packageName, int flags, int userId) {
return PackageManagerService.this
.getPackageUid(packageName, flags, userId);
@@ -24007,9 +24042,9 @@
@Override
public ResolveInfo resolveIntent(Intent intent, String resolvedType,
- int flags, int userId, boolean resolveForStart) {
+ int flags, int userId, boolean resolveForStart, int filterCallingUid) {
return resolveIntentInternal(
- intent, resolvedType, flags, userId, resolveForStart);
+ intent, resolvedType, flags, userId, resolveForStart, filterCallingUid);
}
@Override
diff --git a/services/core/java/com/android/server/pm/PackageManagerShellCommand.java b/services/core/java/com/android/server/pm/PackageManagerShellCommand.java
index 28e32a5..a92fbb6 100644
--- a/services/core/java/com/android/server/pm/PackageManagerShellCommand.java
+++ b/services/core/java/com/android/server/pm/PackageManagerShellCommand.java
@@ -1505,6 +1505,7 @@
private int runSuspend(boolean suspendedState) {
final PrintWriter pw = getOutPrintWriter();
int userId = UserHandle.USER_SYSTEM;
+ String dialogMessage = null;
final PersistableBundle appExtras = new PersistableBundle();
final PersistableBundle launcherExtras = new PersistableBundle();
String opt;
@@ -1513,6 +1514,9 @@
case "--user":
userId = UserHandle.parseUserArg(getNextArgRequired());
break;
+ case "--dialogMessage":
+ dialogMessage = getNextArgRequired();
+ break;
case "--ael":
case "--aes":
case "--aed":
@@ -1553,7 +1557,7 @@
(Binder.getCallingUid() == Process.ROOT_UID) ? "root" : "com.android.shell";
try {
mInterface.setPackagesSuspendedAsUser(new String[]{packageName}, suspendedState,
- appExtras, launcherExtras, callingPackage, userId);
+ appExtras, launcherExtras, dialogMessage, callingPackage, userId);
pw.println("Package " + packageName + " new suspended state: "
+ mInterface.isPackageSuspendedForUser(packageName, userId));
return 0;
diff --git a/services/core/java/com/android/server/pm/PackageSettingBase.java b/services/core/java/com/android/server/pm/PackageSettingBase.java
index 008a81c..fd4c5e9 100644
--- a/services/core/java/com/android/server/pm/PackageSettingBase.java
+++ b/services/core/java/com/android/server/pm/PackageSettingBase.java
@@ -398,11 +398,12 @@
return readUserState(userId).suspended;
}
- void setSuspended(boolean suspended, String suspendingPackage, PersistableBundle appExtras,
- PersistableBundle launcherExtras, int userId) {
+ void setSuspended(boolean suspended, String suspendingPackage, String dialogMessage,
+ PersistableBundle appExtras, PersistableBundle launcherExtras, int userId) {
final PackageUserState existingUserState = modifyUserState(userId);
existingUserState.suspended = suspended;
existingUserState.suspendingPackage = suspended ? suspendingPackage : null;
+ existingUserState.dialogMessage = suspended ? dialogMessage : null;
existingUserState.suspendedAppExtras = suspended ? appExtras : null;
existingUserState.suspendedLauncherExtras = suspended ? launcherExtras : null;
}
@@ -425,8 +426,8 @@
void setUserState(int userId, long ceDataInode, int enabled, boolean installed, boolean stopped,
boolean notLaunched, boolean hidden, boolean suspended, String suspendingPackage,
- PersistableBundle suspendedAppExtras, PersistableBundle suspendedLauncherExtras,
- boolean instantApp,
+ String dialogMessage, PersistableBundle suspendedAppExtras,
+ PersistableBundle suspendedLauncherExtras, boolean instantApp,
boolean virtualPreload, String lastDisableAppCaller,
ArraySet<String> enabledComponents, ArraySet<String> disabledComponents,
int domainVerifState, int linkGeneration, int installReason,
@@ -440,6 +441,7 @@
state.hidden = hidden;
state.suspended = suspended;
state.suspendingPackage = suspendingPackage;
+ state.dialogMessage = dialogMessage;
state.suspendedAppExtras = suspendedAppExtras;
state.suspendedLauncherExtras = suspendedLauncherExtras;
state.lastDisableAppCaller = lastDisableAppCaller;
diff --git a/services/core/java/com/android/server/pm/Settings.java b/services/core/java/com/android/server/pm/Settings.java
index d0e8544..898ecf3 100644
--- a/services/core/java/com/android/server/pm/Settings.java
+++ b/services/core/java/com/android/server/pm/Settings.java
@@ -222,6 +222,7 @@
private static final String ATTR_HIDDEN = "hidden";
private static final String ATTR_SUSPENDED = "suspended";
private static final String ATTR_SUSPENDING_PACKAGE = "suspending-package";
+ private static final String ATTR_SUSPEND_DIALOG_MESSAGE = "suspend_dialog_message";
// Legacy, uninstall blocks are stored separately.
@Deprecated
private static final String ATTR_BLOCK_UNINSTALL = "blockUninstall";
@@ -734,6 +735,7 @@
false /*hidden*/,
false /*suspended*/,
null, /*suspendingPackage*/
+ null, /*dialogMessage*/
null, /*suspendedAppExtras*/
null, /*suspendedLauncherExtras*/
instantApp,
@@ -1628,6 +1630,7 @@
false /*hidden*/,
false /*suspended*/,
null, /*suspendingPackage*/
+ null, /*dialogMessage*/
null, /*suspendedAppExtras*/
null, /*suspendedLauncherExtras*/
false /*instantApp*/,
@@ -1704,6 +1707,8 @@
false);
String suspendingPackage = parser.getAttributeValue(null,
ATTR_SUSPENDING_PACKAGE);
+ final String dialogMessage = parser.getAttributeValue(null,
+ ATTR_SUSPEND_DIALOG_MESSAGE);
if (suspended && suspendingPackage == null) {
suspendingPackage = PLATFORM_PACKAGE_NAME;
}
@@ -1767,7 +1772,7 @@
setBlockUninstallLPw(userId, name, true);
}
ps.setUserState(userId, ceDataInode, enabled, installed, stopped, notLaunched,
- hidden, suspended, suspendingPackage, suspendedAppExtras,
+ hidden, suspended, suspendingPackage, dialogMessage, suspendedAppExtras,
suspendedLauncherExtras, instantApp, virtualPreload, enabledCaller,
enabledComponents, disabledComponents, verifState, linkGeneration,
installReason, harmfulAppWarning);
@@ -2077,7 +2082,14 @@
}
if (ustate.suspended) {
serializer.attribute(null, ATTR_SUSPENDED, "true");
- serializer.attribute(null, ATTR_SUSPENDING_PACKAGE, ustate.suspendingPackage);
+ if (ustate.suspendingPackage != null) {
+ serializer.attribute(null, ATTR_SUSPENDING_PACKAGE,
+ ustate.suspendingPackage);
+ }
+ if (ustate.dialogMessage != null) {
+ serializer.attribute(null, ATTR_SUSPEND_DIALOG_MESSAGE,
+ ustate.dialogMessage);
+ }
if (ustate.suspendedAppExtras != null) {
serializer.startTag(null, TAG_SUSPENDED_APP_EXTRAS);
try {
@@ -4750,8 +4762,11 @@
pw.print(" suspended=");
pw.print(ps.getSuspended(user.id));
if (ps.getSuspended(user.id)) {
+ final PackageUserState pus = ps.readUserState(user.id);
pw.print(" suspendingPackage=");
- pw.print(ps.readUserState(user.id).suspendingPackage);
+ pw.print(pus.suspendingPackage);
+ pw.print(" dialogMessage=");
+ pw.print(pus.dialogMessage);
}
pw.print(" stopped=");
pw.print(ps.getStopped(user.id));
diff --git a/services/core/java/com/android/server/pm/permission/BasePermission.java b/services/core/java/com/android/server/pm/permission/BasePermission.java
index bcf4b07..1d002ef 100644
--- a/services/core/java/com/android/server/pm/permission/BasePermission.java
+++ b/services/core/java/com/android/server/pm/permission/BasePermission.java
@@ -411,17 +411,23 @@
}
public @NonNull PermissionInfo generatePermissionInfo(int adjustedProtectionLevel, int flags) {
- final boolean protectionLevelChanged = protectionLevel != adjustedProtectionLevel;
- // if we return different protection level, don't use the cached info
- if (perm != null && !protectionLevelChanged) {
- return PackageParser.generatePermissionInfo(perm, flags);
+ PermissionInfo permissionInfo;
+ if (perm != null) {
+ final boolean protectionLevelChanged = protectionLevel != adjustedProtectionLevel;
+ permissionInfo = PackageParser.generatePermissionInfo(perm, flags);
+ if (protectionLevelChanged && permissionInfo == perm.info) {
+ // if we return different protection level, don't use the cached info
+ permissionInfo = new PermissionInfo(permissionInfo);
+ permissionInfo.protectionLevel = adjustedProtectionLevel;
+ }
+ return permissionInfo;
}
- final PermissionInfo pi = new PermissionInfo();
- pi.name = name;
- pi.packageName = sourcePackageName;
- pi.nonLocalizedLabel = name;
- pi.protectionLevel = protectionLevelChanged ? adjustedProtectionLevel : protectionLevel;
- return pi;
+ permissionInfo = new PermissionInfo();
+ permissionInfo.name = name;
+ permissionInfo.packageName = sourcePackageName;
+ permissionInfo.nonLocalizedLabel = name;
+ permissionInfo.protectionLevel = protectionLevel;
+ return permissionInfo;
}
public static boolean readLPw(@NonNull Map<String, BasePermission> out,
diff --git a/services/core/java/com/android/server/pm/permission/DefaultPermissionGrantPolicy.java b/services/core/java/com/android/server/pm/permission/DefaultPermissionGrantPolicy.java
index 518d464..4055a47 100644
--- a/services/core/java/com/android/server/pm/permission/DefaultPermissionGrantPolicy.java
+++ b/services/core/java/com/android/server/pm/permission/DefaultPermissionGrantPolicy.java
@@ -1052,7 +1052,8 @@
private PackageParser.Package getDefaultSystemHandlerActivityPackage(
Intent intent, int userId) {
ResolveInfo handler = mServiceInternal.resolveIntent(intent,
- intent.resolveType(mContext.getContentResolver()), DEFAULT_FLAGS, userId, false);
+ intent.resolveType(mContext.getContentResolver()), DEFAULT_FLAGS, userId, false,
+ Binder.getCallingUid());
if (handler == null || handler.activityInfo == null) {
return null;
}
@@ -1093,7 +1094,7 @@
ResolveInfo homeActivity = mServiceInternal.resolveIntent(homeIntent,
homeIntent.resolveType(mContext.getContentResolver()), DEFAULT_FLAGS,
- userId, false);
+ userId, false, Binder.getCallingUid());
if (homeActivity != null) {
continue;
}
diff --git a/services/core/java/com/android/server/stats/StatsCompanionService.java b/services/core/java/com/android/server/stats/StatsCompanionService.java
index d4625e9..5f2ac4f 100644
--- a/services/core/java/com/android/server/stats/StatsCompanionService.java
+++ b/services/core/java/com/android/server/stats/StatsCompanionService.java
@@ -273,7 +273,8 @@
// Add in all the apps for every user/profile.
for (UserInfo profile : users) {
- List<PackageInfo> pi = pm.getInstalledPackagesAsUser(0, profile.id);
+ List<PackageInfo> pi =
+ pm.getInstalledPackagesAsUser(PackageManager.MATCH_DISABLED_COMPONENTS, profile.id);
for (int j = 0; j < pi.size(); j++) {
if (pi.get(j).applicationInfo != null) {
uids.add(pi.get(j).applicationInfo.uid);
diff --git a/services/core/java/com/android/server/statusbar/StatusBarManagerService.java b/services/core/java/com/android/server/statusbar/StatusBarManagerService.java
index 8af1101..2db8039 100644
--- a/services/core/java/com/android/server/statusbar/StatusBarManagerService.java
+++ b/services/core/java/com/android/server/statusbar/StatusBarManagerService.java
@@ -23,7 +23,7 @@
import android.content.ComponentName;
import android.content.Context;
import android.graphics.Rect;
-import android.hardware.biometrics.IBiometricDialogReceiver;
+import android.hardware.biometrics.IBiometricPromptReceiver;
import android.os.Binder;
import android.os.Bundle;
import android.os.Handler;
@@ -547,7 +547,7 @@
}
@Override
- public void showFingerprintDialog(Bundle bundle, IBiometricDialogReceiver receiver) {
+ public void showFingerprintDialog(Bundle bundle, IBiometricPromptReceiver receiver) {
if (mBar != null) {
try {
mBar.showFingerprintDialog(bundle, receiver);
diff --git a/services/core/java/com/android/server/wm/RootWindowContainer.java b/services/core/java/com/android/server/wm/RootWindowContainer.java
index 52d8177..fd965fb 100644
--- a/services/core/java/com/android/server/wm/RootWindowContainer.java
+++ b/services/core/java/com/android/server/wm/RootWindowContainer.java
@@ -417,6 +417,14 @@
}, true /* traverseTopToBottom */);
}
+ void updateHiddenWhileSuspendedState(final ArraySet<String> packages, final boolean suspended) {
+ forAllWindows((w) -> {
+ if (packages.contains(w.getOwningPackage())) {
+ w.setHiddenWhileSuspended(suspended);
+ }
+ }, false);
+ }
+
void updateAppOpsState() {
forAllWindows((w) -> {
w.updateAppOpsState();
diff --git a/services/core/java/com/android/server/wm/WindowManagerService.java b/services/core/java/com/android/server/wm/WindowManagerService.java
index 28a57f5..0c9504f 100644
--- a/services/core/java/com/android/server/wm/WindowManagerService.java
+++ b/services/core/java/com/android/server/wm/WindowManagerService.java
@@ -128,6 +128,7 @@
import android.content.IntentFilter;
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageManager;
+import android.content.pm.PackageManagerInternal;
import android.content.res.Configuration;
import android.database.ContentObserver;
import android.graphics.Bitmap;
@@ -264,6 +265,7 @@
import java.net.Socket;
import java.text.DateFormat;
import java.util.ArrayList;
+import java.util.Arrays;
import java.util.Date;
import java.util.List;
/** {@hide} */
@@ -426,6 +428,7 @@
final ActivityManagerInternal mAmInternal;
final AppOpsManager mAppOps;
+ final PackageManagerInternal mPmInternal;
final DisplaySettings mDisplaySettings;
@@ -1006,6 +1009,22 @@
mAppOps.startWatchingMode(OP_SYSTEM_ALERT_WINDOW, null, opListener);
mAppOps.startWatchingMode(AppOpsManager.OP_TOAST_WINDOW, null, opListener);
+ mPmInternal = LocalServices.getService(PackageManagerInternal.class);
+ final IntentFilter suspendPackagesFilter = new IntentFilter();
+ suspendPackagesFilter.addAction(Intent.ACTION_PACKAGES_SUSPENDED);
+ suspendPackagesFilter.addAction(Intent.ACTION_PACKAGES_UNSUSPENDED);
+ context.registerReceiverAsUser(new BroadcastReceiver() {
+ @Override
+ public void onReceive(Context context, Intent intent) {
+ final String[] affectedPackages =
+ intent.getStringArrayExtra(Intent.EXTRA_CHANGED_PACKAGE_LIST);
+ final boolean suspended =
+ Intent.ACTION_PACKAGES_SUSPENDED.equals(intent.getAction());
+ updateHiddenWhileSuspendedState(new ArraySet<>(Arrays.asList(affectedPackages)),
+ suspended);
+ }
+ }, UserHandle.ALL, suspendPackagesFilter, null, null);
+
// Get persisted window scale setting
mWindowAnimationScaleSetting = Settings.Global.getFloat(context.getContentResolver(),
Settings.Global.WINDOW_ANIMATION_SCALE, mWindowAnimationScaleSetting);
@@ -1360,6 +1379,10 @@
win.initAppOpsState();
+ final boolean suspended = mPmInternal.isPackageSuspended(win.getOwningPackage(),
+ UserHandle.getUserId(win.getOwningUid()));
+ win.setHiddenWhileSuspended(suspended);
+
final boolean hideSystemAlertWindows = !mHidingNonSystemOverlayWindows.isEmpty();
win.setForceHideNonSystemOverlayWindowIfNeeded(hideSystemAlertWindows);
@@ -1619,6 +1642,8 @@
if (DEBUG_ADD_REMOVE) Slog.v(TAG_WM, "postWindowRemoveCleanupLocked: " + win);
mWindowMap.remove(win.mClient.asBinder());
+ markForSeamlessRotation(win, false);
+
win.resetAppOpsState();
if (mCurrentFocus == null) {
@@ -1683,6 +1708,12 @@
dc.computeImeTarget(true /* updateImeTarget */);
}
+ private void updateHiddenWhileSuspendedState(ArraySet<String> packages, boolean suspended) {
+ synchronized (mWindowMap) {
+ mRoot.updateHiddenWhileSuspendedState(packages, suspended);
+ }
+ }
+
private void updateAppOpsState() {
synchronized(mWindowMap) {
mRoot.updateAppOpsState();
diff --git a/services/core/java/com/android/server/wm/WindowState.java b/services/core/java/com/android/server/wm/WindowState.java
index f015889..84df128 100644
--- a/services/core/java/com/android/server/wm/WindowState.java
+++ b/services/core/java/com/android/server/wm/WindowState.java
@@ -20,6 +20,8 @@
import static android.app.AppOpsManager.MODE_ALLOWED;
import static android.app.AppOpsManager.MODE_DEFAULT;
import static android.app.AppOpsManager.OP_NONE;
+import static android.app.AppOpsManager.OP_SYSTEM_ALERT_WINDOW;
+import static android.app.AppOpsManager.OP_TOAST_WINDOW;
import static android.os.PowerManager.DRAW_WAKE_LOCK;
import static android.os.Trace.TRACE_TAG_WINDOW_MANAGER;
import static android.view.Display.DEFAULT_DISPLAY;
@@ -64,7 +66,6 @@
import static android.view.WindowManager.LayoutParams.TYPE_MAGNIFICATION_OVERLAY;
import static android.view.WindowManager.LayoutParams.TYPE_NAVIGATION_BAR;
import static android.view.WindowManager.LayoutParams.TYPE_NAVIGATION_BAR_PANEL;
-import static android.view.WindowManager.LayoutParams.TYPE_STATUS_BAR;
import static android.view.WindowManager.LayoutParams.TYPE_TOAST;
import static android.view.WindowManager.LayoutParams.TYPE_WALLPAPER;
import static android.view.WindowManager.LayoutParams.isSystemAlertWindowType;
@@ -267,6 +268,8 @@
* animation is done.
*/
boolean mPolicyVisibilityAfterAnim = true;
+ // overlay window is hidden because the owning app is suspended
+ private boolean mHiddenWhileSuspended;
private boolean mAppOpVisibility = true;
boolean mPermanentlyHidden; // the window should never be shown again
// This is a non-system overlay window that is currently force hidden.
@@ -2484,6 +2487,10 @@
// to handle their windows being removed from under them.
return false;
}
+ if (mHiddenWhileSuspended) {
+ // Being hidden due to owner package being suspended.
+ return false;
+ }
if (mForceHideNonSystemOverlayWindow) {
// This is an alert window that is currently force hidden.
return false;
@@ -2580,6 +2587,22 @@
}
}
+ void setHiddenWhileSuspended(boolean hide) {
+ if (mOwnerCanAddInternalSystemWindow
+ || (!isSystemAlertWindowType(mAttrs.type) && mAttrs.type != TYPE_TOAST)) {
+ return;
+ }
+ if (mHiddenWhileSuspended == hide) {
+ return;
+ }
+ mHiddenWhileSuspended = hide;
+ if (hide) {
+ hideLw(true, true);
+ } else {
+ showLw(true, true);
+ }
+ }
+
private void setAppOpVisibilityLw(boolean state) {
if (mAppOpVisibility != state) {
mAppOpVisibility = state;
@@ -3300,7 +3323,8 @@
pw.println(Integer.toHexString(mSystemUiVisibility));
}
if (!mPolicyVisibility || !mPolicyVisibilityAfterAnim || !mAppOpVisibility
- || isParentWindowHidden()|| mPermanentlyHidden || mForceHideNonSystemOverlayWindow) {
+ || isParentWindowHidden()|| mPermanentlyHidden || mForceHideNonSystemOverlayWindow
+ || mHiddenWhileSuspended) {
pw.print(prefix); pw.print("mPolicyVisibility=");
pw.print(mPolicyVisibility);
pw.print(" mPolicyVisibilityAfterAnim=");
@@ -3309,6 +3333,7 @@
pw.print(mAppOpVisibility);
pw.print(" parentHidden="); pw.print(isParentWindowHidden());
pw.print(" mPermanentlyHidden="); pw.print(mPermanentlyHidden);
+ pw.print(" mHiddenWhileSuspended="); pw.print(mHiddenWhileSuspended);
pw.print(" mForceHideNonSystemOverlayWindow="); pw.println(
mForceHideNonSystemOverlayWindow);
}
diff --git a/services/core/jni/BroadcastRadio/Tuner.cpp b/services/core/jni/BroadcastRadio/Tuner.cpp
index 36d2994..a04697f 100644
--- a/services/core/jni/BroadcastRadio/Tuner.cpp
+++ b/services/core/jni/BroadcastRadio/Tuner.cpp
@@ -90,11 +90,12 @@
bool mIsAudioConnected = false;
Band mBand;
wp<V1_0::IBroadcastRadio> mHalModule;
- wp<V1_1::IBroadcastRadio> mHalModule11;
sp<V1_0::ITuner> mHalTuner;
sp<V1_1::ITuner> mHalTuner11;
sp<HalDeathRecipient> mHalDeathRecipient;
+ sp<V1_1::IBroadcastRadio> getHalModule11() const;
+
private:
DISALLOW_COPY_AND_ASSIGN(TunerContext);
};
@@ -143,6 +144,16 @@
tunerCallback->hardwareFailure();
}
+sp<V1_1::IBroadcastRadio> TunerContext::getHalModule11() const {
+ auto halModule = mHalModule.promote();
+ if (halModule == nullptr) {
+ ALOGE("HAL module is gone");
+ return nullptr;
+ }
+
+ return V1_1::IBroadcastRadio::castFrom(halModule).withDefault(nullptr);
+}
+
// TODO(b/62713378): implement support for multiple tuners open at the same time
static void notifyAudioService(TunerContext& ctx, bool connected) {
if (!ctx.mWithAudio) return;
@@ -175,8 +186,6 @@
}
ctx.mHalModule = halModule;
- ctx.mHalModule11 = V1_1::IBroadcastRadio::castFrom(halModule).withDefault(nullptr);
-
ctx.mHalTuner = halTuner;
ctx.mHalTuner11 = V1_1::ITuner::castFrom(halTuner).withDefault(nullptr);
ALOGW_IF(ctx.mHalRev >= HalRevision::V1_1 && ctx.mHalTuner11 == nullptr,
@@ -388,18 +397,13 @@
lock_guard<mutex> lk(gContextMutex);
auto& ctx = getNativeContext(nativeContext);
- if (ctx.mHalModule11 == nullptr) {
+ auto halModule = ctx.getHalModule11();
+ if (halModule == nullptr) {
jniThrowException(env, "java/lang/IllegalStateException",
"Out-of-band images are not supported with HAL < 1.1");
return nullptr;
}
- auto halModule = ctx.mHalModule11.promote();
- if (halModule == nullptr) {
- ALOGE("HAL module is gone");
- return nullptr;
- }
-
JavaRef<jbyteArray> jRawImage = nullptr;
auto hidlResult = halModule->getImage(id, [&](hidl_vec<uint8_t> rawImage) {
@@ -418,7 +422,7 @@
if (convert::ThrowIfFailed(env, hidlResult)) return nullptr;
- return jRawImage.get();
+ return jRawImage.release();
}
static bool nativeIsAnalogForced(JNIEnv *env, jobject obj, jlong nativeContext) {
diff --git a/services/core/jni/BroadcastRadio/convert.cpp b/services/core/jni/BroadcastRadio/convert.cpp
index 61b48c2..d2b7c7d 100644
--- a/services/core/jni/BroadcastRadio/convert.cpp
+++ b/services/core/jni/BroadcastRadio/convert.cpp
@@ -510,19 +510,16 @@
jint status = 0;
switch (item.type) {
case MetadataType::INT:
- ALOGV("metadata INT %d", key);
status = env->CallIntMethod(jMetadata.get(), gjni.RadioMetadata.putIntFromNative,
key, item.intValue);
break;
case MetadataType::TEXT: {
- ALOGV("metadata TEXT %d", key);
auto value = make_javastr(env, item.stringValue);
status = env->CallIntMethod(jMetadata.get(), gjni.RadioMetadata.putStringFromNative,
key, value.get());
break;
}
case MetadataType::RAW: {
- ALOGV("metadata RAW %d", key);
auto len = item.rawValue.size();
if (len == 0) break;
auto value = make_javaref(env, env->NewByteArray(len));
@@ -537,7 +534,6 @@
break;
}
case MetadataType::CLOCK:
- ALOGV("metadata CLOCK %d", key);
status = env->CallIntMethod(jMetadata.get(), gjni.RadioMetadata.putClockFromNative,
key, item.clockValue.utcSecondsSinceEpoch,
item.clockValue.timezoneOffsetInMinutes);
diff --git a/services/core/jni/com_android_server_location_GnssLocationProvider.cpp b/services/core/jni/com_android_server_location_GnssLocationProvider.cpp
index 21fea1c..e18eee2 100644
--- a/services/core/jni/com_android_server_location_GnssLocationProvider.cpp
+++ b/services/core/jni/com_android_server_location_GnssLocationProvider.cpp
@@ -81,6 +81,7 @@
using android::hardware::Void;
using android::hardware::hidl_vec;
using android::hardware::hidl_death_recipient;
+using android::hardware::gnss::V1_0::GnssConstellationType;
using android::hardware::gnss::V1_0::GnssLocation;
using android::hardware::gnss::V1_0::GnssLocationFlags;
@@ -91,7 +92,6 @@
using android::hardware::gnss::V1_0::IAGnssRilCallback;
using android::hardware::gnss::V1_0::IGnssBatching;
using android::hardware::gnss::V1_0::IGnssBatchingCallback;
-using android::hardware::gnss::V1_0::IGnssConfiguration;
using android::hardware::gnss::V1_0::IGnssDebug;
using android::hardware::gnss::V1_0::IGnssGeofenceCallback;
using android::hardware::gnss::V1_0::IGnssGeofencing;
@@ -108,6 +108,8 @@
using IGnss_V1_0 = android::hardware::gnss::V1_0::IGnss;
using IGnss_V1_1 = android::hardware::gnss::V1_1::IGnss;
+using IGnssConfiguration_V1_0 = android::hardware::gnss::V1_0::IGnssConfiguration;
+using IGnssConfiguration_V1_1 = android::hardware::gnss::V1_1::IGnssConfiguration;
using IGnssMeasurement_V1_0 = android::hardware::gnss::V1_0::IGnssMeasurement;
using IGnssMeasurement_V1_1 = android::hardware::gnss::V1_1::IGnssMeasurement;
using IGnssMeasurementCallback_V1_0 = android::hardware::gnss::V1_0::IGnssMeasurementCallback;
@@ -137,7 +139,8 @@
sp<IAGnss> agnssIface = nullptr;
sp<IGnssBatching> gnssBatchingIface = nullptr;
sp<IGnssDebug> gnssDebugIface = nullptr;
-sp<IGnssConfiguration> gnssConfigurationIface = nullptr;
+sp<IGnssConfiguration_V1_0> gnssConfigurationIface = nullptr;
+sp<IGnssConfiguration_V1_1> gnssConfigurationIface_V1_1 = nullptr;
sp<IGnssNi> gnssNiIface = nullptr;
sp<IGnssMeasurement_V1_0> gnssMeasurementIface = nullptr;
sp<IGnssMeasurement_V1_1> gnssMeasurementIface_V1_1 = nullptr;
@@ -1098,13 +1101,11 @@
* Methods from ::android::hardware::gps::V1_0::IGnssBatchingCallback
* follow.
*/
- Return<void> gnssLocationBatchCb(
- const ::android::hardware::hidl_vec<GnssLocation> & locations)
+ Return<void> gnssLocationBatchCb(const hidl_vec<GnssLocation> & locations)
override;
};
-Return<void> GnssBatchingCallback::gnssLocationBatchCb(
- const ::android::hardware::hidl_vec<GnssLocation> & locations) {
+Return<void> GnssBatchingCallback::gnssLocationBatchCb(const hidl_vec<GnssLocation> & locations) {
JNIEnv* env = getJniEnv();
jobjectArray jLocations = env->NewObjectArray(locations.size(),
@@ -1257,11 +1258,21 @@
gnssNiIface = gnssNi;
}
- auto gnssConfiguration = gnssHal->getExtensionGnssConfiguration();
- if (!gnssConfiguration.isOk()) {
- ALOGD("Unable to get a handle to GnssConfiguration");
+ if (gnssHal_V1_1 != nullptr) {
+ auto gnssConfiguration = gnssHal_V1_1->getExtensionGnssConfiguration_1_1();
+ if (!gnssConfiguration.isOk()) {
+ ALOGD("Unable to get a handle to GnssConfiguration");
+ } else {
+ gnssConfigurationIface_V1_1 = gnssConfiguration;
+ gnssConfigurationIface = gnssConfigurationIface_V1_1;
+ }
} else {
- gnssConfigurationIface = gnssConfiguration;
+ auto gnssConfiguration_V1_0 = gnssHal->getExtensionGnssConfiguration();
+ if (!gnssConfiguration_V1_0.isOk()) {
+ ALOGD("Unable to get a handle to GnssConfiguration");
+ } else {
+ gnssConfigurationIface = gnssConfiguration_V1_0;
+ }
}
auto gnssGeofencing = gnssHal->getExtensionGnssGeofencing();
@@ -1997,6 +2008,48 @@
}
}
+static jboolean android_location_GnssLocationProvider_set_satellite_blacklist(
+ JNIEnv* env, jobject, jintArray constellations, jintArray sv_ids) {
+ if (gnssConfigurationIface_V1_1 == nullptr) {
+ ALOGI("No GNSS Satellite Blacklist interface available");
+ return JNI_FALSE;
+ }
+
+ jint *constellation_array = env->GetIntArrayElements(constellations, 0);
+ if (NULL == constellation_array) {
+ ALOGI("GetIntArrayElements returns NULL.");
+ return JNI_FALSE;
+ }
+ jsize length = env->GetArrayLength(constellations);
+
+ jint *sv_id_array = env->GetIntArrayElements(sv_ids, 0);
+ if (NULL == sv_id_array) {
+ ALOGI("GetIntArrayElements returns NULL.");
+ return JNI_FALSE;
+ }
+
+ if (length != env->GetArrayLength(sv_ids)) {
+ ALOGI("Lengths of constellations and sv_ids are inconsistent.");
+ return JNI_FALSE;
+ }
+
+ hidl_vec<IGnssConfiguration_V1_1::BlacklistedSource> sources;
+ sources.resize(length);
+
+ for (int i = 0; i < length; i++) {
+ sources[i].constellation = static_cast<GnssConstellationType>(constellation_array[i]);
+ sources[i].svid = sv_id_array[i];
+ }
+
+ auto result = gnssConfigurationIface_V1_1->setBlacklist(sources);
+ if (result.isOk()) {
+ return result;
+ } else {
+ return JNI_FALSE;
+ }
+}
+
+
static jint android_location_GnssLocationProvider_get_batch_size(JNIEnv*, jclass) {
if (gnssBatchingIface == nullptr) {
return 0; // batching not supported, size = 0
@@ -2185,6 +2238,9 @@
{"native_set_emergency_supl_pdn",
"(I)Z",
reinterpret_cast<void *>(android_location_GnssLocationProvider_set_emergency_supl_pdn)},
+ {"native_set_satellite_blacklist",
+ "([I[I)Z",
+ reinterpret_cast<void *>(android_location_GnssLocationProvider_set_satellite_blacklist)},
{"native_get_batch_size",
"()I",
reinterpret_cast<void *>(android_location_GnssLocationProvider_get_batch_size)},
diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
index 90e8a9c..9bc5fca 100644
--- a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
+++ b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
@@ -108,7 +108,6 @@
import android.app.admin.SecurityLog.SecurityEvent;
import android.app.admin.SystemUpdateInfo;
import android.app.admin.SystemUpdatePolicy;
-import android.app.backup.BackupManager;
import android.app.backup.IBackupManager;
import android.app.backup.ISelectBackupTransportCallback;
import android.app.trust.TrustManager;
@@ -220,6 +219,8 @@
import com.android.internal.util.XmlUtils;
import com.android.internal.widget.LockPatternUtils;
import com.android.server.LocalServices;
+import com.android.server.LockGuard;
+import com.android.server.StatLogger;
import com.android.server.SystemServerInitThreadPool;
import com.android.server.SystemService;
import com.android.server.devicepolicy.DevicePolicyManagerService.ActiveAdmin.TrustAgentInfo;
@@ -462,21 +463,60 @@
* Whether or not device admin feature is supported. If it isn't return defaults for all
* public methods.
*/
- boolean mHasFeature;
+ final boolean mHasFeature;
/**
* Whether or not this device is a watch.
*/
- boolean mIsWatch;
+ final boolean mIsWatch;
private final CertificateMonitor mCertificateMonitor;
private final SecurityLogMonitor mSecurityLogMonitor;
+
+ @GuardedBy("getLockObject()")
private NetworkLogger mNetworkLogger;
private final AtomicBoolean mRemoteBugreportServiceIsActive = new AtomicBoolean();
private final AtomicBoolean mRemoteBugreportSharingAccepted = new AtomicBoolean();
- private SetupContentObserver mSetupContentObserver;
+ private final SetupContentObserver mSetupContentObserver;
+
+ private static boolean ENABLE_LOCK_GUARD = Build.IS_ENG
+ || (SystemProperties.getInt("debug.dpm.lock_guard", 0) == 1);
+
+ interface Stats {
+ int LOCK_GUARD_GUARD = 0;
+
+ int COUNT = LOCK_GUARD_GUARD + 1;
+ }
+
+ private final StatLogger mStatLogger = new StatLogger(new String[] {
+ "LockGuard.guard()",
+ });
+
+ private final Object mLockDoNoUseDirectly = LockGuard.installNewLock(
+ LockGuard.INDEX_DPMS, /* doWtf=*/ true);
+
+ final Object getLockObject() {
+ if (ENABLE_LOCK_GUARD) {
+ final long start = mStatLogger.getTime();
+ LockGuard.guard(LockGuard.INDEX_DPMS);
+ mStatLogger.logDurationStat(Stats.LOCK_GUARD_GUARD, start);
+ }
+ return mLockDoNoUseDirectly;
+ }
+
+ /**
+ * Check if the current thread holds the DPMS lock, and if not, do a WTF.
+ *
+ * (Doing this check too much may be costly, so don't call it in a hot path.)
+ */
+ final void ensureLocked() {
+ if (Thread.holdsLock(mLockDoNoUseDirectly)) {
+ return;
+ }
+ Slog.wtfStack(LOG_TAG, "Not holding DPMS lock.");
+ }
@VisibleForTesting
final TransferOwnershipMetadataManager mTransferOwnershipMetadataManager;
@@ -627,8 +667,10 @@
}
}
+ @GuardedBy("getLockObject()")
final SparseArray<DevicePolicyData> mUserData = new SparseArray<>();
- @GuardedBy("DevicePolicyManagerService.this")
+
+ @GuardedBy("getLockObject()")
final SparseArray<PasswordMetrics> mUserPasswordMetrics = new SparseArray<>();
final Handler mHandler;
@@ -649,7 +691,7 @@
*/
if (Intent.ACTION_USER_STARTED.equals(action)
&& userHandle == mOwners.getDeviceOwnerUserId()) {
- synchronized (DevicePolicyManagerService.this) {
+ synchronized (getLockObject()) {
if (isNetworkLoggingEnabledInternalLocked()) {
setNetworkLoggingActiveInternal(true);
}
@@ -684,14 +726,14 @@
if (Intent.ACTION_USER_ADDED.equals(action)) {
sendDeviceOwnerUserCommand(DeviceAdminReceiver.ACTION_USER_ADDED, userHandle);
- synchronized (DevicePolicyManagerService.this) {
+ synchronized (getLockObject()) {
// It might take a while for the user to become affiliated. Make security
// and network logging unavailable in the meantime.
maybePauseDeviceWideLoggingLocked();
}
} else if (Intent.ACTION_USER_REMOVED.equals(action)) {
sendDeviceOwnerUserCommand(DeviceAdminReceiver.ACTION_USER_REMOVED, userHandle);
- synchronized (DevicePolicyManagerService.this) {
+ synchronized (getLockObject()) {
// Check whether the user is affiliated, *before* removing its data.
boolean isRemovedUserAffiliated = isUserAffiliatedWithDeviceLocked(userHandle);
removeUserData(userHandle);
@@ -705,7 +747,7 @@
}
} else if (Intent.ACTION_USER_STARTED.equals(action)) {
sendDeviceOwnerUserCommand(DeviceAdminReceiver.ACTION_USER_STARTED, userHandle);
- synchronized (DevicePolicyManagerService.this) {
+ synchronized (getLockObject()) {
maybeSendAdminEnabledBroadcastLocked(userHandle);
// Reset the policy data
mUserData.remove(userHandle);
@@ -716,7 +758,7 @@
} else if (Intent.ACTION_USER_SWITCHED.equals(action)) {
sendDeviceOwnerUserCommand(DeviceAdminReceiver.ACTION_USER_SWITCHED, userHandle);
} else if (Intent.ACTION_USER_UNLOCKED.equals(action)) {
- synchronized (DevicePolicyManagerService.this) {
+ synchronized (getLockObject()) {
maybeSendAdminEnabledBroadcastLocked(userHandle);
}
} else if (Intent.ACTION_EXTERNAL_APPLICATIONS_UNAVAILABLE.equals(action)) {
@@ -741,7 +783,7 @@
}
private void sendDeviceOwnerUserCommand(String action, int userHandle) {
- synchronized (DevicePolicyManagerService.this) {
+ synchronized (getLockObject()) {
ActiveAdmin deviceOwner = getDeviceOwnerAdminLocked();
if (deviceOwner != null) {
Bundle extras = new Bundle();
@@ -1662,7 +1704,7 @@
+ " for user " + userHandle);
}
DevicePolicyData policy = getUserData(userHandle);
- synchronized (this) {
+ synchronized (getLockObject()) {
for (int i = policy.mAdminList.size() - 1; i >= 0; i--) {
ActiveAdmin aa = policy.mAdminList.get(i);
try {
@@ -2091,6 +2133,7 @@
if (!mHasFeature) {
// Skip the rest of the initialization
+ mSetupContentObserver = null;
return;
}
@@ -2132,7 +2175,7 @@
*/
@NonNull
DevicePolicyData getUserData(int userHandle) {
- synchronized (this) {
+ synchronized (getLockObject()) {
DevicePolicyData policy = mUserData.get(userHandle);
if (policy == null) {
policy = new DevicePolicyData(userHandle);
@@ -2173,7 +2216,7 @@
}
void removeUserData(int userHandle) {
- synchronized (this) {
+ synchronized (getLockObject()) {
if (userHandle == UserHandle.USER_SYSTEM) {
Slog.w(LOG_TAG, "Tried to remove device policy file for user 0! Ignoring.");
return;
@@ -2199,7 +2242,7 @@
}
void loadOwners() {
- synchronized (this) {
+ synchronized (getLockObject()) {
mOwners.load();
setDeviceOwnerSystemPropertyLocked();
findOwnerComponentIfNecessaryLocked();
@@ -2223,7 +2266,7 @@
/** Apply default restrictions that haven't been applied to profile owners yet. */
private void maybeSetDefaultProfileOwnerUserRestrictions() {
- synchronized (this) {
+ synchronized (getLockObject()) {
for (final int userId : mOwners.getProfileOwnerKeys()) {
final ActiveAdmin profileOwner = getProfileOwnerAdminLocked(userId);
// The following restrictions used to be applied to managed profiles by different
@@ -2513,6 +2556,7 @@
}
ActiveAdmin getActiveAdminUncheckedLocked(ComponentName who, int userHandle) {
+ ensureLocked();
ActiveAdmin admin = getUserData(userHandle).mAdminMap.get(who);
if (admin != null
&& who.getPackageName().equals(admin.info.getActivityInfo().packageName)
@@ -2523,6 +2567,7 @@
}
ActiveAdmin getActiveAdminUncheckedLocked(ComponentName who, int userHandle, boolean parent) {
+ ensureLocked();
if (parent) {
enforceManagedProfile(userHandle, "call APIs on the parent profile");
}
@@ -2535,6 +2580,7 @@
ActiveAdmin getActiveAdminForCallerLocked(ComponentName who, int reqPolicy)
throws SecurityException {
+ ensureLocked();
final int callingUid = mInjector.binderGetCallingUid();
ActiveAdmin result = getActiveAdminWithPolicyForUidLocked(who, reqPolicy, callingUid);
@@ -2565,6 +2611,7 @@
ActiveAdmin getActiveAdminForCallerLocked(ComponentName who, int reqPolicy, boolean parent)
throws SecurityException {
+ ensureLocked();
if (parent) {
enforceManagedProfile(mInjector.userHandleGetCallingUserId(),
"call APIs on the parent profile");
@@ -2577,6 +2624,7 @@
* the admin's uid matches the uid.
*/
private ActiveAdmin getActiveAdminForUidLocked(ComponentName who, int uid) {
+ ensureLocked();
final int userId = UserHandle.getUserId(uid);
final DevicePolicyData policy = getUserData(userId);
ActiveAdmin admin = policy.mAdminMap.get(who);
@@ -2591,6 +2639,7 @@
private ActiveAdmin getActiveAdminWithPolicyForUidLocked(ComponentName who, int reqPolicy,
int uid) {
+ ensureLocked();
// Try to find an admin which can use reqPolicy
final int userId = UserHandle.getUserId(uid);
final DevicePolicyData policy = getUserData(userId);
@@ -2620,6 +2669,7 @@
@VisibleForTesting
boolean isActiveAdminWithPolicyForUserLocked(ActiveAdmin admin, int reqPolicy,
int userId) {
+ ensureLocked();
final boolean ownsDevice = isDeviceOwner(admin.info.getComponent(), userId);
final boolean ownsProfile = isProfileOwner(admin.info.getComponent(), userId);
@@ -3319,14 +3369,14 @@
updateUserSetupCompleteAndPaired();
List<String> packageList;
- synchronized (this) {
+ synchronized (getLockObject()) {
packageList = getKeepUninstalledPackagesLocked();
}
if (packageList != null) {
mInjector.getPackageManagerInternal().setKeepUninstalledPackages(packageList);
}
- synchronized (this) {
+ synchronized (getLockObject()) {
ActiveAdmin deviceOwner = getDeviceOwnerAdminLocked();
if (deviceOwner != null) {
// Push the force-ephemeral-users policy to the user manager.
@@ -3379,7 +3429,7 @@
private void ensureDeviceOwnerUserStarted() {
final int userId;
- synchronized (this) {
+ synchronized (getLockObject()) {
if (!mOwners.hasDeviceOwner()) {
return;
}
@@ -3436,7 +3486,7 @@
// before reboot
Set<Integer> usersWithProfileOwners;
Set<Integer> usersWithData;
- synchronized(this) {
+ synchronized (getLockObject()) {
usersWithProfileOwners = mOwners.getProfileOwnerKeys();
usersWithData = new ArraySet<>();
for (int i = 0; i < mUserData.size(); i++) {
@@ -3460,7 +3510,7 @@
final Bundle adminExtras = new Bundle();
adminExtras.putParcelable(Intent.EXTRA_USER, UserHandle.of(userHandle));
- synchronized (this) {
+ synchronized (getLockObject()) {
final long now = System.currentTimeMillis();
List<ActiveAdmin> admins = getActiveAdminsForLockscreenPoliciesLocked(
@@ -3496,7 +3546,7 @@
}
enforceManageUsers();
- synchronized (this) {
+ synchronized (getLockObject()) {
final DevicePolicyData policy = getUserData(userHandle.getIdentifier());
boolean changed = false;
@@ -3515,7 +3565,7 @@
if (!mHasFeature) {
return Collections.<String> emptySet();
}
- synchronized (this) {
+ synchronized (getLockObject()) {
final DevicePolicyData policy = getUserData(userHandle.getIdentifier());
return policy.mAcceptedCaCertificates;
}
@@ -3542,7 +3592,7 @@
DevicePolicyData policy = getUserData(userHandle);
DeviceAdminInfo info = findAdmin(adminReceiver, userHandle,
/* throwForMissingPermission= */ true);
- synchronized (this) {
+ synchronized (getLockObject()) {
checkActiveAdminPrecondition(adminReceiver, info, policy);
long ident = mInjector.binderClearCallingIdentity();
try {
@@ -3592,7 +3642,7 @@
}
private void pushActiveAdminPackages() {
- synchronized (this) {
+ synchronized (getLockObject()) {
final List<UserInfo> users = mUserManager.getUsers();
for (int i = users.size() - 1; i >= 0; --i) {
final int userId = users.get(i).id;
@@ -3603,7 +3653,7 @@
}
private void pushAllMeteredRestrictedPackages() {
- synchronized (this) {
+ synchronized (getLockObject()) {
final List<UserInfo> users = mUserManager.getUsers();
for (int i = users.size() - 1; i >= 0; --i) {
final int userId = users.get(i).id;
@@ -3681,7 +3731,7 @@
return false;
}
enforceFullCrossUsersPermission(userHandle);
- synchronized (this) {
+ synchronized (getLockObject()) {
return getActiveAdminUncheckedLocked(adminReceiver, userHandle) != null;
}
}
@@ -3692,7 +3742,7 @@
return false;
}
enforceFullCrossUsersPermission(userHandle);
- synchronized (this) {
+ synchronized (getLockObject()) {
DevicePolicyData policyData = getUserData(userHandle);
return policyData.mRemovingAdmins.contains(adminReceiver);
}
@@ -3704,7 +3754,7 @@
return false;
}
enforceFullCrossUsersPermission(userHandle);
- synchronized (this) {
+ synchronized (getLockObject()) {
ActiveAdmin administrator = getActiveAdminUncheckedLocked(adminReceiver, userHandle);
if (administrator == null) {
throw new SecurityException("No active admin " + adminReceiver);
@@ -3721,7 +3771,7 @@
}
enforceFullCrossUsersPermission(userHandle);
- synchronized (this) {
+ synchronized (getLockObject()) {
DevicePolicyData policy = getUserData(userHandle);
final int N = policy.mAdminList.size();
if (N <= 0) {
@@ -3741,7 +3791,7 @@
return false;
}
enforceFullCrossUsersPermission(userHandle);
- synchronized (this) {
+ synchronized (getLockObject()) {
DevicePolicyData policy = getUserData(userHandle);
final int N = policy.mAdminList.size();
for (int i=0; i<N; i++) {
@@ -3762,7 +3812,7 @@
enforceShell("forceRemoveActiveAdmin");
long ident = mInjector.binderClearCallingIdentity();
try {
- synchronized (this) {
+ synchronized (getLockObject()) {
if (!isAdminTestOnlyLocked(adminReceiver, userHandle)) {
throw new SecurityException("Attempt to remove non-test admin "
+ adminReceiver + " " + userHandle);
@@ -3842,7 +3892,7 @@
}
enforceFullCrossUsersPermission(userHandle);
enforceUserUnlocked(userHandle);
- synchronized (this) {
+ synchronized (getLockObject()) {
ActiveAdmin admin = getActiveAdminUncheckedLocked(adminReceiver, userHandle);
if (admin == null) {
return;
@@ -3884,7 +3934,7 @@
validateQualityConstant(quality);
final int userId = mInjector.userHandleGetCallingUserId();
- synchronized (this) {
+ synchronized (getLockObject()) {
ActiveAdmin ap = getActiveAdminForCallerLocked(
who, DeviceAdminInfo.USES_POLICY_LIMIT_PASSWORD, parent);
final PasswordMetrics metrics = ap.minimumPasswordMetrics;
@@ -3903,7 +3953,6 @@
* be the correct one upon boot.
* This should be called whenever the password or the admin policies have changed.
*/
- @GuardedBy("DevicePolicyManagerService.this")
private void updatePasswordValidityCheckpointLocked(int userHandle, boolean parent) {
final int credentialOwner = getCredentialOwner(userHandle, parent);
DevicePolicyData policy = getUserData(credentialOwner);
@@ -3926,7 +3975,7 @@
return PASSWORD_QUALITY_UNSPECIFIED;
}
enforceFullCrossUsersPermission(userHandle);
- synchronized (this) {
+ synchronized (getLockObject()) {
int mode = PASSWORD_QUALITY_UNSPECIFIED;
if (who != null) {
@@ -3998,7 +4047,7 @@
}
Preconditions.checkNotNull(who, "ComponentName is null");
final int userId = mInjector.userHandleGetCallingUserId();
- synchronized (this) {
+ synchronized (getLockObject()) {
ActiveAdmin ap = getActiveAdminForCallerLocked(
who, DeviceAdminInfo.USES_POLICY_LIMIT_PASSWORD, parent);
final PasswordMetrics metrics = ap.minimumPasswordMetrics;
@@ -4023,7 +4072,7 @@
}
Preconditions.checkNotNull(who, "ComponentName is null");
final int userId = mInjector.userHandleGetCallingUserId();
- synchronized (this) {
+ synchronized (getLockObject()) {
ActiveAdmin ap = getActiveAdminForCallerLocked(
who, DeviceAdminInfo.USES_POLICY_LIMIT_PASSWORD, parent);
if (ap.passwordHistoryLength != length) {
@@ -4052,7 +4101,7 @@
Preconditions.checkNotNull(who, "ComponentName is null");
Preconditions.checkArgumentNonnegative(timeout, "Timeout must be >= 0 ms");
final int userHandle = mInjector.userHandleGetCallingUserId();
- synchronized (this) {
+ synchronized (getLockObject()) {
ActiveAdmin ap = getActiveAdminForCallerLocked(
who, DeviceAdminInfo.USES_POLICY_EXPIRE_PASSWORD, parent);
// Calling this API automatically bumps the expiration date
@@ -4086,7 +4135,7 @@
return 0L;
}
enforceFullCrossUsersPermission(userHandle);
- synchronized (this) {
+ synchronized (getLockObject()) {
long timeout = 0L;
if (who != null) {
@@ -4114,7 +4163,7 @@
final int userId = UserHandle.getCallingUserId();
List<String> changedProviders = null;
- synchronized (this) {
+ synchronized (getLockObject()) {
ActiveAdmin activeAdmin = getActiveAdminForCallerLocked(admin,
DeviceAdminInfo.USES_POLICY_PROFILE_OWNER);
if (activeAdmin.crossProfileWidgetProviders == null) {
@@ -4141,7 +4190,7 @@
final int userId = UserHandle.getCallingUserId();
List<String> changedProviders = null;
- synchronized (this) {
+ synchronized (getLockObject()) {
ActiveAdmin activeAdmin = getActiveAdminForCallerLocked(admin,
DeviceAdminInfo.USES_POLICY_PROFILE_OWNER);
if (activeAdmin.crossProfileWidgetProviders == null
@@ -4165,7 +4214,7 @@
@Override
public List<String> getCrossProfileWidgetProviders(ComponentName admin) {
- synchronized (this) {
+ synchronized (getLockObject()) {
ActiveAdmin activeAdmin = getActiveAdminForCallerLocked(admin,
DeviceAdminInfo.USES_POLICY_PROFILE_OWNER);
if (activeAdmin.crossProfileWidgetProviders == null
@@ -4211,7 +4260,7 @@
return 0L;
}
enforceFullCrossUsersPermission(userHandle);
- synchronized (this) {
+ synchronized (getLockObject()) {
return getPasswordExpirationLocked(who, userHandle, parent);
}
}
@@ -4223,7 +4272,7 @@
}
Preconditions.checkNotNull(who, "ComponentName is null");
final int userId = mInjector.userHandleGetCallingUserId();
- synchronized (this) {
+ synchronized (getLockObject()) {
final ActiveAdmin ap = getActiveAdminForCallerLocked(
who, DeviceAdminInfo.USES_POLICY_LIMIT_PASSWORD, parent);
final PasswordMetrics metrics = ap.minimumPasswordMetrics;
@@ -4245,7 +4294,7 @@
public void setPasswordMinimumLowerCase(ComponentName who, int length, boolean parent) {
Preconditions.checkNotNull(who, "ComponentName is null");
final int userId = mInjector.userHandleGetCallingUserId();
- synchronized (this) {
+ synchronized (getLockObject()) {
ActiveAdmin ap = getActiveAdminForCallerLocked(
who, DeviceAdminInfo.USES_POLICY_LIMIT_PASSWORD, parent);
final PasswordMetrics metrics = ap.minimumPasswordMetrics;
@@ -4270,7 +4319,7 @@
}
Preconditions.checkNotNull(who, "ComponentName is null");
final int userId = mInjector.userHandleGetCallingUserId();
- synchronized (this) {
+ synchronized (getLockObject()) {
ActiveAdmin ap = getActiveAdminForCallerLocked(
who, DeviceAdminInfo.USES_POLICY_LIMIT_PASSWORD, parent);
final PasswordMetrics metrics = ap.minimumPasswordMetrics;
@@ -4295,7 +4344,7 @@
}
Preconditions.checkNotNull(who, "ComponentName is null");
final int userId = mInjector.userHandleGetCallingUserId();
- synchronized (this) {
+ synchronized (getLockObject()) {
ActiveAdmin ap = getActiveAdminForCallerLocked(
who, DeviceAdminInfo.USES_POLICY_LIMIT_PASSWORD, parent);
final PasswordMetrics metrics = ap.minimumPasswordMetrics;
@@ -4320,7 +4369,7 @@
}
Preconditions.checkNotNull(who, "ComponentName is null");
final int userId = mInjector.userHandleGetCallingUserId();
- synchronized (this) {
+ synchronized (getLockObject()) {
ActiveAdmin ap = getActiveAdminForCallerLocked(
who, DeviceAdminInfo.USES_POLICY_LIMIT_PASSWORD, parent);
final PasswordMetrics metrics = ap.minimumPasswordMetrics;
@@ -4345,7 +4394,7 @@
}
Preconditions.checkNotNull(who, "ComponentName is null");
final int userId = mInjector.userHandleGetCallingUserId();
- synchronized (this) {
+ synchronized (getLockObject()) {
ActiveAdmin ap = getActiveAdminForCallerLocked(
who, DeviceAdminInfo.USES_POLICY_LIMIT_PASSWORD, parent);
final PasswordMetrics metrics = ap.minimumPasswordMetrics;
@@ -4372,7 +4421,7 @@
return 0;
}
enforceFullCrossUsersPermission(userHandle);
- synchronized (this) {
+ synchronized (getLockObject()) {
if (who != null) {
final ActiveAdmin admin = getActiveAdminUncheckedLocked(who, userHandle, parent);
return admin != null ? getter.apply(admin) : 0;
@@ -4404,7 +4453,7 @@
enforceFullCrossUsersPermission(userHandle);
enforceUserUnlocked(userHandle, parent);
- synchronized (this) {
+ synchronized (getLockObject()) {
// This API can only be called by an active device admin,
// so try to retrieve it to check that the caller is one.
getActiveAdminForCallerLocked(null, DeviceAdminInfo.USES_POLICY_LIMIT_PASSWORD, parent);
@@ -4435,7 +4484,7 @@
enforceFullCrossUsersPermission(userHandle);
enforceManagedProfile(userHandle, "call APIs refering to the parent profile");
- synchronized (this) {
+ synchronized (getLockObject()) {
final int targetUser = getProfileParentId(userHandle);
enforceUserUnlocked(targetUser, false);
int credentialOwner = getCredentialOwner(userHandle, false);
@@ -4502,7 +4551,7 @@
@Override
public int getCurrentFailedPasswordAttempts(int userHandle, boolean parent) {
enforceFullCrossUsersPermission(userHandle);
- synchronized (this) {
+ synchronized (getLockObject()) {
if (!isCallerWithSystemUid()) {
// This API can only be called by an active device admin,
// so try to retrieve it to check that the caller is one.
@@ -4523,7 +4572,7 @@
}
Preconditions.checkNotNull(who, "ComponentName is null");
final int userId = mInjector.userHandleGetCallingUserId();
- synchronized (this) {
+ synchronized (getLockObject()) {
// This API can only be called by an active device admin,
// so try to retrieve it to check that the caller is one.
getActiveAdminForCallerLocked(
@@ -4548,7 +4597,7 @@
return 0;
}
enforceFullCrossUsersPermission(userHandle);
- synchronized (this) {
+ synchronized (getLockObject()) {
ActiveAdmin admin = (who != null)
? getActiveAdminUncheckedLocked(who, userHandle, parent)
: getAdminWithMinimumFailedPasswordsForWipeLocked(userHandle, parent);
@@ -4562,7 +4611,7 @@
return UserHandle.USER_NULL;
}
enforceFullCrossUsersPermission(userHandle);
- synchronized (this) {
+ synchronized (getLockObject()) {
ActiveAdmin admin = getAdminWithMinimumFailedPasswordsForWipeLocked(
userHandle, parent);
return admin != null ? admin.getUserHandle().getIdentifier() : UserHandle.USER_NULL;
@@ -4623,7 +4672,7 @@
/* PO or DO could do an untrusted reset in certain conditions. */
private boolean canUserHaveUntrustedCredentialReset(@UserIdInt int userId) {
- synchronized (this) {
+ synchronized (getLockObject()) {
// An active DO or PO might be able to fo an untrusted credential reset
for (final ActiveAdmin admin : getUserData(userId).mAdminList) {
if (!isActiveAdminWithPolicyForUserLocked(admin,
@@ -4649,7 +4698,7 @@
enforceNotManagedProfile(userHandle, "clear the active password");
}
- synchronized (this) {
+ synchronized (getLockObject()) {
// If caller has PO (or DO) it can change the password, so see if that's the case first.
ActiveAdmin admin = getActiveAdminWithPolicyForUidLocked(
null, DeviceAdminInfo.USES_POLICY_PROFILE_OWNER, callingUid);
@@ -4719,7 +4768,7 @@
private boolean resetPasswordInternal(String password, long tokenHandle, byte[] token,
int flags, int callingUid, int userHandle) {
int quality;
- synchronized (this) {
+ synchronized (getLockObject()) {
quality = getPasswordQuality(null, userHandle, /* parent */ false);
if (quality == DevicePolicyManager.PASSWORD_QUALITY_MANAGED) {
quality = PASSWORD_QUALITY_UNSPECIFIED;
@@ -4829,7 +4878,7 @@
mLockPatternUtils.requireStrongAuth(STRONG_AUTH_REQUIRED_AFTER_DPM_LOCK_NOW,
UserHandle.USER_ALL);
}
- synchronized (this) {
+ synchronized (getLockObject()) {
int newOwner = requireEntry ? callingUid : -1;
if (policy.mPasswordOwner != newOwner) {
policy.mPasswordOwner = newOwner;
@@ -4852,7 +4901,7 @@
}
private void setDoNotAskCredentialsOnBoot() {
- synchronized (this) {
+ synchronized (getLockObject()) {
DevicePolicyData policyData = getUserData(UserHandle.USER_SYSTEM);
if (!policyData.doNotAskCredentialsOnBoot) {
policyData.doNotAskCredentialsOnBoot = true;
@@ -4865,7 +4914,7 @@
public boolean getDoNotAskCredentialsOnBoot() {
mContext.enforceCallingOrSelfPermission(
android.Manifest.permission.QUERY_DO_NOT_ASK_CREDENTIALS_ON_BOOT, null);
- synchronized (this) {
+ synchronized (getLockObject()) {
DevicePolicyData policyData = getUserData(UserHandle.USER_SYSTEM);
return policyData.doNotAskCredentialsOnBoot;
}
@@ -4878,7 +4927,7 @@
}
Preconditions.checkNotNull(who, "ComponentName is null");
final int userHandle = mInjector.userHandleGetCallingUserId();
- synchronized (this) {
+ synchronized (getLockObject()) {
ActiveAdmin ap = getActiveAdminForCallerLocked(
who, DeviceAdminInfo.USES_POLICY_FORCE_LOCK, parent);
if (ap.maximumTimeToUnlock != timeMs) {
@@ -4952,7 +5001,7 @@
return 0;
}
enforceFullCrossUsersPermission(userHandle);
- synchronized (this) {
+ synchronized (getLockObject()) {
if (who != null) {
final ActiveAdmin admin = getActiveAdminUncheckedLocked(who, userHandle, parent);
return admin != null ? admin.maximumTimeToUnlock : 0;
@@ -4994,7 +5043,7 @@
}
final int userHandle = mInjector.userHandleGetCallingUserId();
- synchronized (this) {
+ synchronized (getLockObject()) {
ActiveAdmin ap = getActiveAdminForCallerLocked(who,
DeviceAdminInfo.USES_POLICY_PROFILE_OWNER, parent);
if (ap.strongAuthUnlockTimeout != timeoutMs) {
@@ -5015,7 +5064,7 @@
return DevicePolicyManager.DEFAULT_STRONG_AUTH_TIMEOUT_MS;
}
enforceFullCrossUsersPermission(userId);
- synchronized (this) {
+ synchronized (getLockObject()) {
if (who != null) {
ActiveAdmin admin = getActiveAdminUncheckedLocked(who, userId, parent);
return admin != null ? admin.strongAuthUnlockTimeout : 0;
@@ -5053,7 +5102,7 @@
}
final int callingUserId = mInjector.userHandleGetCallingUserId();
- synchronized (this) {
+ synchronized (getLockObject()) {
// This API can only be called by an active device admin,
// so try to retrieve it to check that the caller is one.
final ActiveAdmin admin = getActiveAdminForCallerLocked(
@@ -5122,7 +5171,7 @@
}
private void enforceProfileOrDeviceOwner(ComponentName who) {
- synchronized (this) {
+ synchronized (getLockObject()) {
getActiveAdminForCallerLocked(who, DeviceAdminInfo.USES_POLICY_PROFILE_OWNER);
}
}
@@ -5130,7 +5179,7 @@
@Override
public boolean approveCaCert(String alias, int userId, boolean approval) {
enforceManageUsers();
- synchronized (this) {
+ synchronized (getLockObject()) {
Set<String> certs = getUserData(userId).mAcceptedCaCertificates;
boolean changed = (approval ? certs.add(alias) : certs.remove(alias));
if (!changed) {
@@ -5145,7 +5194,7 @@
@Override
public boolean isCaCertApproved(String alias, int userId) {
enforceManageUsers();
- synchronized (this) {
+ synchronized (getLockObject()) {
return getUserData(userId).mAcceptedCaCertificates.contains(alias);
}
}
@@ -5157,7 +5206,7 @@
isSecure |= mLockPatternUtils.isSecure(getProfileParentId(userInfo.id));
}
if (!isSecure) {
- synchronized (this) {
+ synchronized (getLockObject()) {
getUserData(userInfo.id).mAcceptedCaCertificates.clear();
saveSettingsLocked(userInfo.id);
}
@@ -5188,7 +5237,7 @@
mInjector.binderRestoreCallingIdentity(id);
}
- synchronized (this) {
+ synchronized (getLockObject()) {
getUserData(userHandle.getIdentifier()).mOwnerInstalledCaCerts.add(alias);
saveSettingsLocked(userHandle.getIdentifier());
}
@@ -5210,7 +5259,7 @@
mInjector.binderRestoreCallingIdentity(id);
}
- synchronized (this) {
+ synchronized (getLockObject()) {
if (getUserData(userId).mOwnerInstalledCaCerts.removeAll(Arrays.asList(aliases))) {
saveSettingsLocked(userId);
}
@@ -5295,7 +5344,7 @@
}
} else {
// Caller provided - check it is the device owner.
- synchronized (this) {
+ synchronized (getLockObject()) {
getActiveAdminForCallerLocked(who, DeviceAdminInfo.USES_POLICY_DEVICE_OWNER);
}
}
@@ -5555,7 +5604,7 @@
// Retrieve the user ID of the calling process.
final int userId = mInjector.userHandleGetCallingUserId();
- synchronized (this) {
+ synchronized (getLockObject()) {
// Ensure calling process is device/profile owner.
getActiveAdminForCallerLocked(who, DeviceAdminInfo.USES_POLICY_PROFILE_OWNER);
// Ensure the delegate is installed (skip this for DELEGATION_CERT_INSTALL in pre-N).
@@ -5616,7 +5665,7 @@
// Retrieve the user ID of the calling process.
final int callingUid = mInjector.binderGetCallingUid();
final int userId = UserHandle.getUserId(callingUid);
- synchronized (this) {
+ synchronized (getLockObject()) {
// Ensure calling process is device/profile owner.
if (who != null) {
getActiveAdminForCallerLocked(who, DeviceAdminInfo.USES_POLICY_PROFILE_OWNER);
@@ -5659,7 +5708,7 @@
// Retrieve the user ID of the calling process.
final int userId = mInjector.userHandleGetCallingUserId();
- synchronized (this) {
+ synchronized (getLockObject()) {
// Ensure calling process is device/profile owner.
getActiveAdminForCallerLocked(who, DeviceAdminInfo.USES_POLICY_PROFILE_OWNER);
final DevicePolicyData policy = getUserData(userId);
@@ -5698,7 +5747,7 @@
// Retrieve the UID and user ID of the calling process.
final int callingUid = mInjector.binderGetCallingUid();
final int userId = UserHandle.getUserId(callingUid);
- synchronized (this) {
+ synchronized (getLockObject()) {
// Retrieve user policy data.
final DevicePolicyData policy = getUserData(userId);
// Retrieve the list of delegation scopes granted to callerPackage.
@@ -5737,7 +5786,7 @@
String scope) {
// If a ComponentName is given ensure it is a device or profile owner according to policy.
if (who != null) {
- synchronized (this) {
+ synchronized (getLockObject()) {
getActiveAdminForCallerLocked(who, reqPolicy);
}
// If no ComponentName is given ensure calling process has scope delegation.
@@ -5756,7 +5805,7 @@
Preconditions.checkNotNull(who, "ComponentName is null");
final int userId = mInjector.userHandleGetCallingUserId();
- synchronized(this) {
+ synchronized (getLockObject()) {
// Ensure calling process is device/profile owner.
getActiveAdminForCallerLocked(who, DeviceAdminInfo.USES_POLICY_PROFILE_OWNER);
final DevicePolicyData policy = getUserData(userId);
@@ -5887,7 +5936,7 @@
enforceFullCrossUsersPermission(mInjector.userHandleGetCallingUserId());
final ActiveAdmin admin;
- synchronized (this) {
+ synchronized (getLockObject()) {
admin = getActiveAdminForCallerLocked(null, DeviceAdminInfo.USES_POLICY_WIPE_DATA);
}
String internalReason = "DevicePolicyManager.wipeDataWithReason() from "
@@ -5970,7 +6019,7 @@
mContext.enforceCallingOrSelfPermission(
android.Manifest.permission.BIND_DEVICE_ADMIN, null);
- synchronized (this) {
+ synchronized (getLockObject()) {
ActiveAdmin admin = getActiveAdminUncheckedLocked(comp, userHandle);
if (admin == null) {
result.sendResult(null);
@@ -6009,7 +6058,7 @@
}
validateQualityConstant(metrics.quality);
- synchronized (this) {
+ synchronized (getLockObject()) {
mUserPasswordMetrics.put(userHandle, metrics);
}
}
@@ -6033,7 +6082,7 @@
long ident = mInjector.binderClearCallingIdentity();
try {
- synchronized (this) {
+ synchronized (getLockObject()) {
policy.mFailedPasswordAttempts = 0;
updatePasswordValidityCheckpointLocked(userId, /* parent */ false);
updatePasswordExpirationsLocked(userId);
@@ -6086,7 +6135,7 @@
ActiveAdmin strictestAdmin = null;
final long ident = mInjector.binderClearCallingIdentity();
try {
- synchronized (this) {
+ synchronized (getLockObject()) {
DevicePolicyData policy = getUserData(userHandle);
policy.mFailedPasswordAttempts++;
saveSettingsLocked(userHandle);
@@ -6146,7 +6195,7 @@
mContext.enforceCallingOrSelfPermission(
android.Manifest.permission.BIND_DEVICE_ADMIN, null);
- synchronized (this) {
+ synchronized (getLockObject()) {
DevicePolicyData policy = getUserData(userHandle);
if (policy.mFailedPasswordAttempts != 0 || policy.mPasswordOwner >= 0) {
long ident = mInjector.binderClearCallingIdentity();
@@ -6221,7 +6270,7 @@
if (!mHasFeature) {
return null;
}
- synchronized(this) {
+ synchronized (getLockObject()) {
Preconditions.checkNotNull(who, "ComponentName is null");
// Only check if system user has set global proxy. We don't allow other users to set it.
@@ -6276,7 +6325,7 @@
return null;
}
enforceFullCrossUsersPermission(userHandle);
- synchronized(this) {
+ synchronized (getLockObject()) {
DevicePolicyData policy = getUserData(UserHandle.USER_SYSTEM);
// Scan through active admins and find if anyone has already
// set the global proxy.
@@ -6296,7 +6345,7 @@
@Override
public void setRecommendedGlobalProxy(ComponentName who, ProxyInfo proxyInfo) {
- synchronized (this) {
+ synchronized (getLockObject()) {
getActiveAdminForCallerLocked(who, DeviceAdminInfo.USES_POLICY_DEVICE_OWNER);
}
long token = mInjector.binderClearCallingIdentity();
@@ -6365,7 +6414,7 @@
}
Preconditions.checkNotNull(who, "ComponentName is null");
final int userHandle = UserHandle.getCallingUserId();
- synchronized (this) {
+ synchronized (getLockObject()) {
// Check for permissions
// Only system user can set storage encryption
if (userHandle != UserHandle.USER_SYSTEM) {
@@ -6416,7 +6465,7 @@
return false;
}
enforceFullCrossUsersPermission(userHandle);
- synchronized (this) {
+ synchronized (getLockObject()) {
// Check for permissions if a particular caller is specified
if (who != null) {
// When checking for a single caller, status is based on caller's request
@@ -6519,7 +6568,7 @@
}
Preconditions.checkNotNull(who, "ComponentName is null");
final int userHandle = UserHandle.getCallingUserId();
- synchronized (this) {
+ synchronized (getLockObject()) {
ActiveAdmin ap = getActiveAdminForCallerLocked(who,
DeviceAdminInfo.USES_POLICY_PROFILE_OWNER);
if (ap.disableScreenCapture != disabled) {
@@ -6539,7 +6588,7 @@
if (!mHasFeature) {
return false;
}
- synchronized (this) {
+ synchronized (getLockObject()) {
if (who != null) {
ActiveAdmin admin = getActiveAdminUncheckedLocked(who, userHandle);
return (admin != null) ? admin.disableScreenCapture : false;
@@ -6581,7 +6630,7 @@
}
Preconditions.checkNotNull(who, "ComponentName is null");
final int userHandle = UserHandle.getCallingUserId();
- synchronized (this) {
+ synchronized (getLockObject()) {
ActiveAdmin admin = getActiveAdminForCallerLocked(who,
DeviceAdminInfo.USES_POLICY_PROFILE_OWNER);
if (admin.requireAutoTime != required) {
@@ -6609,7 +6658,7 @@
if (!mHasFeature) {
return false;
}
- synchronized (this) {
+ synchronized (getLockObject()) {
ActiveAdmin deviceOwner = getDeviceOwnerAdminLocked();
if (deviceOwner != null && deviceOwner.requireAutoTime) {
// If the device owner enforces auto time, we don't need to check the PO's
@@ -6640,7 +6689,7 @@
"Cannot force ephemeral users on systems without split system user.");
}
boolean removeAllUsers = false;
- synchronized (this) {
+ synchronized (getLockObject()) {
final ActiveAdmin deviceOwner =
getActiveAdminForCallerLocked(who, DeviceAdminInfo.USES_POLICY_DEVICE_OWNER);
if (deviceOwner.forceEphemeralUsers != forceEphemeralUsers) {
@@ -6666,7 +6715,7 @@
return false;
}
Preconditions.checkNotNull(who, "ComponentName is null");
- synchronized (this) {
+ synchronized (getLockObject()) {
final ActiveAdmin deviceOwner =
getActiveAdminForCallerLocked(who, DeviceAdminInfo.USES_POLICY_DEVICE_OWNER);
return deviceOwner.forceEphemeralUsers;
@@ -6674,7 +6723,7 @@
}
private void ensureDeviceOwnerAndAllUsersAffiliated(ComponentName who) throws SecurityException {
- synchronized (this) {
+ synchronized (getLockObject()) {
getActiveAdminForCallerLocked(who, DeviceAdminInfo.USES_POLICY_DEVICE_OWNER);
if (!areAllUsersAffiliatedWithDeviceLocked()) {
throw new SecurityException("Not all users are affiliated.");
@@ -6701,7 +6750,7 @@
}
final long currentTime = System.currentTimeMillis();
- synchronized (this) {
+ synchronized (getLockObject()) {
DevicePolicyData policyData = getUserData(UserHandle.USER_SYSTEM);
if (currentTime > policyData.mLastBugReportRequestTime) {
policyData.mLastBugReportRequestTime = currentTime;
@@ -6736,7 +6785,7 @@
void sendDeviceOwnerCommand(String action, Bundle extras) {
int deviceOwnerUserId;
ComponentName deviceOwnerComponent;
- synchronized (this) {
+ synchronized (getLockObject()) {
deviceOwnerUserId = mOwners.getDeviceOwnerUserId();
deviceOwnerComponent = mOwners.getDeviceOwnerComponent();
}
@@ -6765,13 +6814,17 @@
mContext.sendBroadcastAsUser(intent, UserHandle.of(userId));
}
- private synchronized String getDeviceOwnerRemoteBugreportUri() {
- return mOwners.getDeviceOwnerRemoteBugreportUri();
+ private String getDeviceOwnerRemoteBugreportUri() {
+ synchronized (getLockObject()) {
+ return mOwners.getDeviceOwnerRemoteBugreportUri();
+ }
}
- private synchronized void setDeviceOwnerRemoteBugreportUriAndHash(String bugreportUri,
+ private void setDeviceOwnerRemoteBugreportUriAndHash(String bugreportUri,
String bugreportHash) {
- mOwners.setDeviceOwnerRemoteBugreportUriAndHash(bugreportUri, bugreportHash);
+ synchronized (getLockObject()) {
+ mOwners.setDeviceOwnerRemoteBugreportUriAndHash(bugreportUri, bugreportHash);
+ }
}
private void registerRemoteBugreportReceivers() {
@@ -6833,7 +6886,7 @@
mRemoteBugreportSharingAccepted.set(true);
String bugreportUriString = null;
String bugreportHash = null;
- synchronized (this) {
+ synchronized (getLockObject()) {
bugreportUriString = getDeviceOwnerRemoteBugreportUri();
bugreportHash = mOwners.getDeviceOwnerRemoteBugreportHash();
}
@@ -6870,7 +6923,7 @@
Uri bugreportUri = Uri.parse(bugreportUriString);
pfd = mContext.getContentResolver().openFileDescriptor(bugreportUri, "r");
- synchronized (this) {
+ synchronized (getLockObject()) {
Intent intent = new Intent(DeviceAdminReceiver.ACTION_BUGREPORT_SHARE);
intent.setComponent(mOwners.getDeviceOwnerComponent());
intent.setDataAndType(bugreportUri, RemoteBugreportUtils.BUGREPORT_MIMETYPE);
@@ -6911,7 +6964,7 @@
}
Preconditions.checkNotNull(who, "ComponentName is null");
final int userHandle = mInjector.userHandleGetCallingUserId();
- synchronized (this) {
+ synchronized (getLockObject()) {
ActiveAdmin ap = getActiveAdminForCallerLocked(who,
DeviceAdminInfo.USES_POLICY_DISABLE_CAMERA);
if (ap.disableCamera != disabled) {
@@ -6937,7 +6990,7 @@
if (!mHasFeature) {
return false;
}
- synchronized (this) {
+ synchronized (getLockObject()) {
if (who != null) {
ActiveAdmin admin = getActiveAdminUncheckedLocked(who, userHandle);
return (admin != null) ? admin.disableCamera : false;
@@ -6978,7 +7031,7 @@
which = which & PROFILE_KEYGUARD_FEATURES;
}
}
- synchronized (this) {
+ synchronized (getLockObject()) {
ActiveAdmin ap = getActiveAdminForCallerLocked(
who, DeviceAdminInfo.USES_POLICY_DISABLE_KEYGUARD_FEATURES, parent);
if (ap.disabledKeyguardFeatures != which) {
@@ -7005,7 +7058,7 @@
enforceFullCrossUsersPermission(userHandle);
final long ident = mInjector.binderClearCallingIdentity();
try {
- synchronized (this) {
+ synchronized (getLockObject()) {
if (who != null) {
ActiveAdmin admin = getActiveAdminUncheckedLocked(who, userHandle, parent);
return (admin != null) ? admin.disabledKeyguardFeatures : 0;
@@ -7053,7 +7106,7 @@
}
Preconditions.checkNotNull(packageList, "packageList is null");
final int userHandle = UserHandle.getCallingUserId();
- synchronized (this) {
+ synchronized (getLockObject()) {
// Ensure the caller is a DO or a keep uninstalled packages delegate.
enforceCanManageScope(who, callerPackage, DeviceAdminInfo.USES_POLICY_DEVICE_OWNER,
DELEGATION_KEEP_UNINSTALLED_PACKAGES);
@@ -7074,7 +7127,7 @@
return null;
}
// TODO In split system user mode, allow apps on user 0 to query the list
- synchronized (this) {
+ synchronized (getLockObject()) {
// Ensure the caller is a DO or a keep uninstalled packages delegate.
enforceCanManageScope(who, callerPackage, DeviceAdminInfo.USES_POLICY_DEVICE_OWNER,
DELEGATION_KEEP_UNINSTALLED_PACKAGES);
@@ -7099,7 +7152,7 @@
}
final boolean hasIncompatibleAccountsOrNonAdb =
hasIncompatibleAccountsOrNonAdbNoLock(userId, admin);
- synchronized (this) {
+ synchronized (getLockObject()) {
enforceCanSetDeviceOwnerLocked(admin, userId, hasIncompatibleAccountsOrNonAdb);
final ActiveAdmin activeAdmin = getActiveAdminUncheckedLocked(admin, userId);
if (activeAdmin == null
@@ -7168,7 +7221,7 @@
}
public boolean isDeviceOwner(ComponentName who, int userId) {
- synchronized (this) {
+ synchronized (getLockObject()) {
return mOwners.hasDeviceOwner()
&& mOwners.getDeviceOwnerUserId() == userId
&& mOwners.getDeviceOwnerComponent().equals(who);
@@ -7176,7 +7229,7 @@
}
private boolean isDeviceOwnerPackage(String packageName, int userId) {
- synchronized (this) {
+ synchronized (getLockObject()) {
return mOwners.hasDeviceOwner()
&& mOwners.getDeviceOwnerUserId() == userId
&& mOwners.getDeviceOwnerPackageName().equals(packageName);
@@ -7184,7 +7237,7 @@
}
private boolean isProfileOwnerPackage(String packageName, int userId) {
- synchronized (this) {
+ synchronized (getLockObject()) {
return mOwners.hasProfileOwner(userId)
&& mOwners.getProfileOwnerPackage(userId).equals(packageName);
}
@@ -7203,7 +7256,7 @@
if (!callingUserOnly) {
enforceManageUsers();
}
- synchronized (this) {
+ synchronized (getLockObject()) {
if (!mOwners.hasDeviceOwner()) {
return null;
}
@@ -7221,7 +7274,7 @@
return UserHandle.USER_NULL;
}
enforceManageUsers();
- synchronized (this) {
+ synchronized (getLockObject()) {
return mOwners.hasDeviceOwner() ? mOwners.getDeviceOwnerUserId() : UserHandle.USER_NULL;
}
}
@@ -7236,7 +7289,7 @@
return null;
}
enforceManageUsers();
- synchronized (this) {
+ synchronized (getLockObject()) {
if (!mOwners.hasDeviceOwner()) {
return null;
}
@@ -7250,6 +7303,7 @@
/** Returns the active device owner or {@code null} if there is no device owner. */
@VisibleForTesting
ActiveAdmin getDeviceOwnerAdminLocked() {
+ ensureLocked();
ComponentName component = mOwners.getDeviceOwnerComponent();
if (component == null) {
return null;
@@ -7280,7 +7334,7 @@
} catch (NameNotFoundException e) {
throw new SecurityException(e);
}
- synchronized (this) {
+ synchronized (getLockObject()) {
final ComponentName deviceOwnerComponent = mOwners.getDeviceOwnerComponent();
final int deviceOwnerUserId = mOwners.getDeviceOwnerUserId();
if (!mOwners.hasDeviceOwner()
@@ -7368,7 +7422,7 @@
}
final boolean hasIncompatibleAccountsOrNonAdb =
hasIncompatibleAccountsOrNonAdbNoLock(userHandle, who);
- synchronized (this) {
+ synchronized (getLockObject()) {
enforceCanSetProfileOwnerLocked(who, userHandle, hasIncompatibleAccountsOrNonAdb);
final ActiveAdmin admin = getActiveAdminUncheckedLocked(who, userHandle);
@@ -7414,7 +7468,7 @@
final int userId = mInjector.userHandleGetCallingUserId();
enforceNotManagedProfile(userId, "clear profile owner");
enforceUserUnlocked(userId);
- synchronized (this) {
+ synchronized (getLockObject()) {
// Check if this is the profile owner who is calling
final ActiveAdmin admin =
getActiveAdminForCallerLocked(who, DeviceAdminInfo.USES_POLICY_PROFILE_OWNER);
@@ -7457,7 +7511,7 @@
return;
}
- synchronized (this) {
+ synchronized (getLockObject()) {
getActiveAdminForCallerLocked(who, DeviceAdminInfo.USES_POLICY_DEVICE_OWNER);
long token = mInjector.binderClearCallingIdentity();
try {
@@ -7546,7 +7600,7 @@
+ "device or profile owner is set.");
}
- synchronized (this) {
+ synchronized (getLockObject()) {
boolean transitionCheckNeeded = true;
// Calling identity/permission checks.
@@ -7616,7 +7670,7 @@
return;
}
Preconditions.checkNotNull(who, "ComponentName is null");
- synchronized (this) {
+ synchronized (getLockObject()) {
// Check if this is the profile owner who is calling
getActiveAdminForCallerLocked(who, DeviceAdminInfo.USES_POLICY_PROFILE_OWNER);
final int userId = UserHandle.getCallingUserId();
@@ -7664,7 +7718,7 @@
return null;
}
- synchronized (this) {
+ synchronized (getLockObject()) {
return mOwners.getProfileOwnerComponent(userHandle);
}
}
@@ -7881,7 +7935,7 @@
}
private void enforceDeviceOwnerOrManageUsers() {
- synchronized (this) {
+ synchronized (getLockObject()) {
if (getActiveAdminWithPolicyForUidLocked(null, DeviceAdminInfo.USES_POLICY_DEVICE_OWNER,
mInjector.binderGetCallingUid()) != null) {
return;
@@ -7891,7 +7945,7 @@
}
private void enforceProfileOwnerOrSystemUser() {
- synchronized (this) {
+ synchronized (getLockObject()) {
if (getActiveAdminWithPolicyForUidLocked(null,
DeviceAdminInfo.USES_POLICY_PROFILE_OWNER, mInjector.binderGetCallingUid())
!= null) {
@@ -7904,7 +7958,7 @@
private void enforceProfileOwnerOrFullCrossUsersPermission(int userId) {
if (userId == mInjector.userHandleGetCallingUserId()) {
- synchronized (this) {
+ synchronized (getLockObject()) {
if (getActiveAdminWithPolicyForUidLocked(null,
DeviceAdminInfo.USES_POLICY_PROFILE_OWNER, mInjector.binderGetCallingUid())
!= null) {
@@ -8017,7 +8071,7 @@
protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
if (!DumpUtils.checkDumpPermission(mContext, LOG_TAG, pw)) return;
- synchronized (this) {
+ synchronized (getLockObject()) {
pw.println("Current Device Policy Manager state:");
mOwners.dump(" ", pw);
@@ -8048,6 +8102,8 @@
pw.println();
mConstants.dump(" ", pw);
pw.println();
+ mStatLogger.dump(pw, " ");
+ pw.println();
pw.println(" Encryption Status: " + getEncryptionStatusName(getEncryptionStatus()));
}
}
@@ -8076,7 +8132,7 @@
ComponentName activity) {
Preconditions.checkNotNull(who, "ComponentName is null");
final int userHandle = UserHandle.getCallingUserId();
- synchronized (this) {
+ synchronized (getLockObject()) {
getActiveAdminForCallerLocked(who, DeviceAdminInfo.USES_POLICY_PROFILE_OWNER);
long id = mInjector.binderClearCallingIdentity();
@@ -8095,7 +8151,7 @@
public void clearPackagePersistentPreferredActivities(ComponentName who, String packageName) {
Preconditions.checkNotNull(who, "ComponentName is null");
final int userHandle = UserHandle.getCallingUserId();
- synchronized (this) {
+ synchronized (getLockObject()) {
getActiveAdminForCallerLocked(who, DeviceAdminInfo.USES_POLICY_PROFILE_OWNER);
long id = mInjector.binderClearCallingIdentity();
@@ -8113,7 +8169,7 @@
@Override
public void setDefaultSmsApplication(ComponentName admin, String packageName) {
Preconditions.checkNotNull(admin, "ComponentName is null");
- synchronized (this) {
+ synchronized (getLockObject()) {
getActiveAdminForCallerLocked(admin, DeviceAdminInfo.USES_POLICY_DEVICE_OWNER);
}
mInjector.binderWithCleanCallingIdentity(() ->
@@ -8167,7 +8223,7 @@
Preconditions.checkNotNull(admin, "admin is null");
Preconditions.checkNotNull(agent, "agent is null");
final int userHandle = UserHandle.getCallingUserId();
- synchronized (this) {
+ synchronized (getLockObject()) {
ActiveAdmin ap = getActiveAdminForCallerLocked(admin,
DeviceAdminInfo.USES_POLICY_DISABLE_KEYGUARD_FEATURES, parent);
ap.trustAgentInfos.put(agent.flattenToString(), new TrustAgentInfo(args));
@@ -8184,7 +8240,7 @@
Preconditions.checkNotNull(agent, "agent null");
enforceFullCrossUsersPermission(userHandle);
- synchronized (this) {
+ synchronized (getLockObject()) {
final String componentName = agent.flattenToString();
if (admin != null) {
final ActiveAdmin ap = getActiveAdminUncheckedLocked(admin, userHandle, parent);
@@ -8234,7 +8290,7 @@
@Override
public void setRestrictionsProvider(ComponentName who, ComponentName permissionProvider) {
Preconditions.checkNotNull(who, "ComponentName is null");
- synchronized (this) {
+ synchronized (getLockObject()) {
getActiveAdminForCallerLocked(who, DeviceAdminInfo.USES_POLICY_PROFILE_OWNER);
int userHandle = UserHandle.getCallingUserId();
@@ -8246,7 +8302,7 @@
@Override
public ComponentName getRestrictionsProvider(int userHandle) {
- synchronized (this) {
+ synchronized (getLockObject()) {
if (!isCallerWithSystemUid()) {
throw new SecurityException("Only the system can query the permission provider");
}
@@ -8259,7 +8315,7 @@
public void addCrossProfileIntentFilter(ComponentName who, IntentFilter filter, int flags) {
Preconditions.checkNotNull(who, "ComponentName is null");
int callingUserId = UserHandle.getCallingUserId();
- synchronized (this) {
+ synchronized (getLockObject()) {
getActiveAdminForCallerLocked(who, DeviceAdminInfo.USES_POLICY_PROFILE_OWNER);
long id = mInjector.binderClearCallingIdentity();
@@ -8290,7 +8346,7 @@
public void clearCrossProfileIntentFilters(ComponentName who) {
Preconditions.checkNotNull(who, "ComponentName is null");
int callingUserId = UserHandle.getCallingUserId();
- synchronized (this) {
+ synchronized (getLockObject()) {
getActiveAdminForCallerLocked(who, DeviceAdminInfo.USES_POLICY_PROFILE_OWNER);
long id = mInjector.binderClearCallingIdentity();
try {
@@ -8397,7 +8453,7 @@
}
}
- synchronized (this) {
+ synchronized (getLockObject()) {
ActiveAdmin admin = getActiveAdminForCallerLocked(who,
DeviceAdminInfo.USES_POLICY_PROFILE_OWNER);
admin.permittedAccessiblityServices = packageList;
@@ -8413,7 +8469,7 @@
}
Preconditions.checkNotNull(who, "ComponentName is null");
- synchronized (this) {
+ synchronized (getLockObject()) {
ActiveAdmin admin = getActiveAdminForCallerLocked(who,
DeviceAdminInfo.USES_POLICY_PROFILE_OWNER);
return admin.permittedAccessiblityServices;
@@ -8425,7 +8481,7 @@
if (!mHasFeature) {
return null;
}
- synchronized (this) {
+ synchronized (getLockObject()) {
List<String> result = null;
// If we have multiple profiles we return the intersection of the
// permitted lists. This can happen in cases where we have a device
@@ -8492,7 +8548,7 @@
throw new SecurityException(
"Only the system can query if an accessibility service is disabled by admin");
}
- synchronized (this) {
+ synchronized (getLockObject()) {
ActiveAdmin admin = getActiveAdminUncheckedLocked(who, userHandle);
if (admin == null) {
return false;
@@ -8570,7 +8626,7 @@
}
}
- synchronized (this) {
+ synchronized (getLockObject()) {
ActiveAdmin admin = getActiveAdminForCallerLocked(who,
DeviceAdminInfo.USES_POLICY_PROFILE_OWNER);
admin.permittedInputMethods = packageList;
@@ -8586,7 +8642,7 @@
}
Preconditions.checkNotNull(who, "ComponentName is null");
- synchronized (this) {
+ synchronized (getLockObject()) {
ActiveAdmin admin = getActiveAdminForCallerLocked(who,
DeviceAdminInfo.USES_POLICY_PROFILE_OWNER);
return admin.permittedInputMethods;
@@ -8606,7 +8662,7 @@
}
int userId = currentUser.id;
- synchronized (this) {
+ synchronized (getLockObject()) {
List<String> result = null;
// If we have multiple profiles we return the intersection of the
// permitted lists. This can happen in cases where we have a device
@@ -8666,7 +8722,7 @@
throw new SecurityException(
"Only the system can query if an input method is disabled by admin");
}
- synchronized (this) {
+ synchronized (getLockObject()) {
ActiveAdmin admin = getActiveAdminUncheckedLocked(who, userHandle);
if (admin == null) {
return false;
@@ -8692,7 +8748,7 @@
return false;
}
- synchronized (this) {
+ synchronized (getLockObject()) {
ActiveAdmin admin = getActiveAdminForCallerLocked(
who, DeviceAdminInfo.USES_POLICY_PROFILE_OWNER);
admin.permittedNotificationListeners = packageList;
@@ -8708,7 +8764,7 @@
}
Preconditions.checkNotNull(who, "ComponentName is null");
- synchronized (this) {
+ synchronized (getLockObject()) {
ActiveAdmin admin = getActiveAdminForCallerLocked(
who, DeviceAdminInfo.USES_POLICY_PROFILE_OWNER);
return admin.permittedNotificationListeners;
@@ -8726,7 +8782,7 @@
throw new SecurityException(
"Only the system can query if a notification listener service is permitted");
}
- synchronized (this) {
+ synchronized (getLockObject()) {
ActiveAdmin profileOwner = getProfileOwnerAdminLocked(userId);
if (profileOwner == null || profileOwner.permittedNotificationListeners == null) {
return true;
@@ -8782,7 +8838,7 @@
// Create user.
UserHandle user = null;
- synchronized (this) {
+ synchronized (getLockObject()) {
getActiveAdminForCallerLocked(admin, DeviceAdminInfo.USES_POLICY_DEVICE_OWNER);
final int callingUid = mInjector.binderGetCallingUid();
@@ -8871,7 +8927,7 @@
final String ownerName = getProfileOwnerName(Process.myUserHandle().getIdentifier());
setProfileOwner(profileOwner, ownerName, userHandle);
- synchronized (this) {
+ synchronized (getLockObject()) {
DevicePolicyData policyData = getUserData(userHandle);
policyData.mInitBundle = adminExtras;
policyData.mAdminBroadcastPending = true;
@@ -8902,7 +8958,7 @@
Preconditions.checkNotNull(who, "ComponentName is null");
Preconditions.checkNotNull(userHandle, "UserHandle is null");
- synchronized (this) {
+ synchronized (getLockObject()) {
getActiveAdminForCallerLocked(who, DeviceAdminInfo.USES_POLICY_DEVICE_OWNER);
}
@@ -8941,7 +8997,7 @@
public boolean switchUser(ComponentName who, UserHandle userHandle) {
Preconditions.checkNotNull(who, "ComponentName is null");
- synchronized (this) {
+ synchronized (getLockObject()) {
getActiveAdminForCallerLocked(who, DeviceAdminInfo.USES_POLICY_DEVICE_OWNER);
long id = mInjector.binderClearCallingIdentity();
@@ -8965,7 +9021,7 @@
Preconditions.checkNotNull(who, "ComponentName is null");
Preconditions.checkNotNull(userHandle, "UserHandle is null");
- synchronized (this) {
+ synchronized (getLockObject()) {
getActiveAdminForCallerLocked(who, DeviceAdminInfo.USES_POLICY_DEVICE_OWNER);
}
@@ -9000,7 +9056,7 @@
Preconditions.checkNotNull(who, "ComponentName is null");
Preconditions.checkNotNull(userHandle, "UserHandle is null");
- synchronized (this) {
+ synchronized (getLockObject()) {
getActiveAdminForCallerLocked(who, DeviceAdminInfo.USES_POLICY_DEVICE_OWNER);
}
@@ -9018,7 +9074,7 @@
Preconditions.checkNotNull(who, "ComponentName is null");
final int callingUserId = mInjector.userHandleGetCallingUserId();
- synchronized (this) {
+ synchronized (getLockObject()) {
getActiveAdminForCallerLocked(who, DeviceAdminInfo.USES_POLICY_PROFILE_OWNER);
if (!isUserAffiliatedWithDeviceLocked(callingUserId)) {
throw new SecurityException("Admin " + who +
@@ -9070,7 +9126,7 @@
@Override
public List<UserHandle> getSecondaryUsers(ComponentName who) {
Preconditions.checkNotNull(who, "ComponentName is null");
- synchronized (this) {
+ synchronized (getLockObject()) {
getActiveAdminForCallerLocked(who, DeviceAdminInfo.USES_POLICY_DEVICE_OWNER);
}
@@ -9094,7 +9150,7 @@
@Override
public boolean isEphemeralUser(ComponentName who) {
Preconditions.checkNotNull(who, "ComponentName is null");
- synchronized (this) {
+ synchronized (getLockObject()) {
getActiveAdminForCallerLocked(who, DeviceAdminInfo.USES_POLICY_PROFILE_OWNER);
}
@@ -9129,7 +9185,7 @@
public String[] setPackagesSuspended(ComponentName who, String callerPackage,
String[] packageNames, boolean suspended) {
int callingUserId = UserHandle.getCallingUserId();
- synchronized (this) {
+ synchronized (getLockObject()) {
// Ensure the caller is a DO/PO or a package access delegate.
enforceCanManageScope(who, callerPackage, DeviceAdminInfo.USES_POLICY_PROFILE_OWNER,
DELEGATION_PACKAGE_ACCESS);
@@ -9137,7 +9193,7 @@
long id = mInjector.binderClearCallingIdentity();
try {
return mIPackageManager.setPackagesSuspendedAsUser(
- packageNames, suspended, null, null, "android", callingUserId);
+ packageNames, suspended, null, null, null, "android", callingUserId);
} catch (RemoteException re) {
// Shouldn't happen.
Slog.e(LOG_TAG, "Failed talking to the package manager", re);
@@ -9151,7 +9207,7 @@
@Override
public boolean isPackageSuspended(ComponentName who, String callerPackage, String packageName) {
int callingUserId = UserHandle.getCallingUserId();
- synchronized (this) {
+ synchronized (getLockObject()) {
// Ensure the caller is a DO/PO or a package access delegate.
enforceCanManageScope(who, callerPackage, DeviceAdminInfo.USES_POLICY_PROFILE_OWNER,
DELEGATION_PACKAGE_ACCESS);
@@ -9177,7 +9233,7 @@
}
final int userHandle = mInjector.userHandleGetCallingUserId();
- synchronized (this) {
+ synchronized (getLockObject()) {
final ActiveAdmin activeAdmin =
getActiveAdminForCallerLocked(who,
DeviceAdminInfo.USES_POLICY_PROFILE_OWNER);
@@ -9216,7 +9272,7 @@
}
private void pushUserRestrictions(int userId) {
- synchronized (this) {
+ synchronized (getLockObject()) {
final boolean isDeviceOwner = mOwners.isDeviceOwnerUserId(userId);
final Bundle userRestrictions;
// Whether device owner enforces camera restriction.
@@ -9263,7 +9319,7 @@
return null;
}
Preconditions.checkNotNull(who, "ComponentName is null");
- synchronized (this) {
+ synchronized (getLockObject()) {
final ActiveAdmin activeAdmin = getActiveAdminForCallerLocked(who,
DeviceAdminInfo.USES_POLICY_PROFILE_OWNER);
return activeAdmin.userRestrictions;
@@ -9274,7 +9330,7 @@
public boolean setApplicationHidden(ComponentName who, String callerPackage, String packageName,
boolean hidden) {
int callingUserId = UserHandle.getCallingUserId();
- synchronized (this) {
+ synchronized (getLockObject()) {
// Ensure the caller is a DO/PO or a package access delegate.
enforceCanManageScope(who, callerPackage, DeviceAdminInfo.USES_POLICY_PROFILE_OWNER,
DELEGATION_PACKAGE_ACCESS);
@@ -9297,7 +9353,7 @@
public boolean isApplicationHidden(ComponentName who, String callerPackage,
String packageName) {
int callingUserId = UserHandle.getCallingUserId();
- synchronized (this) {
+ synchronized (getLockObject()) {
// Ensure the caller is a DO/PO or a package access delegate.
enforceCanManageScope(who, callerPackage, DeviceAdminInfo.USES_POLICY_PROFILE_OWNER,
DELEGATION_PACKAGE_ACCESS);
@@ -9318,7 +9374,7 @@
@Override
public void enableSystemApp(ComponentName who, String callerPackage, String packageName) {
- synchronized (this) {
+ synchronized (getLockObject()) {
// Ensure the caller is a DO/PO or an enable system app delegate.
enforceCanManageScope(who, callerPackage, DeviceAdminInfo.USES_POLICY_PROFILE_OWNER,
DELEGATION_ENABLE_SYSTEM_APP);
@@ -9359,7 +9415,7 @@
@Override
public int enableSystemAppWithIntent(ComponentName who, String callerPackage, Intent intent) {
- synchronized (this) {
+ synchronized (getLockObject()) {
// Ensure the caller is a DO/PO or an enable system app delegate.
enforceCanManageScope(who, callerPackage, DeviceAdminInfo.USES_POLICY_PROFILE_OWNER,
DELEGATION_ENABLE_SYSTEM_APP);
@@ -9421,7 +9477,7 @@
@Override
public boolean installExistingPackage(ComponentName who, String callerPackage,
String packageName) {
- synchronized (this) {
+ synchronized (getLockObject()) {
// Ensure the caller is a PO or an install existing package delegate
enforceCanManageScope(who, callerPackage, DeviceAdminInfo.USES_POLICY_PROFILE_OWNER,
DELEGATION_INSTALL_EXISTING_PACKAGE);
@@ -9458,7 +9514,7 @@
return;
}
Preconditions.checkNotNull(who, "ComponentName is null");
- synchronized (this) {
+ synchronized (getLockObject()) {
ActiveAdmin ap = getActiveAdminForCallerLocked(who,
DeviceAdminInfo.USES_POLICY_PROFILE_OWNER);
if (disabled) {
@@ -9481,7 +9537,7 @@
if (!mHasFeature) {
return null;
}
- synchronized (this) {
+ synchronized (getLockObject()) {
DevicePolicyData policy = getUserData(userId);
final int N = policy.mAdminList.size();
ArraySet<String> resultSet = new ArraySet<>();
@@ -9497,7 +9553,7 @@
public void setUninstallBlocked(ComponentName who, String callerPackage, String packageName,
boolean uninstallBlocked) {
final int userId = UserHandle.getCallingUserId();
- synchronized (this) {
+ synchronized (getLockObject()) {
// Ensure the caller is a DO/PO or a block uninstall delegate
enforceCanManageScope(who, callerPackage, DeviceAdminInfo.USES_POLICY_PROFILE_OWNER,
DELEGATION_BLOCK_UNINSTALL);
@@ -9521,7 +9577,7 @@
// when the package is a system app, or when it is an active device admin.
final int userId = UserHandle.getCallingUserId();
- synchronized (this) {
+ synchronized (getLockObject()) {
if (who != null) {
getActiveAdminForCallerLocked(who, DeviceAdminInfo.USES_POLICY_PROFILE_OWNER);
}
@@ -9545,7 +9601,7 @@
return;
}
Preconditions.checkNotNull(who, "ComponentName is null");
- synchronized (this) {
+ synchronized (getLockObject()) {
ActiveAdmin admin = getActiveAdminForCallerLocked(who,
DeviceAdminInfo.USES_POLICY_PROFILE_OWNER);
if (admin.disableCallerId != disabled) {
@@ -9561,7 +9617,7 @@
return false;
}
Preconditions.checkNotNull(who, "ComponentName is null");
- synchronized (this) {
+ synchronized (getLockObject()) {
ActiveAdmin admin = getActiveAdminForCallerLocked(who,
DeviceAdminInfo.USES_POLICY_PROFILE_OWNER);
return admin.disableCallerId;
@@ -9571,7 +9627,7 @@
@Override
public boolean getCrossProfileCallerIdDisabledForUser(int userId) {
enforceCrossUsersPermission(userId);
- synchronized (this) {
+ synchronized (getLockObject()) {
ActiveAdmin admin = getProfileOwnerAdminLocked(userId);
return (admin != null) ? admin.disableCallerId : false;
}
@@ -9583,7 +9639,7 @@
return;
}
Preconditions.checkNotNull(who, "ComponentName is null");
- synchronized (this) {
+ synchronized (getLockObject()) {
ActiveAdmin admin = getActiveAdminForCallerLocked(who,
DeviceAdminInfo.USES_POLICY_PROFILE_OWNER);
if (admin.disableContactsSearch != disabled) {
@@ -9599,7 +9655,7 @@
return false;
}
Preconditions.checkNotNull(who, "ComponentName is null");
- synchronized (this) {
+ synchronized (getLockObject()) {
ActiveAdmin admin = getActiveAdminForCallerLocked(who,
DeviceAdminInfo.USES_POLICY_PROFILE_OWNER);
return admin.disableContactsSearch;
@@ -9609,7 +9665,7 @@
@Override
public boolean getCrossProfileContactsSearchDisabledForUser(int userId) {
enforceCrossUsersPermission(userId);
- synchronized (this) {
+ synchronized (getLockObject()) {
ActiveAdmin admin = getProfileOwnerAdminLocked(userId);
return (admin != null) ? admin.disableContactsSearch : false;
}
@@ -9624,7 +9680,7 @@
final long ident = mInjector.binderClearCallingIdentity();
try {
- synchronized (this) {
+ synchronized (getLockObject()) {
final int managedUserId = getManagedUserId(callingUserId);
if (managedUserId < 0) {
return;
@@ -9682,7 +9738,7 @@
return;
}
Preconditions.checkNotNull(who, "ComponentName is null");
- synchronized (this) {
+ synchronized (getLockObject()) {
ActiveAdmin admin = getActiveAdminForCallerLocked(who,
DeviceAdminInfo.USES_POLICY_PROFILE_OWNER);
if (admin.disableBluetoothContactSharing != disabled) {
@@ -9698,7 +9754,7 @@
return false;
}
Preconditions.checkNotNull(who, "ComponentName is null");
- synchronized (this) {
+ synchronized (getLockObject()) {
ActiveAdmin admin = getActiveAdminForCallerLocked(who,
DeviceAdminInfo.USES_POLICY_PROFILE_OWNER);
return admin.disableBluetoothContactSharing;
@@ -9710,7 +9766,7 @@
// TODO: Should there be a check to make sure this relationship is
// within a profile group?
// enforceSystemProcess("getCrossProfileCallerIdDisabled can only be called by system");
- synchronized (this) {
+ synchronized (getLockObject()) {
ActiveAdmin admin = getProfileOwnerAdminLocked(userId);
return (admin != null) ? admin.disableBluetoothContactSharing : false;
}
@@ -9722,7 +9778,7 @@
Preconditions.checkNotNull(who, "ComponentName is null");
Preconditions.checkNotNull(packages, "packages is null");
- synchronized (this) {
+ synchronized (getLockObject()) {
enforceCanCallLockTaskLocked(who);
final int userHandle = mInjector.userHandleGetCallingUserId();
setLockTaskPackagesLocked(userHandle, new ArrayList<>(Arrays.asList(packages)));
@@ -9743,7 +9799,7 @@
Preconditions.checkNotNull(who, "ComponentName is null");
final int userHandle = mInjector.binderGetCallingUserHandle().getIdentifier();
- synchronized (this) {
+ synchronized (getLockObject()) {
enforceCanCallLockTaskLocked(who);
final List<String> packages = getUserData(userHandle).mLockTaskPackages;
return packages.toArray(new String[packages.size()]);
@@ -9753,7 +9809,7 @@
@Override
public boolean isLockTaskPermitted(String pkg) {
final int userHandle = mInjector.userHandleGetCallingUserId();
- synchronized (this) {
+ synchronized (getLockObject()) {
return getUserData(userHandle).mLockTaskPackages.contains(pkg);
}
}
@@ -9772,7 +9828,7 @@
"Cannot use LOCK_TASK_FEATURE_NOTIFICATIONS without LOCK_TASK_FEATURE_HOME");
final int userHandle = mInjector.userHandleGetCallingUserId();
- synchronized (this) {
+ synchronized (getLockObject()) {
enforceCanCallLockTaskLocked(who);
setLockTaskFeaturesLocked(userHandle, flags);
}
@@ -9789,7 +9845,7 @@
public int getLockTaskFeatures(ComponentName who) {
Preconditions.checkNotNull(who, "ComponentName is null");
final int userHandle = mInjector.userHandleGetCallingUserId();
- synchronized (this) {
+ synchronized (getLockObject()) {
enforceCanCallLockTaskLocked(who);
return getUserData(userHandle).mLockTaskFeatures;
}
@@ -9828,7 +9884,7 @@
if (!isCallerWithSystemUid()) {
throw new SecurityException("notifyLockTaskModeChanged can only be called by system");
}
- synchronized (this) {
+ synchronized (getLockObject()) {
final DevicePolicyData policy = getUserData(userHandle);
if (policy.mStatusBarDisabled) {
@@ -9858,7 +9914,7 @@
public void setGlobalSetting(ComponentName who, String setting, String value) {
Preconditions.checkNotNull(who, "ComponentName is null");
- synchronized (this) {
+ synchronized (getLockObject()) {
getActiveAdminForCallerLocked(who, DeviceAdminInfo.USES_POLICY_DEVICE_OWNER);
// Some settings are no supported any more. However we do not want to throw a
@@ -9897,7 +9953,7 @@
Preconditions.checkNotNull(who, "ComponentName is null");
Preconditions.checkStringNotEmpty(setting, "String setting is null or empty");
- synchronized (this) {
+ synchronized (getLockObject()) {
getActiveAdminForCallerLocked(who, DeviceAdminInfo.USES_POLICY_PROFILE_OWNER);
if (!SYSTEM_SETTINGS_WHITELIST.contains(setting)) {
@@ -9942,7 +9998,7 @@
Preconditions.checkNotNull(who, "ComponentName is null");
int callingUserId = mInjector.userHandleGetCallingUserId();
- synchronized (this) {
+ synchronized (getLockObject()) {
getActiveAdminForCallerLocked(who, DeviceAdminInfo.USES_POLICY_PROFILE_OWNER);
if (isDeviceOwner(who, callingUserId)) {
@@ -10002,7 +10058,7 @@
@Override
public void setMasterVolumeMuted(ComponentName who, boolean on) {
Preconditions.checkNotNull(who, "ComponentName is null");
- synchronized (this) {
+ synchronized (getLockObject()) {
getActiveAdminForCallerLocked(who, DeviceAdminInfo.USES_POLICY_PROFILE_OWNER);
setUserRestriction(who, UserManager.DISALLOW_UNMUTE_DEVICE, on);
}
@@ -10011,7 +10067,7 @@
@Override
public boolean isMasterVolumeMuted(ComponentName who) {
Preconditions.checkNotNull(who, "ComponentName is null");
- synchronized (this) {
+ synchronized (getLockObject()) {
getActiveAdminForCallerLocked(who, DeviceAdminInfo.USES_POLICY_PROFILE_OWNER);
AudioManager audioManager =
@@ -10022,7 +10078,7 @@
@Override
public void setUserIcon(ComponentName who, Bitmap icon) {
- synchronized (this) {
+ synchronized (getLockObject()) {
Preconditions.checkNotNull(who, "ComponentName is null");
getActiveAdminForCallerLocked(who, DeviceAdminInfo.USES_POLICY_PROFILE_OWNER);
@@ -10040,7 +10096,7 @@
public boolean setKeyguardDisabled(ComponentName who, boolean disabled) {
Preconditions.checkNotNull(who, "ComponentName is null");
final int userId = mInjector.userHandleGetCallingUserId();
- synchronized (this) {
+ synchronized (getLockObject()) {
getActiveAdminForCallerLocked(who, DeviceAdminInfo.USES_POLICY_PROFILE_OWNER);
if (!isUserAffiliatedWithDeviceLocked(userId)) {
throw new SecurityException("Admin " + who +
@@ -10070,7 +10126,7 @@
@Override
public boolean setStatusBarDisabled(ComponentName who, boolean disabled) {
int userId = UserHandle.getCallingUserId();
- synchronized (this) {
+ synchronized (getLockObject()) {
getActiveAdminForCallerLocked(who, DeviceAdminInfo.USES_POLICY_PROFILE_OWNER);
if (!isUserAffiliatedWithDeviceLocked(userId)) {
throw new SecurityException("Admin " + who +
@@ -10139,7 +10195,7 @@
DevicePolicyData policy = getUserData(userHandle);
if (!policy.mUserSetupComplete) {
policy.mUserSetupComplete = true;
- synchronized (this) {
+ synchronized (getLockObject()) {
saveSettingsLocked(userHandle);
}
}
@@ -10149,7 +10205,7 @@
DevicePolicyData policy = getUserData(userHandle);
if (!policy.mPaired) {
policy.mPaired = true;
- synchronized (this) {
+ synchronized (getLockObject()) {
saveSettingsLocked(userHandle);
}
}
@@ -10166,7 +10222,7 @@
private final Uri mDefaultImeChanged = Settings.Secure.getUriFor(
Settings.Secure.DEFAULT_INPUT_METHOD);
- @GuardedBy("DevicePolicyManagerService.this")
+ @GuardedBy("getLockObject()")
private Set<Integer> mUserIdsWithPendingChangesByOwner = new ArraySet<>();
public SetupContentObserver(Handler handler) {
@@ -10182,7 +10238,7 @@
mInjector.registerContentObserver(mDefaultImeChanged, false, this, UserHandle.USER_ALL);
}
- @GuardedBy("DevicePolicyManagerService.this")
+ @GuardedBy("getLockObject()")
private void addPendingChangeByOwnerLocked(int userId) {
mUserIdsWithPendingChangesByOwner.add(userId);
}
@@ -10192,13 +10248,13 @@
if (mUserSetupComplete.equals(uri) || (mIsWatch && mPaired.equals(uri))) {
updateUserSetupCompleteAndPaired();
} else if (mDeviceProvisioned.equals(uri)) {
- synchronized (DevicePolicyManagerService.this) {
+ synchronized (getLockObject()) {
// Set PROPERTY_DEVICE_OWNER_PRESENT, for the SUW case where setting the property
// is delayed until device is marked as provisioned.
setDeviceOwnerSystemPropertyLocked();
}
} else if (mDefaultImeChanged.equals(uri)) {
- synchronized (DevicePolicyManagerService.this) {
+ synchronized (getLockObject()) {
if (mUserIdsWithPendingChangesByOwner.contains(userId)) {
// This change notification was triggered by the owner changing the current
// IME. Ignore it.
@@ -10220,7 +10276,7 @@
@Override
public List<String> getCrossProfileWidgetProviders(int profileId) {
- synchronized (DevicePolicyManagerService.this) {
+ synchronized (getLockObject()) {
if (mOwners == null) {
return Collections.emptyList();
}
@@ -10244,7 +10300,7 @@
@Override
public void addOnCrossProfileWidgetProvidersChangeListener(
OnCrossProfileWidgetProvidersChangeListener listener) {
- synchronized (DevicePolicyManagerService.this) {
+ synchronized (getLockObject()) {
if (mWidgetProviderListeners == null) {
mWidgetProviderListeners = new ArrayList<>();
}
@@ -10256,14 +10312,14 @@
@Override
public boolean isActiveAdminWithPolicy(int uid, int reqPolicy) {
- synchronized(DevicePolicyManagerService.this) {
+ synchronized (getLockObject()) {
return getActiveAdminWithPolicyForUidLocked(null, reqPolicy, uid) != null;
}
}
private void notifyCrossProfileProvidersChanged(int userId, List<String> packages) {
final List<OnCrossProfileWidgetProvidersChangeListener> listeners;
- synchronized (DevicePolicyManagerService.this) {
+ synchronized (getLockObject()) {
listeners = new ArrayList<>(mWidgetProviderListeners);
}
final int listenerCount = listeners.size();
@@ -10352,7 +10408,7 @@
@Override
public void reportSeparateProfileChallengeChanged(@UserIdInt int userId) {
- synchronized (DevicePolicyManagerService.this) {
+ synchronized (getLockObject()) {
updateMaximumTimeToLockLocked(userId);
}
}
@@ -10364,7 +10420,7 @@
@Override
public CharSequence getPrintingDisabledReasonForUser(@UserIdInt int userId) {
- synchronized (DevicePolicyManagerService.this) {
+ synchronized (getLockObject()) {
DevicePolicyData policy = getUserData(userId);
if (!mUserManager.hasUserRestriction(UserManager.DISALLOW_PRINTING,
UserHandle.of(userId))) {
@@ -10426,7 +10482,7 @@
if (DevicePolicyManager.POLICY_DISABLE_CAMERA.equals(restriction) ||
DevicePolicyManager.POLICY_DISABLE_SCREEN_CAPTURE.equals(restriction) ||
DevicePolicyManager.POLICY_MANDATORY_BACKUPS.equals(restriction)) {
- synchronized(this) {
+ synchronized (getLockObject()) {
final DevicePolicyData policy = getUserData(userId);
final int N = policy.mAdminList.size();
for (int i = 0; i < N; i++) {
@@ -10485,7 +10541,7 @@
policy.validateAgainstPreviousFreezePeriod(record.first, record.second,
LocalDate.now());
}
- synchronized (this) {
+ synchronized (getLockObject()) {
getActiveAdminForCallerLocked(who, DeviceAdminInfo.USES_POLICY_DEVICE_OWNER);
if (policy == null) {
mOwners.clearSystemUpdatePolicy();
@@ -10502,7 +10558,7 @@
@Override
public SystemUpdatePolicy getSystemUpdatePolicy() {
- synchronized (this) {
+ synchronized (getLockObject()) {
SystemUpdatePolicy policy = mOwners.getSystemUpdatePolicy();
if (policy != null && !policy.isValid()) {
Slog.w(LOG_TAG, "Stored system update policy is invalid, return null instead.");
@@ -10535,7 +10591,7 @@
*/
private void updateSystemUpdateFreezePeriodsRecord(boolean saveIfChanged) {
Slog.d(LOG_TAG, "updateSystemUpdateFreezePeriodsRecord");
- synchronized (this) {
+ synchronized (getLockObject()) {
final SystemUpdatePolicy policy = mOwners.getSystemUpdatePolicy();
if (policy == null) {
return;
@@ -10579,7 +10635,7 @@
@Override
public void clearSystemUpdatePolicyFreezePeriodRecord() {
enforceShell("clearSystemUpdatePolicyFreezePeriodRecord");
- synchronized (this) {
+ synchronized (getLockObject()) {
// Print out current record to help diagnosed CTS failures
Slog.i(LOG_TAG, "Clear freeze period record: "
+ mOwners.getSystemUpdateFreezePeriodRecordAsString());
@@ -10597,7 +10653,7 @@
*/
@VisibleForTesting
boolean isCallerDeviceOwner(int callerUid) {
- synchronized (this) {
+ synchronized (getLockObject()) {
if (!mOwners.hasDeviceOwner()) {
return false;
}
@@ -10643,7 +10699,7 @@
final long ident = mInjector.binderClearCallingIdentity();
try {
- synchronized (this) {
+ synchronized (getLockObject()) {
// Broadcast to device owner first if there is one.
if (mOwners.hasDeviceOwner()) {
final UserHandle deviceOwnerUser =
@@ -10663,7 +10719,7 @@
}
// Send broadcasts to corresponding profile owners if any.
for (final int userId : runningUserIds) {
- synchronized (this) {
+ synchronized (getLockObject()) {
final ComponentName profileOwnerPackage =
mOwners.getProfileOwnerComponent(userId);
if (profileOwnerPackage != null) {
@@ -10689,7 +10745,7 @@
public void setPermissionPolicy(ComponentName admin, String callerPackage, int policy)
throws RemoteException {
int userId = UserHandle.getCallingUserId();
- synchronized (this) {
+ synchronized (getLockObject()) {
// Ensure the caller is a DO/PO or a permission grant state delegate.
enforceCanManageScope(admin, callerPackage, DeviceAdminInfo.USES_POLICY_PROFILE_OWNER,
DELEGATION_PERMISSION_GRANT);
@@ -10704,7 +10760,7 @@
@Override
public int getPermissionPolicy(ComponentName admin) throws RemoteException {
int userId = UserHandle.getCallingUserId();
- synchronized (this) {
+ synchronized (getLockObject()) {
DevicePolicyData userPolicy = getUserData(userId);
return userPolicy.mPermissionPolicy;
}
@@ -10714,7 +10770,7 @@
public boolean setPermissionGrantState(ComponentName admin, String callerPackage,
String packageName, String permission, int grantState) throws RemoteException {
UserHandle user = mInjector.binderGetCallingUserHandle();
- synchronized (this) {
+ synchronized (getLockObject()) {
// Ensure the caller is a DO/PO or a permission grant state delegate.
enforceCanManageScope(admin, callerPackage, DeviceAdminInfo.USES_POLICY_PROFILE_OWNER,
DELEGATION_PERMISSION_GRANT);
@@ -10772,7 +10828,7 @@
enforceCanManageScope(admin, callerPackage,
DeviceAdminInfo.USES_POLICY_PROFILE_OWNER, DELEGATION_PERMISSION_GRANT);
}
- synchronized (this) {
+ synchronized (getLockObject()) {
long ident = mInjector.binderClearCallingIdentity();
try {
int granted = mIPackageManager.checkPermission(permission,
@@ -10910,7 +10966,7 @@
}
private int checkDeviceOwnerProvisioningPreCondition(int deviceOwnerUserId) {
- synchronized (this) {
+ synchronized (getLockObject()) {
// hasIncompatibleAccountsOrNonAdb doesn't matter since the caller is not adb.
return checkDeviceOwnerProvisioningPreConditionLocked(/* owner unknown */ null,
deviceOwnerUserId, /* isAdb= */ false,
@@ -10977,7 +11033,7 @@
* Return device owner or profile owner set on a given user.
*/
private @Nullable ComponentName getOwnerComponent(int userId) {
- synchronized (this) {
+ synchronized (getLockObject()) {
if (mOwners.getDeviceOwnerUserId() == userId) {
return mOwners.getDeviceOwnerComponent();
}
@@ -11028,7 +11084,7 @@
@Override
public String getWifiMacAddress(ComponentName admin) {
// Make sure caller has DO.
- synchronized (this) {
+ synchronized (getLockObject()) {
getActiveAdminForCallerLocked(admin, DeviceAdminInfo.USES_POLICY_DEVICE_OWNER);
}
@@ -11068,7 +11124,7 @@
@Override
public boolean isSystemOnlyUser(ComponentName admin) {
- synchronized (this) {
+ synchronized (getLockObject()) {
getActiveAdminForCallerLocked(admin, DeviceAdminInfo.USES_POLICY_DEVICE_OWNER);
}
final int callingUserId = mInjector.userHandleGetCallingUserId();
@@ -11079,7 +11135,7 @@
public void reboot(ComponentName admin) {
Preconditions.checkNotNull(admin);
// Make sure caller has DO.
- synchronized (this) {
+ synchronized (getLockObject()) {
getActiveAdminForCallerLocked(admin, DeviceAdminInfo.USES_POLICY_DEVICE_OWNER);
}
long ident = mInjector.binderClearCallingIdentity();
@@ -11101,7 +11157,7 @@
}
Preconditions.checkNotNull(who, "ComponentName is null");
final int userHandle = mInjector.userHandleGetCallingUserId();
- synchronized (this) {
+ synchronized (getLockObject()) {
ActiveAdmin admin = getActiveAdminForUidLocked(who,
mInjector.binderGetCallingUid());
if (!TextUtils.equals(admin.shortSupportMessage, message)) {
@@ -11117,7 +11173,7 @@
return null;
}
Preconditions.checkNotNull(who, "ComponentName is null");
- synchronized (this) {
+ synchronized (getLockObject()) {
ActiveAdmin admin = getActiveAdminForUidLocked(who,
mInjector.binderGetCallingUid());
return admin.shortSupportMessage;
@@ -11131,7 +11187,7 @@
}
Preconditions.checkNotNull(who, "ComponentName is null");
final int userHandle = mInjector.userHandleGetCallingUserId();
- synchronized (this) {
+ synchronized (getLockObject()) {
ActiveAdmin admin = getActiveAdminForUidLocked(who,
mInjector.binderGetCallingUid());
if (!TextUtils.equals(admin.longSupportMessage, message)) {
@@ -11147,7 +11203,7 @@
return null;
}
Preconditions.checkNotNull(who, "ComponentName is null");
- synchronized (this) {
+ synchronized (getLockObject()) {
ActiveAdmin admin = getActiveAdminForUidLocked(who,
mInjector.binderGetCallingUid());
return admin.longSupportMessage;
@@ -11163,7 +11219,7 @@
if (!isCallerWithSystemUid()) {
throw new SecurityException("Only the system can query support message for user");
}
- synchronized (this) {
+ synchronized (getLockObject()) {
ActiveAdmin admin = getActiveAdminUncheckedLocked(who, userHandle);
if (admin != null) {
return admin.shortSupportMessage;
@@ -11181,7 +11237,7 @@
if (!isCallerWithSystemUid()) {
throw new SecurityException("Only the system can query support message for user");
}
- synchronized (this) {
+ synchronized (getLockObject()) {
ActiveAdmin admin = getActiveAdminUncheckedLocked(who, userHandle);
if (admin != null) {
return admin.longSupportMessage;
@@ -11198,7 +11254,7 @@
Preconditions.checkNotNull(who, "ComponentName is null");
final int userHandle = mInjector.userHandleGetCallingUserId();
enforceManagedProfile(userHandle, "set organization color");
- synchronized (this) {
+ synchronized (getLockObject()) {
ActiveAdmin admin = getActiveAdminForCallerLocked(who,
DeviceAdminInfo.USES_POLICY_PROFILE_OWNER);
admin.organizationColor = color;
@@ -11214,7 +11270,7 @@
enforceFullCrossUsersPermission(userId);
enforceManageUsers();
enforceManagedProfile(userId, "set organization color");
- synchronized (this) {
+ synchronized (getLockObject()) {
ActiveAdmin admin = getProfileOwnerAdminLocked(userId);
admin.organizationColor = color;
saveSettingsLocked(userId);
@@ -11228,7 +11284,7 @@
}
Preconditions.checkNotNull(who, "ComponentName is null");
enforceManagedProfile(mInjector.userHandleGetCallingUserId(), "get organization color");
- synchronized (this) {
+ synchronized (getLockObject()) {
ActiveAdmin admin = getActiveAdminForCallerLocked(who,
DeviceAdminInfo.USES_POLICY_PROFILE_OWNER);
return admin.organizationColor;
@@ -11242,7 +11298,7 @@
}
enforceFullCrossUsersPermission(userHandle);
enforceManagedProfile(userHandle, "get organization color");
- synchronized (this) {
+ synchronized (getLockObject()) {
ActiveAdmin profileOwner = getProfileOwnerAdminLocked(userHandle);
return (profileOwner != null)
? profileOwner.organizationColor
@@ -11258,7 +11314,7 @@
Preconditions.checkNotNull(who, "ComponentName is null");
final int userHandle = mInjector.userHandleGetCallingUserId();
- synchronized (this) {
+ synchronized (getLockObject()) {
ActiveAdmin admin = getActiveAdminForCallerLocked(who,
DeviceAdminInfo.USES_POLICY_PROFILE_OWNER);
if (!TextUtils.equals(admin.organizationName, text)) {
@@ -11276,7 +11332,7 @@
}
Preconditions.checkNotNull(who, "ComponentName is null");
enforceManagedProfile(mInjector.userHandleGetCallingUserId(), "get organization name");
- synchronized(this) {
+ synchronized (getLockObject()) {
ActiveAdmin admin = getActiveAdminForCallerLocked(who,
DeviceAdminInfo.USES_POLICY_PROFILE_OWNER);
return admin.organizationName;
@@ -11289,7 +11345,7 @@
return null;
}
enforceDeviceOwnerOrManageUsers();
- synchronized(this) {
+ synchronized (getLockObject()) {
final ActiveAdmin deviceOwnerAdmin = getDeviceOwnerAdminLocked();
return deviceOwnerAdmin == null ? null : deviceOwnerAdmin.organizationName;
}
@@ -11302,7 +11358,7 @@
}
enforceFullCrossUsersPermission(userHandle);
enforceManagedProfile(userHandle, "get organization name");
- synchronized (this) {
+ synchronized (getLockObject()) {
ActiveAdmin profileOwner = getProfileOwnerAdminLocked(userHandle);
return (profileOwner != null)
? profileOwner.organizationName
@@ -11318,7 +11374,7 @@
if (!mHasFeature) {
return packageNames;
}
- synchronized (this) {
+ synchronized (getLockObject()) {
final ActiveAdmin admin = getActiveAdminForCallerLocked(who,
DeviceAdminInfo.USES_POLICY_PROFILE_OWNER);
final int callingUserId = mInjector.userHandleGetCallingUserId();
@@ -11367,7 +11423,7 @@
if (!mHasFeature) {
return new ArrayList<>();
}
- synchronized (this) {
+ synchronized (getLockObject()) {
final ActiveAdmin admin = getActiveAdminForCallerLocked(who,
DeviceAdminInfo.USES_POLICY_PROFILE_OWNER);
return admin.meteredDisabledPackages == null
@@ -11387,7 +11443,7 @@
throw new SecurityException(
"Only the system can query restricted pkgs for a specific user");
}
- synchronized (this) {
+ synchronized (getLockObject()) {
final ActiveAdmin admin = getActiveAdminUncheckedLocked(who, userId);
if (admin != null && admin.meteredDisabledPackages != null) {
return admin.meteredDisabledPackages.contains(packageName);
@@ -11429,7 +11485,7 @@
final Set<String> affiliationIds = new ArraySet<>(ids);
final int callingUserId = mInjector.userHandleGetCallingUserId();
- synchronized (this) {
+ synchronized (getLockObject()) {
getActiveAdminForCallerLocked(admin, DeviceAdminInfo.USES_POLICY_PROFILE_OWNER);
getUserData(callingUserId).mAffiliationIds = affiliationIds;
saveSettingsLocked(callingUserId);
@@ -11456,7 +11512,7 @@
}
Preconditions.checkNotNull(admin);
- synchronized (this) {
+ synchronized (getLockObject()) {
getActiveAdminForCallerLocked(admin, DeviceAdminInfo.USES_POLICY_PROFILE_OWNER);
return new ArrayList<String>(
getUserData(mInjector.userHandleGetCallingUserId()).mAffiliationIds);
@@ -11469,7 +11525,7 @@
return false;
}
- synchronized (this) {
+ synchronized (getLockObject()) {
return isUserAffiliatedWithDeviceLocked(mInjector.userHandleGetCallingUserId());
}
}
@@ -11530,7 +11586,7 @@
}
Preconditions.checkNotNull(admin);
- synchronized (this) {
+ synchronized (getLockObject()) {
getActiveAdminForCallerLocked(admin, DeviceAdminInfo.USES_POLICY_DEVICE_OWNER);
if (enabled == mInjector.securityLogGetLoggingEnabledProperty()) {
return;
@@ -11551,7 +11607,7 @@
return false;
}
- synchronized (this) {
+ synchronized (getLockObject()) {
if (!isCallerWithSystemUid()) {
Preconditions.checkNotNull(admin);
getActiveAdminForCallerLocked(admin, DeviceAdminInfo.USES_POLICY_DEVICE_OWNER);
@@ -11560,12 +11616,14 @@
}
}
- private synchronized void recordSecurityLogRetrievalTime() {
- final long currentTime = System.currentTimeMillis();
- DevicePolicyData policyData = getUserData(UserHandle.USER_SYSTEM);
- if (currentTime > policyData.mLastSecurityLogRetrievalTime) {
- policyData.mLastSecurityLogRetrievalTime = currentTime;
- saveSettingsLocked(UserHandle.USER_SYSTEM);
+ private void recordSecurityLogRetrievalTime() {
+ synchronized (getLockObject()) {
+ final long currentTime = System.currentTimeMillis();
+ DevicePolicyData policyData = getUserData(UserHandle.USER_SYSTEM);
+ if (currentTime > policyData.mLastSecurityLogRetrievalTime) {
+ policyData.mLastSecurityLogRetrievalTime = currentTime;
+ saveSettingsLocked(UserHandle.USER_SYSTEM);
+ }
}
}
@@ -11646,7 +11704,7 @@
enforceCanManageDeviceAdmin();
final int userId = mInjector.userHandleGetCallingUserId();
Pair<String, Integer> packageUserPair = new Pair<>(packageName, userId);
- synchronized (this) {
+ synchronized (getLockObject()) {
return mPackagesToRemove.contains(packageUserPair);
}
}
@@ -11672,7 +11730,7 @@
}
final Pair<String, Integer> packageUserPair = new Pair<>(packageName, userId);
- synchronized (this) {
+ synchronized (getLockObject()) {
mPackagesToRemove.add(packageUserPair);
}
@@ -11707,7 +11765,7 @@
@Override
public boolean isDeviceProvisioned() {
enforceManageUsers();
- synchronized (this) {
+ synchronized (getLockObject()) {
return getUserDataUnchecked(UserHandle.USER_SYSTEM).mUserSetupComplete;
}
}
@@ -11734,7 +11792,7 @@
private void startUninstallIntent(final String packageName, final int userId) {
final Pair<String, Integer> packageUserPair = new Pair<>(packageName, userId);
- synchronized (this) {
+ synchronized (getLockObject()) {
if (!mPackagesToRemove.contains(packageUserPair)) {
// Do nothing if uninstall was not requested or was already started.
return;
@@ -11769,7 +11827,7 @@
* @param userHandle The user for which this admin has to be removed.
*/
private void removeAdminArtifacts(final ComponentName adminReceiver, final int userHandle) {
- synchronized (this) {
+ synchronized (getLockObject()) {
final ActiveAdmin admin = getActiveAdminUncheckedLocked(adminReceiver, userHandle);
if (admin == null) {
return;
@@ -11799,7 +11857,7 @@
@Override
public void setDeviceProvisioningConfigApplied() {
enforceManageUsers();
- synchronized (this) {
+ synchronized (getLockObject()) {
DevicePolicyData policy = getUserData(UserHandle.USER_SYSTEM);
policy.mDeviceProvisioningConfigApplied = true;
saveSettingsLocked(UserHandle.USER_SYSTEM);
@@ -11809,7 +11867,7 @@
@Override
public boolean isDeviceProvisioningConfigApplied() {
enforceManageUsers();
- synchronized (this) {
+ synchronized (getLockObject()) {
final DevicePolicyData policy = getUserData(UserHandle.USER_SYSTEM);
return policy.mDeviceProvisioningConfigApplied;
}
@@ -11835,7 +11893,7 @@
Settings.Secure.USER_SETUP_COMPLETE, 0, userId) != 0;
DevicePolicyData policy = getUserData(userId);
policy.mUserSetupComplete = isUserCompleted;
- synchronized (this) {
+ synchronized (getLockObject()) {
saveSettingsLocked(userId);
}
}
@@ -11850,7 +11908,7 @@
return;
}
Preconditions.checkNotNull(admin);
- synchronized (this) {
+ synchronized (getLockObject()) {
ActiveAdmin activeAdmin = getActiveAdminForCallerLocked(
admin, DeviceAdminInfo.USES_POLICY_DEVICE_OWNER);
if (!enabled) {
@@ -11879,7 +11937,7 @@
if (!mHasFeature) {
return true;
}
- synchronized (this) {
+ synchronized (getLockObject()) {
try {
getActiveAdminForCallerLocked(admin, DeviceAdminInfo.USES_POLICY_DEVICE_OWNER);
IBackupManager ibm = mInjector.getIBackupManager();
@@ -11898,7 +11956,7 @@
return false;
}
Preconditions.checkNotNull(admin);
- synchronized (this) {
+ synchronized (getLockObject()) {
getActiveAdminForCallerLocked(admin, DeviceAdminInfo.USES_POLICY_DEVICE_OWNER);
}
@@ -11944,18 +12002,20 @@
return success.get();
}
- synchronized private void saveMandatoryBackupTransport(
+ private void saveMandatoryBackupTransport(
ComponentName admin, int callingUid, ComponentName backupTransportComponent) {
- ActiveAdmin activeAdmin =
- getActiveAdminWithPolicyForUidLocked(
- admin,
- DeviceAdminInfo.USES_POLICY_DEVICE_OWNER,
- callingUid);
- if (!Objects.equals(backupTransportComponent,
- activeAdmin.mandatoryBackupTransport)) {
- activeAdmin.mandatoryBackupTransport =
- backupTransportComponent;
- saveSettingsLocked(UserHandle.USER_SYSTEM);
+ synchronized (getLockObject()) {
+ ActiveAdmin activeAdmin =
+ getActiveAdminWithPolicyForUidLocked(
+ admin,
+ DeviceAdminInfo.USES_POLICY_DEVICE_OWNER,
+ callingUid);
+ if (!Objects.equals(backupTransportComponent,
+ activeAdmin.mandatoryBackupTransport)) {
+ activeAdmin.mandatoryBackupTransport =
+ backupTransportComponent;
+ saveSettingsLocked(UserHandle.USER_SYSTEM);
+ }
}
}
@@ -11964,7 +12024,7 @@
if (!mHasFeature) {
return null;
}
- synchronized (this) {
+ synchronized (getLockObject()) {
ActiveAdmin activeAdmin = getDeviceOwnerAdminLocked();
return activeAdmin == null ? null : activeAdmin.mandatoryBackupTransport;
}
@@ -11995,7 +12055,7 @@
}
final String targetPackage;
- synchronized (this) {
+ synchronized (getLockObject()) {
targetPackage = getOwnerPackageNameForUserLocked(targetUserId);
}
@@ -12032,7 +12092,7 @@
}
Preconditions.checkNotNull(admin);
- synchronized (this) {
+ synchronized (getLockObject()) {
getActiveAdminForCallerLocked(admin, DeviceAdminInfo.USES_POLICY_PROFILE_OWNER);
final int callingUserId = mInjector.userHandleGetCallingUserId();
@@ -12106,7 +12166,7 @@
if (accounts.length == 0) {
return false;
}
- synchronized (this) {
+ synchronized (getLockObject()) {
if (owner == null || !isAdminTestOnlyLocked(owner, userId)) {
Log.w(LOG_TAG,
"Non test-only owner can't be installed with existing accounts.");
@@ -12158,50 +12218,54 @@
}
@Override
- public synchronized void setNetworkLoggingEnabled(ComponentName admin, boolean enabled) {
+ public void setNetworkLoggingEnabled(ComponentName admin, boolean enabled) {
if (!mHasFeature) {
return;
}
- Preconditions.checkNotNull(admin);
- getActiveAdminForCallerLocked(admin, DeviceAdminInfo.USES_POLICY_DEVICE_OWNER);
+ synchronized (getLockObject()) {
+ Preconditions.checkNotNull(admin);
+ getActiveAdminForCallerLocked(admin, DeviceAdminInfo.USES_POLICY_DEVICE_OWNER);
- if (enabled == isNetworkLoggingEnabledInternalLocked()) {
- // already in the requested state
- return;
- }
- ActiveAdmin deviceOwner = getDeviceOwnerAdminLocked();
- deviceOwner.isNetworkLoggingEnabled = enabled;
- if (!enabled) {
- deviceOwner.numNetworkLoggingNotifications = 0;
- deviceOwner.lastNetworkLoggingNotificationTimeMs = 0;
- }
- saveSettingsLocked(mInjector.userHandleGetCallingUserId());
+ if (enabled == isNetworkLoggingEnabledInternalLocked()) {
+ // already in the requested state
+ return;
+ }
+ ActiveAdmin deviceOwner = getDeviceOwnerAdminLocked();
+ deviceOwner.isNetworkLoggingEnabled = enabled;
+ if (!enabled) {
+ deviceOwner.numNetworkLoggingNotifications = 0;
+ deviceOwner.lastNetworkLoggingNotificationTimeMs = 0;
+ }
+ saveSettingsLocked(mInjector.userHandleGetCallingUserId());
- setNetworkLoggingActiveInternal(enabled);
+ setNetworkLoggingActiveInternal(enabled);
+ }
}
- private synchronized void setNetworkLoggingActiveInternal(boolean active) {
- final long callingIdentity = mInjector.binderClearCallingIdentity();
- try {
- if (active) {
- mNetworkLogger = new NetworkLogger(this, mInjector.getPackageManagerInternal());
- if (!mNetworkLogger.startNetworkLogging()) {
+ private void setNetworkLoggingActiveInternal(boolean active) {
+ synchronized (getLockObject()) {
+ final long callingIdentity = mInjector.binderClearCallingIdentity();
+ try {
+ if (active) {
+ mNetworkLogger = new NetworkLogger(this, mInjector.getPackageManagerInternal());
+ if (!mNetworkLogger.startNetworkLogging()) {
+ mNetworkLogger = null;
+ Slog.wtf(LOG_TAG, "Network logging could not be started due to the logging"
+ + " service not being available yet.");
+ }
+ maybePauseDeviceWideLoggingLocked();
+ sendNetworkLoggingNotificationLocked();
+ } else {
+ if (mNetworkLogger != null && !mNetworkLogger.stopNetworkLogging()) {
+ Slog.wtf(LOG_TAG, "Network logging could not be stopped due to the logging"
+ + " service not being available yet.");
+ }
mNetworkLogger = null;
- Slog.wtf(LOG_TAG, "Network logging could not be started due to the logging"
- + " service not being available yet.");
+ mInjector.getNotificationManager().cancel(SystemMessage.NOTE_NETWORK_LOGGING);
}
- maybePauseDeviceWideLoggingLocked();
- sendNetworkLoggingNotificationLocked();
- } else {
- if (mNetworkLogger != null && !mNetworkLogger.stopNetworkLogging()) {
- Slog.wtf(LOG_TAG, "Network logging could not be stopped due to the logging"
- + " service not being available yet.");
- }
- mNetworkLogger = null;
- mInjector.getNotificationManager().cancel(SystemMessage.NOTE_NETWORK_LOGGING);
+ } finally {
+ mInjector.binderRestoreCallingIdentity(callingIdentity);
}
- } finally {
- mInjector.binderRestoreCallingIdentity(callingIdentity);
}
}
@@ -12248,7 +12312,7 @@
if (!mHasFeature) {
return false;
}
- synchronized (this) {
+ synchronized (getLockObject()) {
enforceDeviceOwnerOrManageUsers();
return isNetworkLoggingEnabledInternalLocked();
}
@@ -12274,7 +12338,7 @@
Preconditions.checkNotNull(admin);
ensureDeviceOwnerAndAllUsersAffiliated(admin);
- synchronized (this) {
+ synchronized (getLockObject()) {
if (mNetworkLogger == null
|| !isNetworkLoggingEnabledInternalLocked()) {
return null;
@@ -12399,7 +12463,7 @@
if (token == null || token.length < 32) {
throw new IllegalArgumentException("token must be at least 32-byte long");
}
- synchronized (this) {
+ synchronized (getLockObject()) {
final int userHandle = mInjector.userHandleGetCallingUserId();
getActiveAdminForCallerLocked(admin, DeviceAdminInfo.USES_POLICY_PROFILE_OWNER);
@@ -12424,7 +12488,7 @@
if (!mHasFeature) {
return false;
}
- synchronized (this) {
+ synchronized (getLockObject()) {
final int userHandle = mInjector.userHandleGetCallingUserId();
getActiveAdminForCallerLocked(admin, DeviceAdminInfo.USES_POLICY_PROFILE_OWNER);
@@ -12447,7 +12511,7 @@
@Override
public boolean isResetPasswordTokenActive(ComponentName admin) {
- synchronized (this) {
+ synchronized (getLockObject()) {
final int userHandle = mInjector.userHandleGetCallingUserId();
getActiveAdminForCallerLocked(admin, DeviceAdminInfo.USES_POLICY_PROFILE_OWNER);
@@ -12469,7 +12533,7 @@
public boolean resetPasswordWithToken(ComponentName admin, String passwordOrNull, byte[] token,
int flags) {
Preconditions.checkNotNull(token);
- synchronized (this) {
+ synchronized (getLockObject()) {
final int userHandle = mInjector.userHandleGetCallingUserId();
getActiveAdminForCallerLocked(admin, DeviceAdminInfo.USES_POLICY_PROFILE_OWNER);
@@ -12495,7 +12559,7 @@
public StringParceledListSlice getOwnerInstalledCaCerts(@NonNull UserHandle user) {
final int userId = user.getIdentifier();
enforceProfileOwnerOrFullCrossUsersPermission(userId);
- synchronized (this) {
+ synchronized (getLockObject()) {
return new StringParceledListSlice(
new ArrayList<>(getUserData(userId).mOwnerInstalledCaCerts));
}
@@ -12507,7 +12571,7 @@
Preconditions.checkNotNull(admin, "ComponentName is null");
Preconditions.checkNotNull(packageName, "packageName is null");
Preconditions.checkNotNull(callback, "callback is null");
- synchronized (this) {
+ synchronized (getLockObject()) {
getActiveAdminForCallerLocked(admin, DeviceAdminInfo.USES_POLICY_PROFILE_OWNER);
}
final int userId = UserHandle.getCallingUserId();
@@ -12535,13 +12599,13 @@
}
@Override
- public synchronized void setLogoutEnabled(ComponentName admin, boolean enabled) {
+ public void setLogoutEnabled(ComponentName admin, boolean enabled) {
if (!mHasFeature) {
return;
}
Preconditions.checkNotNull(admin);
- synchronized (this) {
+ synchronized (getLockObject()) {
ActiveAdmin deviceOwner =
getActiveAdminForCallerLocked(admin, DeviceAdminInfo.USES_POLICY_DEVICE_OWNER);
@@ -12559,7 +12623,7 @@
if (!mHasFeature) {
return false;
}
- synchronized (this) {
+ synchronized (getLockObject()) {
ActiveAdmin deviceOwner = getDeviceOwnerAdminLocked();
return (deviceOwner != null) && deviceOwner.isLogoutEnabled;
}
@@ -12607,7 +12671,7 @@
final long id = mInjector.binderClearCallingIdentity();
try {
- synchronized (this) {
+ synchronized (getLockObject()) {
/*
* We must ensure the whole process is atomic to prevent the device from ending up
* in an invalid state (e.g. no active admin). This could happen if the device
@@ -12713,7 +12777,7 @@
final String startUserSessionMessageString =
startUserSessionMessage != null ? startUserSessionMessage.toString() : null;
- synchronized (this) {
+ synchronized (getLockObject()) {
final ActiveAdmin deviceOwner =
getActiveAdminForCallerLocked(admin, DeviceAdminInfo.USES_POLICY_DEVICE_OWNER);
@@ -12738,7 +12802,7 @@
final String endUserSessionMessageString =
endUserSessionMessage != null ? endUserSessionMessage.toString() : null;
- synchronized (this) {
+ synchronized (getLockObject()) {
final ActiveAdmin deviceOwner =
getActiveAdminForCallerLocked(admin, DeviceAdminInfo.USES_POLICY_DEVICE_OWNER);
@@ -12760,7 +12824,7 @@
}
Preconditions.checkNotNull(admin);
- synchronized (this) {
+ synchronized (getLockObject()) {
final ActiveAdmin deviceOwner =
getActiveAdminForCallerLocked(admin, DeviceAdminInfo.USES_POLICY_DEVICE_OWNER);
return deviceOwner.startUserSessionMessage;
@@ -12774,7 +12838,7 @@
}
Preconditions.checkNotNull(admin);
- synchronized (this) {
+ synchronized (getLockObject()) {
final ActiveAdmin deviceOwner =
getActiveAdminForCallerLocked(admin, DeviceAdminInfo.USES_POLICY_DEVICE_OWNER);
return deviceOwner.endUserSessionMessage;
@@ -12788,7 +12852,7 @@
@Override
@Nullable
public PersistableBundle getTransferOwnershipBundle() {
- synchronized (this) {
+ synchronized (getLockObject()) {
final int callingUserId = mInjector.userHandleGetCallingUserId();
getActiveAdminForCallerLocked(null, DeviceAdminInfo.USES_POLICY_PROFILE_OWNER);
final File bundleFile = new File(
@@ -12817,7 +12881,7 @@
}
Preconditions.checkNotNull(who, "ComponentName is null in addOverrideApn");
Preconditions.checkNotNull(apnSetting, "ApnSetting is null in addOverrideApn");
- synchronized (this) {
+ synchronized (getLockObject()) {
getActiveAdminForCallerLocked(who, DeviceAdminInfo.USES_POLICY_DEVICE_OWNER);
}
@@ -12848,7 +12912,7 @@
}
Preconditions.checkNotNull(who, "ComponentName is null in updateOverrideApn");
Preconditions.checkNotNull(apnSetting, "ApnSetting is null in updateOverrideApn");
- synchronized (this) {
+ synchronized (getLockObject()) {
getActiveAdminForCallerLocked(who, DeviceAdminInfo.USES_POLICY_DEVICE_OWNER);
}
@@ -12871,7 +12935,7 @@
return false;
}
Preconditions.checkNotNull(who, "ComponentName is null in removeOverrideApn");
- synchronized (this) {
+ synchronized (getLockObject()) {
getActiveAdminForCallerLocked(who, DeviceAdminInfo.USES_POLICY_DEVICE_OWNER);
}
@@ -12899,7 +12963,7 @@
return Collections.emptyList();
}
Preconditions.checkNotNull(who, "ComponentName is null in getOverrideApns");
- synchronized (this) {
+ synchronized (getLockObject()) {
getActiveAdminForCallerLocked(who, DeviceAdminInfo.USES_POLICY_DEVICE_OWNER);
}
@@ -12937,7 +13001,7 @@
return;
}
Preconditions.checkNotNull(who, "ComponentName is null in setOverrideApnEnabled");
- synchronized (this) {
+ synchronized (getLockObject()) {
getActiveAdminForCallerLocked(who, DeviceAdminInfo.USES_POLICY_DEVICE_OWNER);
}
@@ -12962,7 +13026,7 @@
return false;
}
Preconditions.checkNotNull(who, "ComponentName is null in isOverrideApnEnabled");
- synchronized (this) {
+ synchronized (getLockObject()) {
getActiveAdminForCallerLocked(who, DeviceAdminInfo.USES_POLICY_DEVICE_OWNER);
}
diff --git a/services/robotests/src/com/android/server/location/GnssSatelliteBlacklistHelperTest.java b/services/robotests/src/com/android/server/location/GnssSatelliteBlacklistHelperTest.java
new file mode 100644
index 0000000..d6f5446
--- /dev/null
+++ b/services/robotests/src/com/android/server/location/GnssSatelliteBlacklistHelperTest.java
@@ -0,0 +1,130 @@
+package com.android.server.location;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import static org.mockito.Matchers.any;
+import static org.mockito.Mockito.never;
+import static org.mockito.Mockito.verify;
+
+import android.content.ContentResolver;
+import android.content.Context;
+import android.database.ContentObserver;
+import android.os.Looper;
+import android.platform.test.annotations.Presubmit;
+import android.provider.Settings;
+
+import com.android.server.testing.FrameworkRobolectricTestRunner;
+import com.android.server.testing.SystemLoaderPackages;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.ArgumentCaptor;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+import org.robolectric.RuntimeEnvironment;
+import org.robolectric.Shadows;
+import org.robolectric.annotation.Config;
+
+import java.util.Collection;
+import java.util.List;
+
+/**
+ * Unit tests for {@link GnssSatelliteBlacklistHelper}.
+ */
+@RunWith(FrameworkRobolectricTestRunner.class)
+@Config(
+ manifest = Config.NONE,
+ shadows = {
+ },
+ sdk = 27
+)
+@SystemLoaderPackages({"com.android.server.location"})
+@Presubmit
+public class GnssSatelliteBlacklistHelperTest {
+
+ private Context mContext;
+ private ContentResolver mContentResolver;
+ @Mock
+ private GnssSatelliteBlacklistHelper.GnssSatelliteBlacklistCallback mCallback;
+
+ @Before
+ public void setUp() {
+ MockitoAnnotations.initMocks(this);
+ mContext = RuntimeEnvironment.application;
+ mContentResolver = mContext.getContentResolver();
+ new GnssSatelliteBlacklistHelper(mContext, Looper.myLooper(), mCallback);
+ }
+
+ @Test
+ public void blacklistOf2Satellites_callbackIsCalled() {
+ String blacklist = "3,0,5,24";
+ updateBlacklistAndVerifyCallbackIsCalled(blacklist);
+ }
+
+ @Test
+ public void blacklistWithSpaces_callbackIsCalled() {
+ String blacklist = "3, 11";
+ updateBlacklistAndVerifyCallbackIsCalled(blacklist);
+ }
+
+ @Test
+ public void emptyBlacklist_callbackIsCalled() {
+ String blacklist = "";
+ updateBlacklistAndVerifyCallbackIsCalled(blacklist);
+ }
+
+ @Test
+ public void blacklistWithOddNumberOfValues_callbackIsNotCalled() {
+ String blacklist = "3,0,5";
+ updateBlacklistAndNotifyContentObserver(blacklist);
+ verify(mCallback, never()).onUpdateSatelliteBlacklist(any(int[].class), any(int[].class));
+ }
+
+ @Test
+ public void blacklistWithNegativeValue_callbackIsNotCalled() {
+ String blacklist = "3,-11";
+ updateBlacklistAndNotifyContentObserver(blacklist);
+ verify(mCallback, never()).onUpdateSatelliteBlacklist(any(int[].class), any(int[].class));
+ }
+
+ @Test
+ public void blacklistWithNonDigitCharacter_callbackIsNotCalled() {
+ String blacklist = "3,1a,5,11";
+ updateBlacklistAndNotifyContentObserver(blacklist);
+ verify(mCallback, never()).onUpdateSatelliteBlacklist(any(int[].class), any(int[].class));
+ }
+
+ private void updateBlacklistAndNotifyContentObserver(String blacklist) {
+ Settings.Global.putString(mContentResolver,
+ Settings.Global.GNSS_SATELLITE_BLACKLIST, blacklist);
+ notifyContentObserverFor(Settings.Global.GNSS_SATELLITE_BLACKLIST);
+ }
+
+ private void updateBlacklistAndVerifyCallbackIsCalled(String blacklist) {
+ updateBlacklistAndNotifyContentObserver(blacklist);
+
+ ArgumentCaptor<int[]> constellationsCaptor = ArgumentCaptor.forClass(int[].class);
+ ArgumentCaptor<int[]> svIdsCaptor = ArgumentCaptor.forClass(int[].class);
+ verify(mCallback).onUpdateSatelliteBlacklist(constellationsCaptor.capture(),
+ svIdsCaptor.capture());
+
+ int[] constellations = constellationsCaptor.getValue();
+ int[] svIds = svIdsCaptor.getValue();
+ List<Integer> values = GnssSatelliteBlacklistHelper.parseSatelliteBlacklist(blacklist);
+ assertThat(values.size()).isEqualTo(constellations.length * 2);
+ assertThat(svIds.length).isEqualTo(constellations.length);
+ for (int i = 0; i < constellations.length; i++) {
+ assertThat(constellations[i]).isEqualTo(values.get(i * 2));
+ assertThat(svIds[i]).isEqualTo(values.get(i * 2 + 1));
+ }
+ }
+
+ private static void notifyContentObserverFor(String globalSetting) {
+ Collection<ContentObserver> contentObservers =
+ Shadows.shadowOf(RuntimeEnvironment.application.getContentResolver())
+ .getContentObservers(Settings.Global.getUriFor(globalSetting));
+ assertThat(contentObservers).isNotEmpty();
+ contentObservers.iterator().next().onChange(false /* selfChange */);
+ }
+}
diff --git a/services/robotests/src/com/android/server/location/NtpTimeHelperTest.java b/services/robotests/src/com/android/server/location/NtpTimeHelperTest.java
new file mode 100644
index 0000000..a68b579
--- /dev/null
+++ b/services/robotests/src/com/android/server/location/NtpTimeHelperTest.java
@@ -0,0 +1,100 @@
+package com.android.server.location;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import static org.mockito.Mockito.doReturn;
+
+import android.os.Looper;
+import android.platform.test.annotations.Presubmit;
+import android.util.NtpTrustedTime;
+
+import com.android.server.location.NtpTimeHelper.InjectNtpTimeCallback;
+import com.android.server.testing.FrameworkRobolectricTestRunner;
+import com.android.server.testing.SystemLoaderPackages;
+
+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 org.robolectric.shadows.ShadowLooper;
+import org.robolectric.shadows.ShadowSystemClock;
+
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.TimeUnit;
+
+/**
+ * Unit tests for {@link NtpTimeHelper}.
+ */
+@RunWith(FrameworkRobolectricTestRunner.class)
+@Config(
+ manifest = Config.NONE,
+ sdk = 27
+)
+@SystemLoaderPackages({"com.android.server.location"})
+@Presubmit
+public class NtpTimeHelperTest {
+
+ private static final long MOCK_NTP_TIME = 1519930775453L;
+ @Mock
+ private NtpTrustedTime mMockNtpTrustedTime;
+ private NtpTimeHelper mNtpTimeHelper;
+ private CountDownLatch mCountDownLatch;
+
+ @Before
+ public void setUp() throws Exception {
+ MockitoAnnotations.initMocks(this);
+ mCountDownLatch = new CountDownLatch(1);
+ InjectNtpTimeCallback callback =
+ (time, timeReference, uncertainty) -> {
+ assertThat(time).isEqualTo(MOCK_NTP_TIME);
+ mCountDownLatch.countDown();
+ };
+ mNtpTimeHelper = new NtpTimeHelper(RuntimeEnvironment.application,
+ Looper.myLooper(),
+ callback, mMockNtpTrustedTime);
+ }
+
+ @Test
+ public void handleInjectNtpTime_cachedAgeLow_injectTime() throws InterruptedException {
+ doReturn(NtpTimeHelper.NTP_INTERVAL - 1).when(mMockNtpTrustedTime).getCacheAge();
+ doReturn(MOCK_NTP_TIME).when(mMockNtpTrustedTime).getCachedNtpTime();
+
+ mNtpTimeHelper.retrieveAndInjectNtpTime();
+
+ waitForTasksToBePostedOnHandlerAndRunThem();
+ assertThat(mCountDownLatch.await(2, TimeUnit.SECONDS)).isTrue();
+ }
+
+ @Test
+ public void handleInjectNtpTime_injectTimeFailed_injectTimeDelayed()
+ throws InterruptedException {
+ doReturn(NtpTimeHelper.NTP_INTERVAL + 1).when(mMockNtpTrustedTime).getCacheAge();
+ doReturn(false).when(mMockNtpTrustedTime).forceRefresh();
+
+ mNtpTimeHelper.retrieveAndInjectNtpTime();
+ waitForTasksToBePostedOnHandlerAndRunThem();
+ assertThat(mCountDownLatch.await(2, TimeUnit.SECONDS)).isFalse();
+
+ doReturn(true).when(mMockNtpTrustedTime).forceRefresh();
+ doReturn(1L).when(mMockNtpTrustedTime).getCacheAge();
+ doReturn(MOCK_NTP_TIME).when(mMockNtpTrustedTime).getCachedNtpTime();
+ ShadowSystemClock.sleep(NtpTimeHelper.RETRY_INTERVAL);
+
+ waitForTasksToBePostedOnHandlerAndRunThem();
+ assertThat(mCountDownLatch.await(2, TimeUnit.SECONDS)).isTrue();
+ }
+
+ /**
+ * Since a thread is created in {@link NtpTimeHelper#retrieveAndInjectNtpTime} and the task to
+ * be verified is posted in the thread, we have to wait for the task to be posted and then it
+ * can be run.
+ */
+ private void waitForTasksToBePostedOnHandlerAndRunThem() throws InterruptedException {
+ mCountDownLatch.await(1, TimeUnit.SECONDS);
+ ShadowLooper.runUiThreadTasks();
+ }
+}
+
diff --git a/services/tests/servicestests/Android.mk b/services/tests/servicestests/Android.mk
index cdb339a..a85f21c 100644
--- a/services/tests/servicestests/Android.mk
+++ b/services/tests/servicestests/Android.mk
@@ -29,6 +29,7 @@
truth-prebuilt \
testables \
testng \
+ ub-uiautomator\
platformprotosnano
LOCAL_AIDL_INCLUDES := $(LOCAL_PATH)/aidl
@@ -69,8 +70,6 @@
LOCAL_JACK_FLAGS := --multi-dex native
LOCAL_DX_FLAGS := --multi-dex
-LOCAL_STATIC_JAVA_LIBRARIES += ub-uiautomator
-
LOCAL_PROGUARD_ENABLED := disabled
include $(BUILD_PACKAGE)
diff --git a/services/tests/servicestests/AndroidManifest.xml b/services/tests/servicestests/AndroidManifest.xml
index ce98d65..22bec44 100644
--- a/services/tests/servicestests/AndroidManifest.xml
+++ b/services/tests/servicestests/AndroidManifest.xml
@@ -63,6 +63,7 @@
<uses-permission android:name="android.permission.WATCH_APPOPS" />
<uses-permission android:name="android.permission.FOREGROUND_SERVICE"/>
<uses-permission android:name="android.permission.SUSPEND_APPS"/>
+ <uses-permission android:name="android.permission.CONTROL_KEYGUARD"/>
<!-- Uses API introduced in O (26) -->
<uses-sdk android:minSdkVersion="1"
@@ -145,6 +146,15 @@
<activity android:name="com.android.server.pm.ShortcutTestActivity"
android:enabled="true" android:exported="true" />
+ <activity android:name="com.android.server.pm.SuspendedDetailsActivity"
+ android:enabled="true"
+ android:permission="android.permission.SEND_SHOW_SUSPENDED_APP_DETAILS">
+ <intent-filter>
+ <action android:name="android.intent.action.SHOW_SUSPENDED_APP_DETAILS" />
+ <category android:name="android.intent.category.DEFAULT" />
+ </intent-filter>
+ </activity>
+
<activity android:name="com.android.server.accounts.AccountAuthenticatorDummyActivity" />
<activity-alias android:name="a.ShortcutEnabled"
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 194f4ae..a14b950 100644
--- a/services/tests/servicestests/src/com/android/server/am/ActivityStartInterceptorTest.java
+++ b/services/tests/servicestests/src/com/android/server/am/ActivityStartInterceptorTest.java
@@ -17,6 +17,9 @@
package com.android.server.am;
import static android.content.pm.ApplicationInfo.FLAG_SUSPENDED;
+
+import static com.android.server.pm.PackageManagerService.PLATFORM_PACKAGE_NAME;
+
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
@@ -30,15 +33,19 @@
import android.content.Intent;
import android.content.pm.ActivityInfo;
import android.content.pm.ApplicationInfo;
+import android.content.pm.PackageManagerInternal;
import android.content.pm.UserInfo;
import android.os.UserHandle;
import android.os.UserManager;
import android.support.test.filters.SmallTest;
+import android.testing.DexmakerShareClassLoaderRule;
import com.android.internal.app.UnlaunchableAppActivity;
import com.android.server.LocalServices;
+import com.android.server.pm.PackageManagerService;
import org.junit.Before;
+import org.junit.Rule;
import org.junit.Test;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
@@ -64,6 +71,10 @@
0 /* flags */);
private static final String TEST_PACKAGE_NAME = "com.test.package";
+ @Rule
+ public final DexmakerShareClassLoaderRule mDexmakerShareClassLoaderRule =
+ new DexmakerShareClassLoaderRule();
+
@Mock
private Context mContext;
@Mock
@@ -73,20 +84,21 @@
@Mock
private DevicePolicyManagerInternal mDevicePolicyManager;
@Mock
+ private PackageManagerInternal mPackageManagerInternal;
+ @Mock
private UserManager mUserManager;
@Mock
private UserController mUserController;
@Mock
private KeyguardManager mKeyguardManager;
+ @Mock
+ private PackageManagerService mPackageManager;
private ActivityStartInterceptor mInterceptor;
private ActivityInfo mAInfo = new ActivityInfo();
@Before
public void setUp() {
- // This property is used to allow mocking of package private classes with mockito
- System.setProperty("dexmaker.share_classloader", "true");
-
MockitoAnnotations.initMocks(this);
mInterceptor = new ActivityStartInterceptor(mService, mSupervisor, mContext,
mUserController);
@@ -100,6 +112,7 @@
when(mDevicePolicyManager
.createShowAdminSupportIntent(TEST_USER_ID, true))
.thenReturn(ADMIN_SUPPORT_INTENT);
+ when(mService.getPackageManagerInternalLocked()).thenReturn(mPackageManagerInternal);
// Mock UserManager
when(mContext.getSystemService(Context.USER_SERVICE)).thenReturn(mUserManager);
@@ -111,16 +124,24 @@
nullable(CharSequence.class), nullable(CharSequence.class), eq(TEST_USER_ID))).
thenReturn(CONFIRM_CREDENTIALS_INTENT);
+ // Mock PackageManager
+ when(mService.getPackageManager()).thenReturn(mPackageManager);
+ when(mPackageManager.getHarmfulAppWarning(TEST_PACKAGE_NAME, TEST_USER_ID))
+ .thenReturn(null);
+
// Initialise activity info
- mAInfo.packageName = TEST_PACKAGE_NAME;
mAInfo.applicationInfo = new ApplicationInfo();
+ mAInfo.packageName = mAInfo.applicationInfo.packageName = TEST_PACKAGE_NAME;
}
@Test
- public void testSuspendedPackage() {
+ public void testSuspendedByAdminPackage() {
// GIVEN the package we're about to launch is currently suspended
mAInfo.applicationInfo.flags = FLAG_SUSPENDED;
+ when(mPackageManagerInternal.getSuspendingPackage(TEST_PACKAGE_NAME, TEST_USER_ID))
+ .thenReturn(PLATFORM_PACKAGE_NAME);
+
// THEN calling intercept returns true
assertTrue(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 a533447..741901d 100644
--- a/services/tests/servicestests/src/com/android/server/am/ActivityTestsBase.java
+++ b/services/tests/servicestests/src/com/android/server/am/ActivityTestsBase.java
@@ -31,6 +31,8 @@
import static org.mockito.Mockito.spy;
import com.android.server.wm.DisplayWindowController;
+
+import org.junit.Rule;
import org.mockito.invocation.InvocationOnMock;
import android.app.IApplicationThread;
@@ -47,6 +49,8 @@
import android.os.Looper;
import android.service.voice.IVoiceInteractionSession;
import android.support.test.InstrumentationRegistry;
+import android.testing.DexmakerShareClassLoaderRule;
+
import com.android.server.AttributeCache;
import com.android.server.wm.AppWindowContainerController;
import com.android.server.wm.PinnedStackWindowController;
@@ -64,6 +68,10 @@
public class ActivityTestsBase {
private static boolean sOneTimeSetupDone = false;
+ @Rule
+ public final DexmakerShareClassLoaderRule mDexmakerShareClassLoaderRule =
+ new DexmakerShareClassLoaderRule();
+
private final Context mContext = InstrumentationRegistry.getContext();
private HandlerThread mHandlerThread;
@@ -77,9 +85,6 @@
public void setUp() throws Exception {
if (!sOneTimeSetupDone) {
sOneTimeSetupDone = true;
-
- // Allows to mock package local classes and methods
- System.setProperty("dexmaker.share_classloader", "true");
MockitoAnnotations.initMocks(this);
}
mHandlerThread = new HandlerThread("ActivityTestsBaseThread");
diff --git a/services/tests/servicestests/src/com/android/server/am/LockTaskControllerTest.java b/services/tests/servicestests/src/com/android/server/am/LockTaskControllerTest.java
index 1cbb399..f46d712 100644
--- a/services/tests/servicestests/src/com/android/server/am/LockTaskControllerTest.java
+++ b/services/tests/servicestests/src/com/android/server/am/LockTaskControllerTest.java
@@ -55,6 +55,7 @@
import android.support.test.InstrumentationRegistry;
import android.support.test.filters.SmallTest;
import android.telecom.TelecomManager;
+import android.testing.DexmakerShareClassLoaderRule;
import android.util.Pair;
import com.android.internal.statusbar.IStatusBarService;
@@ -65,6 +66,7 @@
import org.junit.After;
import org.junit.Before;
+import org.junit.Rule;
import org.junit.Test;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
@@ -85,6 +87,10 @@
private static final int TEST_USER_ID = 123;
private static final int TEST_UID = 10467;
+ @Rule
+ public final DexmakerShareClassLoaderRule mDexmakerShareClassLoaderRule =
+ new DexmakerShareClassLoaderRule();
+
@Mock private ActivityStackSupervisor mSupervisor;
@Mock private IDevicePolicyManager mDevicePolicyManager;
@Mock private IStatusBarService mStatusBarService;
@@ -100,9 +106,6 @@
@Before
public void setUp() throws Exception {
- // This property is used to allow mocking of package private classes with mockito
- System.setProperty("dexmaker.share_classloader", "true");
-
MockitoAnnotations.initMocks(this);
mContext = InstrumentationRegistry.getTargetContext();
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 6290ff1..edc6509 100644
--- a/services/tests/servicestests/src/com/android/server/am/RecentTasksTest.java
+++ b/services/tests/servicestests/src/com/android/server/am/RecentTasksTest.java
@@ -650,6 +650,8 @@
assertSecurityException(expectCallable, () -> mService.startRecentsActivity(null, null,
null));
assertSecurityException(expectCallable, () -> mService.cancelRecentsAnimation(true));
+ assertSecurityException(expectCallable, () -> mService.stopAppSwitches());
+ assertSecurityException(expectCallable, () -> mService.resumeAppSwitches());
}
private void testGetTasksApis(boolean expectCallable) {
diff --git a/services/tests/servicestests/src/com/android/server/am/UserControllerTest.java b/services/tests/servicestests/src/com/android/server/am/UserControllerTest.java
index 3c10b03..cc4f519 100644
--- a/services/tests/servicestests/src/com/android/server/am/UserControllerTest.java
+++ b/services/tests/servicestests/src/com/android/server/am/UserControllerTest.java
@@ -49,6 +49,7 @@
import java.util.Set;
import static android.content.pm.PackageManager.PERMISSION_GRANTED;
+import static android.testing.DexmakerShareClassLoaderRule.runWithDexmakerShareClassLoader;
import static com.android.server.am.UserController.CONTINUE_USER_SWITCH_MSG;
import static com.android.server.am.UserController.REPORT_LOCKED_BOOT_COMPLETE_MSG;
import static com.android.server.am.UserController.REPORT_USER_SWITCH_COMPLETE_MSG;
@@ -102,13 +103,15 @@
@Override
public void setUp() throws Exception {
super.setUp();
- mInjector = Mockito.spy(new TestInjector(getContext()));
- doNothing().when(mInjector).clearAllLockedTasks(anyString());
- doNothing().when(mInjector).startHomeActivity(anyInt(), anyString());
- doReturn(false).when(mInjector).stackSupervisorSwitchUser(anyInt(), any());
- doNothing().when(mInjector).stackSupervisorResumeFocusedStackTopActivity();
- mUserController = new UserController(mInjector);
- setUpUser(TEST_USER_ID, 0);
+ runWithDexmakerShareClassLoader(() -> {
+ mInjector = Mockito.spy(new TestInjector(getContext()));
+ doNothing().when(mInjector).clearAllLockedTasks(anyString());
+ doNothing().when(mInjector).startHomeActivity(anyInt(), anyString());
+ doReturn(false).when(mInjector).stackSupervisorSwitchUser(anyInt(), any());
+ doNothing().when(mInjector).stackSupervisorResumeFocusedStackTopActivity();
+ mUserController = new UserController(mInjector);
+ setUpUser(TEST_USER_ID, 0);
+ });
}
@Override
diff --git a/services/tests/servicestests/src/com/android/server/locksettings/recoverablekeystore/KeySyncTaskTest.java b/services/tests/servicestests/src/com/android/server/locksettings/recoverablekeystore/KeySyncTaskTest.java
index 5a7dfa2..0e5b7b3 100644
--- a/services/tests/servicestests/src/com/android/server/locksettings/recoverablekeystore/KeySyncTaskTest.java
+++ b/services/tests/servicestests/src/com/android/server/locksettings/recoverablekeystore/KeySyncTaskTest.java
@@ -17,11 +17,9 @@
package com.android.server.locksettings.recoverablekeystore;
import static android.security.keystore.recovery.KeyChainProtectionParams.TYPE_LOCKSCREEN;
-
import static android.security.keystore.recovery.KeyChainProtectionParams.UI_FORMAT_PASSWORD;
import static android.security.keystore.recovery.KeyChainProtectionParams.UI_FORMAT_PATTERN;
import static android.security.keystore.recovery.KeyChainProtectionParams.UI_FORMAT_PIN;
-
import static com.android.internal.widget.LockPatternUtils.CREDENTIAL_TYPE_PASSWORD;
import static com.android.internal.widget.LockPatternUtils.CREDENTIAL_TYPE_PATTERN;
diff --git a/services/tests/servicestests/src/com/android/server/locksettings/recoverablekeystore/RecoverableKeyStoreManagerTest.java b/services/tests/servicestests/src/com/android/server/locksettings/recoverablekeystore/RecoverableKeyStoreManagerTest.java
index 9376bbb..db910f2 100644
--- a/services/tests/servicestests/src/com/android/server/locksettings/recoverablekeystore/RecoverableKeyStoreManagerTest.java
+++ b/services/tests/servicestests/src/com/android/server/locksettings/recoverablekeystore/RecoverableKeyStoreManagerTest.java
@@ -223,7 +223,6 @@
assertThat(mRecoverableKeyStoreDb.getKey(uid, TEST_ALIAS)).isNotNull();
assertThat(mRecoverableKeyStoreDb.getShouldCreateSnapshot(userId, uid)).isTrue();
- // TODO(76083050) Test the grant mechanism for the keys.
}
@Test
diff --git a/services/tests/servicestests/src/com/android/server/pm/BaseShortcutManagerTest.java b/services/tests/servicestests/src/com/android/server/pm/BaseShortcutManagerTest.java
index 1974750..ee83b62 100644
--- a/services/tests/servicestests/src/com/android/server/pm/BaseShortcutManagerTest.java
+++ b/services/tests/servicestests/src/com/android/server/pm/BaseShortcutManagerTest.java
@@ -92,6 +92,8 @@
import org.junit.Assert;
import org.mockito.ArgumentCaptor;
+import org.mockito.invocation.InvocationOnMock;
+import org.mockito.stubbing.Answer;
import java.io.BufferedReader;
import java.io.ByteArrayOutputStream;
@@ -111,6 +113,7 @@
import java.util.function.BiFunction;
import java.util.function.BiPredicate;
import java.util.function.Consumer;
+import java.util.function.Function;
public abstract class BaseShortcutManagerTest extends InstrumentationTestCase {
protected static final String TAG = "ShortcutManagerTest";
@@ -834,6 +837,8 @@
+ targetUserId);
});
+ when(mMockUserManager.getUserInfo(anyInt())).thenAnswer(new AnswerWithSystemCheck<>(
+ inv -> mUserInfos.get((Integer) inv.getArguments()[0])));
when(mMockActivityManagerInternal.getUidProcessState(anyInt())).thenReturn(
ActivityManager.PROCESS_STATE_CACHED_EMPTY);
@@ -863,6 +868,24 @@
}
}
+ /**
+ * Returns a boolean but also checks if the current UID is SYSTEM_UID.
+ */
+ protected class AnswerWithSystemCheck<T> implements Answer<T> {
+ private final Function<InvocationOnMock, T> mChecker;
+
+ public AnswerWithSystemCheck(Function<InvocationOnMock, T> checker) {
+ mChecker = checker;
+ }
+
+ @Override
+ public T answer(InvocationOnMock invocation) throws Throwable {
+ assertEquals("Must be called on SYSTEM UID.",
+ Process.SYSTEM_UID, mInjectedCallingUid);
+ return mChecker.apply(invocation);
+ }
+ }
+
private static boolean b(Boolean value) {
return (value != null && value);
}
@@ -1014,7 +1037,7 @@
pi.applicationInfo.flags = ApplicationInfo.FLAG_INSTALLED
| ApplicationInfo.FLAG_ALLOW_BACKUP;
pi.versionCode = version;
- pi.applicationInfo.versionCode = version;
+ pi.applicationInfo.setVersionCode(version);
pi.signatures = null;
pi.signingCertificateHistory = new Signature[][] {genSignatures(signatures)};
@@ -1032,7 +1055,7 @@
protected void updatePackageVersion(String packageName, int increment) {
updatePackageInfo(packageName, pi -> {
pi.versionCode += increment;
- pi.applicationInfo.versionCode += increment;
+ pi.applicationInfo.setVersionCode(pi.applicationInfo.longVersionCode + increment);
});
}
diff --git a/services/tests/servicestests/src/com/android/server/pm/PackageManagerSettingsTests.java b/services/tests/servicestests/src/com/android/server/pm/PackageManagerSettingsTests.java
index ebb4248..97ff94f 100644
--- a/services/tests/servicestests/src/com/android/server/pm/PackageManagerSettingsTests.java
+++ b/services/tests/servicestests/src/com/android/server/pm/PackageManagerSettingsTests.java
@@ -199,13 +199,13 @@
PACKAGE_NAME_1, 1L, 0.01, true, "appString1");
final PersistableBundle launcherExtras1 = getPersistableBundle(
PACKAGE_NAME_1, 10L, 0.1, false, "launcherString1");
- ps1.setSuspended(true, "suspendingPackage1", appExtras1, launcherExtras1, 0);
+ ps1.setSuspended(true, "suspendingPackage1", "dialogMsg1", appExtras1, launcherExtras1, 0);
settingsUnderTest.mPackages.put(PACKAGE_NAME_1, ps1);
- ps2.setSuspended(true, "suspendingPackage2", null, null, 0);
+ ps2.setSuspended(true, "suspendingPackage2", "dialogMsg2", null, null, 0);
settingsUnderTest.mPackages.put(PACKAGE_NAME_2, ps2);
- ps3.setSuspended(false, "irrelevant", null, null, 0);
+ ps3.setSuspended(false, "irrelevant", "irrevelant2", null, null, 0);
settingsUnderTest.mPackages.put(PACKAGE_NAME_3, ps3);
settingsUnderTest.writePackageRestrictionsLPr(0);
@@ -220,6 +220,7 @@
readUserState(0);
assertThat(readPus1.suspended, is(true));
assertThat(readPus1.suspendingPackage, equalTo("suspendingPackage1"));
+ assertThat(readPus1.dialogMessage, equalTo("dialogMsg1"));
assertThat(BaseBundle.kindofEquals(readPus1.suspendedAppExtras, appExtras1), is(true));
assertThat(BaseBundle.kindofEquals(readPus1.suspendedLauncherExtras, launcherExtras1),
is(true));
@@ -228,12 +229,17 @@
readUserState(0);
assertThat(readPus2.suspended, is(true));
assertThat(readPus2.suspendingPackage, equalTo("suspendingPackage2"));
+ assertThat(readPus2.dialogMessage, equalTo("dialogMsg2"));
assertThat(readPus2.suspendedAppExtras, is(nullValue()));
assertThat(readPus2.suspendedLauncherExtras, is(nullValue()));
final PackageUserState readPus3 = settingsUnderTest.mPackages.get(PACKAGE_NAME_3).
readUserState(0);
assertThat(readPus3.suspended, is(false));
+ assertThat(readPus3.suspendingPackage, is(nullValue()));
+ assertThat(readPus3.dialogMessage, is(nullValue()));
+ assertThat(readPus3.suspendedAppExtras, is(nullValue()));
+ assertThat(readPus3.suspendedLauncherExtras, is(nullValue()));
}
@Test
diff --git a/services/tests/servicestests/src/com/android/server/pm/PackageUserStateTest.java b/services/tests/servicestests/src/com/android/server/pm/PackageUserStateTest.java
index 4e1418c..2a4ea8c 100644
--- a/services/tests/servicestests/src/com/android/server/pm/PackageUserStateTest.java
+++ b/services/tests/servicestests/src/com/android/server/pm/PackageUserStateTest.java
@@ -184,30 +184,40 @@
launcherExtras2.putString("name", "launcherExtras2");
final String suspendingPackage1 = "package1";
final String suspendingPackage2 = "package2";
+ final String dialogMessage1 = "dialogMessage1";
+ final String dialogMessage2 = "dialogMessage2";
final PackageUserState testUserState1 = new PackageUserState();
testUserState1.suspended = true;
testUserState1.suspendedAppExtras = appExtras1;
testUserState1.suspendedLauncherExtras = launcherExtras1;
testUserState1.suspendingPackage = suspendingPackage1;
+ testUserState1.dialogMessage = dialogMessage1;
- final PackageUserState testUserState2 = new PackageUserState(testUserState1);
+ PackageUserState testUserState2 = new PackageUserState(testUserState1);
assertThat(testUserState1.equals(testUserState2), is(true));
testUserState2.suspendingPackage = suspendingPackage2;
assertThat(testUserState1.equals(testUserState2), is(false));
- testUserState2.suspendingPackage = testUserState1.suspendingPackage;
+ testUserState2 = new PackageUserState(testUserState1);
testUserState2.suspendedAppExtras = appExtras2;
assertThat(testUserState1.equals(testUserState2), is(false));
- testUserState2.suspendedAppExtras = testUserState1.suspendedAppExtras;
+ testUserState2 = new PackageUserState(testUserState1);
testUserState2.suspendedLauncherExtras = launcherExtras2;
assertThat(testUserState1.equals(testUserState2), is(false));
- // Everything is different but irrelevant if suspended is false
+ testUserState2 = new PackageUserState(testUserState1);
+ testUserState2.dialogMessage = dialogMessage2;
+ assertThat(testUserState1.equals(testUserState2), is(false));
+
+ testUserState2 = new PackageUserState(testUserState1);
testUserState2.suspended = testUserState1.suspended = false;
- testUserState2.suspendedAppExtras = appExtras2;
+ // Everything is different but irrelevant if suspended is false
testUserState2.suspendingPackage = suspendingPackage2;
+ testUserState2.dialogMessage = dialogMessage2;
+ testUserState2.suspendedAppExtras = appExtras2;
+ testUserState2.suspendedLauncherExtras = launcherExtras2;
assertThat(testUserState1.equals(testUserState2), is(true));
}
diff --git a/services/tests/servicestests/src/com/android/server/pm/SuspendPackagesTest.java b/services/tests/servicestests/src/com/android/server/pm/SuspendPackagesTest.java
index 43a439b..36e4753 100644
--- a/services/tests/servicestests/src/com/android/server/pm/SuspendPackagesTest.java
+++ b/services/tests/servicestests/src/com/android/server/pm/SuspendPackagesTest.java
@@ -21,6 +21,7 @@
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
import android.app.AppGlobals;
import android.content.BroadcastReceiver;
@@ -41,8 +42,15 @@
import android.support.test.InstrumentationRegistry;
import android.support.test.filters.LargeTest;
import android.support.test.runner.AndroidJUnit4;
+import android.support.test.uiautomator.By;
+import android.support.test.uiautomator.UiDevice;
+import android.support.test.uiautomator.UiObject2;
+import android.support.test.uiautomator.Until;
import android.util.Log;
+import android.view.IWindowManager;
+import android.view.WindowManagerGlobal;
+import com.android.servicestests.apps.suspendtestapp.SuspendTestActivity;
import com.android.servicestests.apps.suspendtestapp.SuspendTestReceiver;
import org.junit.After;
@@ -68,14 +76,25 @@
INSTRUMENTATION_PACKAGE + ".action.REPORT_MY_PACKAGE_SUSPENDED";
public static final String ACTION_REPORT_MY_PACKAGE_UNSUSPENDED =
INSTRUMENTATION_PACKAGE + ".action.REPORT_MY_PACKAGE_UNSUSPENDED";
+ public static final String ACTION_REPORT_TEST_ACTIVITY_STARTED =
+ INSTRUMENTATION_PACKAGE + ".action.REPORT_TEST_ACTIVITY_STARTED";
+ public static final String ACTION_REPORT_TEST_ACTIVITY_STOPPED =
+ INSTRUMENTATION_PACKAGE + ".action.REPORT_TEST_ACTIVITY_STOPPED";
+ public static final String ACTION_REPORT_MORE_DETAILS_ACTIVITY_STARTED =
+ INSTRUMENTATION_PACKAGE + ".action.REPORT_MORE_DETAILS_ACTIVITY_STARTED";
+ public static final String ACTION_FINISH_TEST_ACTIVITY =
+ INSTRUMENTATION_PACKAGE + ".action.FINISH_TEST_ACTIVITY";
+ public static final String EXTRA_RECEIVED_PACKAGE_NAME =
+ SuspendPackagesTest.INSTRUMENTATION_PACKAGE + ".extra.RECEIVED_PACKAGE_NAME";
+
private Context mContext;
private PackageManager mPackageManager;
private LauncherApps mLauncherApps;
private Handler mReceiverHandler;
- private ComponentName mTestReceiverComponent;
private AppCommunicationReceiver mAppCommsReceiver;
private StubbedCallback mTestCallback;
+ private UiDevice mUiDevice;
private static final class AppCommunicationReceiver extends BroadcastReceiver {
private Context context;
@@ -86,11 +105,12 @@
this.context = context;
}
- void register(Handler handler) {
+ void register(Handler handler, String... actions) {
registered = true;
final IntentFilter intentFilter = new IntentFilter();
- intentFilter.addAction(ACTION_REPORT_MY_PACKAGE_SUSPENDED);
- intentFilter.addAction(ACTION_REPORT_MY_PACKAGE_UNSUSPENDED);
+ for (String action : actions) {
+ intentFilter.addAction(action);
+ }
context.registerReceiver(this, intentFilter, null, handler);
}
@@ -110,19 +130,28 @@
}
}
- Intent receiveIntentFromApp() {
+ Intent pollForIntent(long secondsToWait) {
if (!registered) {
throw new IllegalStateException("Receiver not registered");
}
final Intent intent;
try {
- intent = intentQueue.poll(5, TimeUnit.SECONDS);
+ intent = intentQueue.poll(secondsToWait, TimeUnit.SECONDS);
} catch (InterruptedException ie) {
throw new RuntimeException("Interrupted while waiting for app broadcast", ie);
}
- assertNotNull("No intent received from app within 5 seconds", intent);
return intent;
}
+
+ void drainPendingBroadcasts() {
+ while (pollForIntent(5) != null);
+ }
+
+ Intent receiveIntentFromApp() {
+ final Intent intentReceived = pollForIntent(5);
+ assertNotNull("No intent received from app within 5 seconds", intentReceived);
+ return intentReceived;
+ }
}
@Before
@@ -131,8 +160,7 @@
mPackageManager = mContext.getPackageManager();
mLauncherApps = (LauncherApps) mContext.getSystemService(Context.LAUNCHER_APPS_SERVICE);
mReceiverHandler = new Handler(Looper.getMainLooper());
- mTestReceiverComponent = new ComponentName(TEST_APP_PACKAGE_NAME,
- SuspendTestReceiver.class.getCanonicalName());
+ mUiDevice = UiDevice.getInstance(InstrumentationRegistry.getInstrumentation());
IPackageManager ipm = AppGlobals.getPackageManager();
try {
// Otherwise implicit broadcasts will not be delivered.
@@ -151,9 +179,10 @@
private Bundle requestAppAction(String action) throws InterruptedException {
final AtomicReference<Bundle> result = new AtomicReference<>();
final CountDownLatch receiverLatch = new CountDownLatch(1);
-
+ final ComponentName testReceiverComponent = new ComponentName(TEST_APP_PACKAGE_NAME,
+ SuspendTestReceiver.class.getCanonicalName());
final Intent broadcastIntent = new Intent(action)
- .setComponent(mTestReceiverComponent)
+ .setComponent(testReceiverComponent)
.setFlags(Intent.FLAG_RECEIVER_FOREGROUND);
mContext.sendOrderedBroadcast(broadcastIntent, null, new BroadcastReceiver() {
@Override
@@ -175,9 +204,10 @@
return extras;
}
- private void suspendTestPackage(PersistableBundle appExtras, PersistableBundle launcherExtras) {
+ private void suspendTestPackage(PersistableBundle appExtras, PersistableBundle launcherExtras,
+ String dialogMessage) {
final String[] unchangedPackages = mPackageManager.setPackagesSuspended(
- PACKAGES_TO_SUSPEND, true, appExtras, launcherExtras, null);
+ PACKAGES_TO_SUSPEND, true, appExtras, launcherExtras, dialogMessage);
assertTrue("setPackagesSuspended returned non-empty list", unchangedPackages.length == 0);
}
@@ -187,6 +217,13 @@
assertTrue("setPackagesSuspended returned non-empty list", unchangedPackages.length == 0);
}
+ private void startTestAppActivity() {
+ final Intent testActivity = new Intent()
+ .setComponent(new ComponentName(TEST_APP_PACKAGE_NAME,
+ SuspendTestActivity.class.getCanonicalName()))
+ .setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
+ mContext.startActivity(testActivity);
+ }
private static boolean areSameExtras(BaseBundle expected, BaseBundle received) {
if (expected != null) {
@@ -199,13 +236,14 @@
}
private static void assertSameExtras(String message, BaseBundle expected, BaseBundle received) {
- assertTrue(message + ": [expected: " + expected + "; received: " + received + "]",
- areSameExtras(expected, received));
+ if (!areSameExtras(expected, received)) {
+ fail(message + ": [expected: " + expected + "; received: " + received + "]");
+ }
}
@Test
public void testIsPackageSuspended() {
- suspendTestPackage(null, null);
+ suspendTestPackage(null, null, null);
assertTrue("isPackageSuspended is false",
mPackageManager.isPackageSuspended(TEST_APP_PACKAGE_NAME));
}
@@ -217,7 +255,7 @@
assertNull(resultFromApp.getBundle(SuspendTestReceiver.EXTRA_SUSPENDED_APP_EXTRAS));
final PersistableBundle appExtras = getExtras("testSuspendedStateFromApp", 20, "20", 0.2);
- suspendTestPackage(appExtras, null);
+ suspendTestPackage(appExtras, null, null);
resultFromApp = requestAppAction(SuspendTestReceiver.ACTION_GET_SUSPENDED_STATE);
assertTrue("resultFromApp:suspended is false",
@@ -230,37 +268,39 @@
@Test
public void testMyPackageSuspendedUnsuspended() {
- mAppCommsReceiver.register(mReceiverHandler);
+ mAppCommsReceiver.register(mReceiverHandler, ACTION_REPORT_MY_PACKAGE_SUSPENDED,
+ ACTION_REPORT_MY_PACKAGE_UNSUSPENDED);
+ mAppCommsReceiver.drainPendingBroadcasts();
final PersistableBundle appExtras = getExtras("testMyPackageSuspendBroadcasts", 1, "1", .1);
- suspendTestPackage(appExtras, null);
+ suspendTestPackage(appExtras, null, null);
Intent intentFromApp = mAppCommsReceiver.receiveIntentFromApp();
- assertTrue("MY_PACKAGE_SUSPENDED delivery not reported",
- ACTION_REPORT_MY_PACKAGE_SUSPENDED.equals(intentFromApp.getAction()));
+ assertEquals("MY_PACKAGE_SUSPENDED delivery not reported",
+ ACTION_REPORT_MY_PACKAGE_SUSPENDED, intentFromApp.getAction());
assertSameExtras("Received app extras different to the ones supplied", appExtras,
intentFromApp.getBundleExtra(SuspendTestReceiver.EXTRA_SUSPENDED_APP_EXTRAS));
unsuspendTestPackage();
intentFromApp = mAppCommsReceiver.receiveIntentFromApp();
- assertTrue("MY_PACKAGE_UNSUSPENDED delivery not reported",
- ACTION_REPORT_MY_PACKAGE_UNSUSPENDED.equals(intentFromApp.getAction()));
+ assertEquals("MY_PACKAGE_UNSUSPENDED delivery not reported",
+ ACTION_REPORT_MY_PACKAGE_UNSUSPENDED, intentFromApp.getAction());
}
@Test
public void testUpdatingAppExtras() {
- mAppCommsReceiver.register(mReceiverHandler);
+ mAppCommsReceiver.register(mReceiverHandler, ACTION_REPORT_MY_PACKAGE_SUSPENDED);
final PersistableBundle extras1 = getExtras("testMyPackageSuspendedOnChangingExtras", 1,
"1", 0.1);
- suspendTestPackage(extras1, null);
+ suspendTestPackage(extras1, null, null);
Intent intentFromApp = mAppCommsReceiver.receiveIntentFromApp();
- assertTrue("MY_PACKAGE_SUSPENDED delivery not reported",
- ACTION_REPORT_MY_PACKAGE_SUSPENDED.equals(intentFromApp.getAction()));
+ assertEquals("MY_PACKAGE_SUSPENDED delivery not reported",
+ ACTION_REPORT_MY_PACKAGE_SUSPENDED, intentFromApp.getAction());
assertSameExtras("Received app extras different to the ones supplied", extras1,
intentFromApp.getBundleExtra(SuspendTestReceiver.EXTRA_SUSPENDED_APP_EXTRAS));
final PersistableBundle extras2 = getExtras("testMyPackageSuspendedOnChangingExtras", 2,
"2", 0.2);
mPackageManager.setSuspendedPackageAppExtras(TEST_APP_PACKAGE_NAME, extras2);
intentFromApp = mAppCommsReceiver.receiveIntentFromApp();
- assertTrue("MY_PACKAGE_SUSPENDED delivery not reported",
- ACTION_REPORT_MY_PACKAGE_SUSPENDED.equals(intentFromApp.getAction()));
+ assertEquals("MY_PACKAGE_SUSPENDED delivery not reported",
+ ACTION_REPORT_MY_PACKAGE_SUSPENDED, intentFromApp.getAction());
assertSameExtras("Received app extras different to the updated extras", extras2,
intentFromApp.getBundleExtra(SuspendTestReceiver.EXTRA_SUSPENDED_APP_EXTRAS));
}
@@ -274,12 +314,26 @@
}
@Test
+ public void testActivityStoppedOnSuspend() {
+ mAppCommsReceiver.register(mReceiverHandler, ACTION_REPORT_TEST_ACTIVITY_STARTED,
+ ACTION_REPORT_TEST_ACTIVITY_STOPPED);
+ startTestAppActivity();
+ Intent intentFromApp = mAppCommsReceiver.receiveIntentFromApp();
+ assertEquals("Test activity start not reported",
+ ACTION_REPORT_TEST_ACTIVITY_STARTED, intentFromApp.getAction());
+ suspendTestPackage(null, null, null);
+ intentFromApp = mAppCommsReceiver.receiveIntentFromApp();
+ assertEquals("Test activity stop not reported on suspending the test app",
+ ACTION_REPORT_TEST_ACTIVITY_STOPPED, intentFromApp.getAction());
+ }
+
+ @Test
public void testGetLauncherExtrasNonNull() {
final Bundle extrasWhenUnsuspended = mLauncherApps.getSuspendedPackageLauncherExtras(
TEST_APP_PACKAGE_NAME, mContext.getUser());
assertNull("Non null extras when package unsuspended:", extrasWhenUnsuspended);
final PersistableBundle launcherExtras = getExtras("testGetLauncherExtras", 1, "1", 0.1);
- suspendTestPackage(null, launcherExtras);
+ suspendTestPackage(null, launcherExtras, null);
final Bundle receivedExtras = mLauncherApps.getSuspendedPackageLauncherExtras(
TEST_APP_PACKAGE_NAME, mContext.getUser());
assertSameExtras("Received launcher extras different to the ones supplied", launcherExtras,
@@ -288,7 +342,7 @@
@Test
public void testGetLauncherExtrasNull() {
- suspendTestPackage(null, null);
+ suspendTestPackage(null, null, null);
final Bundle extrasWhenNoneGiven = mLauncherApps.getSuspendedPackageLauncherExtras(
TEST_APP_PACKAGE_NAME, mContext.getUser());
assertNull("Non null extras when null extras provided:", extrasWhenNoneGiven);
@@ -339,7 +393,7 @@
}
};
mLauncherApps.registerCallback(mTestCallback, mReceiverHandler);
- suspendTestPackage(null, suppliedExtras);
+ suspendTestPackage(null, suppliedExtras, null);
assertFalse("Both callbacks were invoked", twoCallbackLatch.await(5, TimeUnit.SECONDS));
twoCallbackLatch.countDown();
assertTrue("No callback was invoked", twoCallbackLatch.await(2, TimeUnit.SECONDS));
@@ -373,19 +427,53 @@
}
};
mLauncherApps.registerCallback(mTestCallback, mReceiverHandler);
- suspendTestPackage(null, suppliedExtras);
+ suspendTestPackage(null, suppliedExtras, null);
assertTrue("Callback not invoked", oneCallbackLatch.await(5, TimeUnit.SECONDS));
final String result = overridingOneCallbackResult.get();
assertTrue("Callback did not complete as expected: " + result, result.isEmpty());
}
+ private void turnScreenOn() throws Exception {
+ if (!mUiDevice.isScreenOn()) {
+ mUiDevice.wakeUp();
+ }
+ final IWindowManager wm = WindowManagerGlobal.getWindowManagerService();
+ wm.dismissKeyguard(null, null);
+ }
+
+ @Test
+ public void testInterceptorActivity() throws Exception {
+ turnScreenOn();
+ mAppCommsReceiver.register(mReceiverHandler, ACTION_REPORT_MORE_DETAILS_ACTIVITY_STARTED,
+ ACTION_REPORT_TEST_ACTIVITY_STARTED);
+ final String testMessage = "This is a test message";
+ suspendTestPackage(null, null, testMessage);
+ startTestAppActivity();
+ assertNull("No broadcast was expected from app", mAppCommsReceiver.pollForIntent(2));
+ assertNotNull("Given dialog message not shown",
+ mUiDevice.wait(Until.findObject(By.text(testMessage)), 5000));
+ final String buttonText = "More details";
+ final UiObject2 moreDetailsButton = mUiDevice.findObject(
+ By.clickable(true).text(buttonText));
+ assertNotNull("\"More Details\" button not shown", moreDetailsButton);
+ moreDetailsButton.click();
+ final Intent intentFromApp = mAppCommsReceiver.receiveIntentFromApp();
+ assertEquals("\"More Details\" activity start not reported",
+ ACTION_REPORT_MORE_DETAILS_ACTIVITY_STARTED, intentFromApp.getAction());
+ final String receivedPackageName = intentFromApp.getStringExtra(
+ EXTRA_RECEIVED_PACKAGE_NAME);
+ assertEquals("Wrong package name received by \"More Details\" activity",
+ TEST_APP_PACKAGE_NAME, receivedPackageName);
+ }
+
@After
- public void tearDown() throws Exception {
+ public void tearDown() {
mAppCommsReceiver.unregister();
if (mTestCallback != null) {
mLauncherApps.unregisterCallback(mTestCallback);
}
- Thread.sleep(250); // To prevent any race with the next registerReceiver
+ mContext.sendBroadcast(new Intent(ACTION_FINISH_TEST_ACTIVITY)
+ .setPackage(TEST_APP_PACKAGE_NAME));
}
private static abstract class StubbedCallback extends LauncherApps.Callback {
diff --git a/services/tests/servicestests/src/com/android/server/pm/SuspendedDetailsActivity.java b/services/tests/servicestests/src/com/android/server/pm/SuspendedDetailsActivity.java
new file mode 100644
index 0000000..18f0123
--- /dev/null
+++ b/services/tests/servicestests/src/com/android/server/pm/SuspendedDetailsActivity.java
@@ -0,0 +1,42 @@
+/*
+ * 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.server.pm;
+
+import static com.android.server.pm.SuspendPackagesTest.ACTION_REPORT_MORE_DETAILS_ACTIVITY_STARTED;
+import static com.android.server.pm.SuspendPackagesTest.EXTRA_RECEIVED_PACKAGE_NAME;
+import static com.android.server.pm.SuspendPackagesTest.INSTRUMENTATION_PACKAGE;
+
+import android.app.Activity;
+import android.content.Intent;
+import android.os.Bundle;
+import android.util.Log;
+
+public class SuspendedDetailsActivity extends Activity {
+ private static final String TAG = SuspendedDetailsActivity.class.getSimpleName();
+
+ @Override
+ protected void onStart() {
+ Log.d(TAG, "onStart");
+ final String suspendedPackage = getIntent().getStringExtra(Intent.EXTRA_PACKAGE_NAME);
+ super.onStart();
+ final Intent reportStart = new Intent(ACTION_REPORT_MORE_DETAILS_ACTIVITY_STARTED)
+ .putExtra(EXTRA_RECEIVED_PACKAGE_NAME, suspendedPackage)
+ .setPackage(INSTRUMENTATION_PACKAGE);
+ sendBroadcast(reportStart);
+ finish();
+ }
+}
diff --git a/services/tests/servicestests/src/com/android/server/webkit/WebViewUpdateServiceTest.java b/services/tests/servicestests/src/com/android/server/webkit/WebViewUpdateServiceTest.java
index 9ad41cd..dca09af 100644
--- a/services/tests/servicestests/src/com/android/server/webkit/WebViewUpdateServiceTest.java
+++ b/services/tests/servicestests/src/com/android/server/webkit/WebViewUpdateServiceTest.java
@@ -21,7 +21,6 @@
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
-import android.content.Context;
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageInfo;
import android.content.pm.Signature;
@@ -206,7 +205,7 @@
PackageInfo p = createPackageInfo(packageName, enabled, valid, installed, signatures,
updateTime, hidden);
p.setLongVersionCode(versionCode);
- p.applicationInfo.versionCode = versionCode;
+ p.applicationInfo.setVersionCode(versionCode);
if (isSystemApp) p.applicationInfo.flags |= ApplicationInfo.FLAG_SYSTEM;
return p;
}
diff --git a/services/tests/servicestests/src/com/android/server/wm/AppTransitionTests.java b/services/tests/servicestests/src/com/android/server/wm/AppTransitionTests.java
index e7e55cd..8e5aec3 100644
--- a/services/tests/servicestests/src/com/android/server/wm/AppTransitionTests.java
+++ b/services/tests/servicestests/src/com/android/server/wm/AppTransitionTests.java
@@ -28,6 +28,7 @@
import android.support.test.runner.AndroidJUnit4;
import org.junit.Before;
+import org.junit.Rule;
import org.junit.Test;
import org.junit.runner.RunWith;
@@ -41,12 +42,14 @@
@RunWith(AndroidJUnit4.class)
public class AppTransitionTests {
+ @Rule
+ public final WindowManagerServiceRule mRule = new WindowManagerServiceRule();
private WindowManagerService mWm;
@Before
public void setUp() throws Exception {
final Context context = InstrumentationRegistry.getTargetContext();
- mWm = TestWindowManagerPolicy.getWindowManagerService(context);
+ mWm = mRule.getWindowManagerService();
}
@Test
diff --git a/services/tests/servicestests/src/com/android/server/wm/TestWindowManagerPolicy.java b/services/tests/servicestests/src/com/android/server/wm/TestWindowManagerPolicy.java
index 1af344b..1c2d538 100644
--- a/services/tests/servicestests/src/com/android/server/wm/TestWindowManagerPolicy.java
+++ b/services/tests/servicestests/src/com/android/server/wm/TestWindowManagerPolicy.java
@@ -16,108 +16,47 @@
package com.android.server.wm;
-import static android.view.Display.DEFAULT_DISPLAY;
import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_STARTING;
import static android.view.WindowManager.LayoutParams.TYPE_STATUS_BAR;
-import static com.android.server.wm.WindowManagerDebugConfig.TAG_WM;
-
-import static org.mockito.ArgumentMatchers.anyString;
-import static org.mockito.Matchers.anyInt;
-import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.any;
-import static org.mockito.Mockito.doAnswer;
-import static org.mockito.Mockito.spy;
-
-import android.os.PowerSaveState;
-import android.util.proto.ProtoOutputStream;
-import org.mockito.invocation.InvocationOnMock;
import android.annotation.Nullable;
-import android.app.ActivityManagerInternal;
import android.content.Context;
import android.content.res.CompatibilityInfo;
import android.content.res.Configuration;
import android.graphics.Rect;
-import android.hardware.display.DisplayManagerInternal;
import android.os.Bundle;
import android.os.IBinder;
import android.os.RemoteException;
+import android.util.proto.ProtoOutputStream;
import android.view.Display;
import android.view.DisplayCutout;
+import android.view.IWindow;
import android.view.IWindowManager;
-import android.view.InputChannel;
import android.view.KeyEvent;
import android.view.WindowManager;
import android.view.animation.Animation;
-import android.os.PowerManagerInternal;
import com.android.internal.policy.IKeyguardDismissCallback;
import com.android.internal.policy.IShortcutService;
-import com.android.server.input.InputManagerService;
-import com.android.server.LocalServices;
import com.android.server.policy.WindowManagerPolicy;
import java.io.PrintWriter;
+import java.util.function.Supplier;
class TestWindowManagerPolicy implements WindowManagerPolicy {
private static final String TAG = "TestWindowManagerPolicy";
- private static WindowManagerService sWm = null;
+ private final Supplier<WindowManagerService> mWmSupplier;
int rotationToReport = 0;
private Runnable mRunnableWhenAddingSplashScreen;
- static synchronized WindowManagerService getWindowManagerService(Context context) {
- if (sWm == null) {
- // We only want to do this once for the test process as we don't want WM to try to
- // register a bunch of local services again.
- if (LocalServices.getService(DisplayManagerInternal.class) == null) {
- LocalServices.addService(DisplayManagerInternal.class,
- mock(DisplayManagerInternal.class));
- }
- if (LocalServices.getService(PowerManagerInternal.class) == null) {
- LocalServices.addService(PowerManagerInternal.class,
- mock(PowerManagerInternal.class));
- final PowerManagerInternal pm =
- LocalServices.getService(PowerManagerInternal.class);
- PowerSaveState state = new PowerSaveState.Builder().build();
- doReturn(state).when(pm).getLowPowerState(anyInt());
- }
- if (LocalServices.getService(ActivityManagerInternal.class) == null) {
- LocalServices.addService(ActivityManagerInternal.class,
- mock(ActivityManagerInternal.class));
- final ActivityManagerInternal am =
- LocalServices.getService(ActivityManagerInternal.class);
- doAnswer((InvocationOnMock invocationOnMock) -> {
- final Runnable runnable = invocationOnMock.<Runnable>getArgument(0);
- if (runnable != null) {
- runnable.run();
- }
- return null;
- }).when(am).notifyKeyguardFlagsChanged(any());
- }
+ public TestWindowManagerPolicy(Supplier<WindowManagerService> wmSupplier) {
- InputManagerService ims = mock(InputManagerService.class);
- // InputChannel is final and can't be mocked.
- InputChannel[] input = InputChannel.openInputChannelPair(TAG_WM);
- if (input != null && input.length > 1) {
- doReturn(input[1]).when(ims).monitorInput(anyString());
- }
-
- sWm = WindowManagerService.main(context, ims, true, false,
- false, new TestWindowManagerPolicy());
-
- sWm.onInitReady();
-
- // Display creation is driven by the ActivityManagerService via ActivityStackSupervisor.
- // We emulate those steps here.
- sWm.mRoot.createDisplayContent(sWm.mDisplayManager.getDisplay(DEFAULT_DISPLAY),
- mock(DisplayWindowController.class));
- }
- return sWm;
+ mWmSupplier = wmSupplier;
}
@Override
@@ -216,10 +155,12 @@
int logo, int windowFlags, Configuration overrideConfig, int displayId) {
final com.android.server.wm.WindowState window;
final AppWindowToken atoken;
- synchronized (sWm.mWindowMap) {
- atoken = sWm.mRoot.getAppWindowToken(appToken);
+ final WindowManagerService wm = mWmSupplier.get();
+ synchronized (wm.mWindowMap) {
+ atoken = wm.mRoot.getAppWindowToken(appToken);
window = WindowTestsBase.createWindow(null, TYPE_APPLICATION_STARTING, atoken,
- "Starting window");
+ "Starting window", 0 /* ownerId */, false /* internalWindows */, wm,
+ mock(Session.class), mock(IWindow.class));
atoken.startingWindow = window;
}
if (mRunnableWhenAddingSplashScreen != null) {
@@ -227,7 +168,7 @@
mRunnableWhenAddingSplashScreen = null;
}
return () -> {
- synchronized (sWm.mWindowMap) {
+ synchronized (wm.mWindowMap) {
atoken.removeChild(window);
atoken.startingWindow = null;
}
diff --git a/services/tests/servicestests/src/com/android/server/wm/WindowManagerServiceRule.java b/services/tests/servicestests/src/com/android/server/wm/WindowManagerServiceRule.java
new file mode 100644
index 0000000..32bfda32
--- /dev/null
+++ b/services/tests/servicestests/src/com/android/server/wm/WindowManagerServiceRule.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 com.android.server.wm;
+
+import static android.testing.DexmakerShareClassLoaderRule.runWithDexmakerShareClassLoader;
+import static android.view.Display.DEFAULT_DISPLAY;
+
+import static com.android.server.wm.WindowManagerDebugConfig.TAG_WM;
+
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.anyInt;
+import static org.mockito.ArgumentMatchers.anyString;
+import static org.mockito.Mockito.doAnswer;
+import static org.mockito.Mockito.doReturn;
+import static org.mockito.Mockito.mock;
+
+import android.app.ActivityManagerInternal;
+import android.content.Context;
+import android.hardware.display.DisplayManagerInternal;
+import android.os.PowerManagerInternal;
+import android.os.PowerSaveState;
+import android.support.test.InstrumentationRegistry;
+import android.view.InputChannel;
+
+import com.android.server.LocalServices;
+import com.android.server.input.InputManagerService;
+import com.android.server.policy.WindowManagerPolicy;
+
+import org.junit.rules.TestRule;
+import org.junit.runner.Description;
+import org.junit.runners.model.Statement;
+import org.mockito.invocation.InvocationOnMock;
+
+/**
+ * A test rule that sets up a fresh WindowManagerService instance before each test and makes sure
+ * to properly tear it down after.
+ *
+ * <p>
+ * Usage:
+ * <pre>
+ * {@literal @}Rule
+ * public final WindowManagerServiceRule mWmRule = new WindowManagerServiceRule();
+ * </pre>
+ */
+public class WindowManagerServiceRule implements TestRule {
+
+ private WindowManagerService mService;
+
+ @Override
+ public Statement apply(Statement base, Description description) {
+ return new Statement() {
+ @Override
+ public void evaluate() throws Throwable {
+ runWithDexmakerShareClassLoader(this::setUp);
+ try {
+ base.evaluate();
+ } finally {
+ tearDown();
+ }
+ }
+
+ private void setUp() {
+ final Context context = InstrumentationRegistry.getTargetContext();
+
+ removeServices();
+
+ LocalServices.addService(DisplayManagerInternal.class,
+ mock(DisplayManagerInternal.class));
+
+ LocalServices.addService(PowerManagerInternal.class,
+ mock(PowerManagerInternal.class));
+ final PowerManagerInternal pm =
+ LocalServices.getService(PowerManagerInternal.class);
+ PowerSaveState state = new PowerSaveState.Builder().build();
+ doReturn(state).when(pm).getLowPowerState(anyInt());
+
+ LocalServices.addService(ActivityManagerInternal.class,
+ mock(ActivityManagerInternal.class));
+ final ActivityManagerInternal am =
+ LocalServices.getService(ActivityManagerInternal.class);
+ doAnswer((InvocationOnMock invocationOnMock) -> {
+ final Runnable runnable = invocationOnMock.<Runnable>getArgument(0);
+ if (runnable != null) {
+ runnable.run();
+ }
+ return null;
+ }).when(am).notifyKeyguardFlagsChanged(any());
+
+ InputManagerService ims = mock(InputManagerService.class);
+ // InputChannel is final and can't be mocked.
+ InputChannel[] input = InputChannel.openInputChannelPair(TAG_WM);
+ if (input != null && input.length > 1) {
+ doReturn(input[1]).when(ims).monitorInput(anyString());
+ }
+
+ mService = WindowManagerService.main(context, ims, true, false,
+ false, new TestWindowManagerPolicy(
+ WindowManagerServiceRule.this::getWindowManagerService));
+
+ mService.onInitReady();
+
+ // Display creation is driven by the ActivityManagerService via ActivityStackSupervisor.
+ // We emulate those steps here.
+ mService.mRoot.createDisplayContent(
+ mService.mDisplayManager.getDisplay(DEFAULT_DISPLAY),
+ mock(DisplayWindowController.class));
+ }
+
+ private void removeServices() {
+ LocalServices.removeServiceForTest(DisplayManagerInternal.class);
+ LocalServices.removeServiceForTest(PowerManagerInternal.class);
+ LocalServices.removeServiceForTest(ActivityManagerInternal.class);
+ LocalServices.removeServiceForTest(WindowManagerInternal.class);
+ LocalServices.removeServiceForTest(WindowManagerPolicy.class);
+ }
+
+ private void tearDown() {
+ waitUntilWindowManagerHandlersIdle();
+ removeServices();
+ mService = null;
+ }
+ };
+ }
+
+ public WindowManagerService getWindowManagerService() {
+ return mService;
+ }
+
+ public void waitUntilWindowManagerHandlersIdle() {
+ final WindowManagerService wm = getWindowManagerService();
+ if (wm != null) {
+ wm.mH.runWithScissors(() -> { }, 0);
+ wm.mAnimationHandler.runWithScissors(() -> { }, 0);
+ SurfaceAnimationThread.getHandler().runWithScissors(() -> { }, 0);
+ }
+ }
+}
diff --git a/services/tests/servicestests/src/com/android/server/wm/WindowManagerServiceRuleTest.java b/services/tests/servicestests/src/com/android/server/wm/WindowManagerServiceRuleTest.java
new file mode 100644
index 0000000..6cf6d7b
--- /dev/null
+++ b/services/tests/servicestests/src/com/android/server/wm/WindowManagerServiceRuleTest.java
@@ -0,0 +1,42 @@
+/*
+ * 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.server.wm;
+
+import static org.hamcrest.CoreMatchers.notNullValue;
+import static org.junit.Assert.assertThat;
+
+import android.platform.test.annotations.Presubmit;
+import android.support.test.filters.SmallTest;
+import android.support.test.runner.AndroidJUnit4;
+
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+@RunWith(AndroidJUnit4.class)
+@Presubmit
+@SmallTest
+public class WindowManagerServiceRuleTest {
+
+ @Rule
+ public final WindowManagerServiceRule mRule = new WindowManagerServiceRule();
+
+ @Test
+ public void testWindowManagerSetUp() {
+ assertThat(mRule.getWindowManagerService(), notNullValue());
+ }
+}
\ No newline at end of file
diff --git a/services/tests/servicestests/src/com/android/server/wm/WindowStateTests.java b/services/tests/servicestests/src/com/android/server/wm/WindowStateTests.java
index 7c928c9..85e846d 100644
--- a/services/tests/servicestests/src/com/android/server/wm/WindowStateTests.java
+++ b/services/tests/servicestests/src/com/android/server/wm/WindowStateTests.java
@@ -37,6 +37,7 @@
import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_ATTACHED_DIALOG;
import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_MEDIA;
import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_MEDIA_OVERLAY;
+import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY;
import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_SUB_PANEL;
import static android.view.WindowManager.LayoutParams.TYPE_INPUT_METHOD;
@@ -51,6 +52,7 @@
import static org.mockito.ArgumentMatchers.anyString;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.reset;
+import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.verify;
/**
@@ -129,6 +131,16 @@
}
@Test
+ public void testOverlayWindowHiddenWhenSuspended() {
+ final WindowState overlayWindow = spy(createWindow(null, TYPE_APPLICATION_OVERLAY,
+ "overlayWindow"));
+ overlayWindow.setHiddenWhileSuspended(true);
+ verify(overlayWindow).hideLw(true, true);
+ overlayWindow.setHiddenWhileSuspended(false);
+ verify(overlayWindow).showLw(true, true);
+ }
+
+ @Test
public void testGetTopParentWindow() throws Exception {
final WindowState root = createWindow(null, TYPE_APPLICATION, "root");
final WindowState child1 = createWindow(root, FIRST_SUB_WINDOW, "child1");
diff --git a/services/tests/servicestests/src/com/android/server/wm/WindowTestUtils.java b/services/tests/servicestests/src/com/android/server/wm/WindowTestUtils.java
index f4cdc90..d74defc 100644
--- a/services/tests/servicestests/src/com/android/server/wm/WindowTestUtils.java
+++ b/services/tests/servicestests/src/com/android/server/wm/WindowTestUtils.java
@@ -48,13 +48,6 @@
public static int sNextTaskId = 0;
/**
- * Retrieves an instance of {@link WindowManagerService}, creating it if necessary.
- */
- public static WindowManagerService getWindowManagerService(Context context) {
- return TestWindowManagerPolicy.getWindowManagerService(context);
- }
-
- /**
* Retrieves an instance of a mock {@link WindowManagerService}.
*/
public static WindowManagerService getMockWindowManagerService() {
diff --git a/services/tests/servicestests/src/com/android/server/wm/WindowTestsBase.java b/services/tests/servicestests/src/com/android/server/wm/WindowTestsBase.java
index d2eee68..473a287 100644
--- a/services/tests/servicestests/src/com/android/server/wm/WindowTestsBase.java
+++ b/services/tests/servicestests/src/com/android/server/wm/WindowTestsBase.java
@@ -24,14 +24,14 @@
import android.content.res.Configuration;
import android.graphics.Rect;
import android.hardware.display.DisplayManagerGlobal;
+import android.testing.DexmakerShareClassLoaderRule;
import android.util.Log;
import android.view.Display;
import android.view.DisplayInfo;
import org.junit.Assert;
import org.junit.After;
import org.junit.Before;
-import org.mockito.Mock;
-import org.mockito.MockitoAnnotations;
+import org.junit.Rule;
import android.content.Context;
import android.support.test.InstrumentationRegistry;
@@ -66,16 +66,15 @@
*/
class WindowTestsBase {
private static final String TAG = WindowTestsBase.class.getSimpleName();
- static WindowManagerService sWm = null;
- private static final IWindow sIWindow = new TestIWindow();
- private static Session sMockSession;
+ WindowManagerService sWm = null; // TODO(roosa): rename to mWm in follow-up CL
+ private final IWindow mIWindow = new TestIWindow();
+ private Session mMockSession;
// The default display is removed in {@link #setUp} and then we iterate over all displays to
// make sure we don't collide with any existing display. If we run into no other display, the
// added display should be treated as default. This cannot be the default display
private static int sNextDisplayId = DEFAULT_DISPLAY + 1;
static int sNextStackId = 1000;
- private static boolean sOneTimeSetupDone = false;
DisplayContent mDisplayContent;
DisplayInfo mDisplayInfo = new DisplayInfo();
WindowState mWallpaperWindow;
@@ -90,27 +89,27 @@
HashSet<WindowState> mCommonWindows;
WallpaperController mWallpaperController;
- @Mock
- static WindowState.PowerManagerWrapper mPowerManagerWrapper;
+ @Rule
+ public final DexmakerShareClassLoaderRule mDexmakerShareClassLoaderRule =
+ new DexmakerShareClassLoaderRule();
+
+ @Rule
+ public final WindowManagerServiceRule mWmRule = new WindowManagerServiceRule();
+
+ static WindowState.PowerManagerWrapper mPowerManagerWrapper; // TODO(roosa): make non-static.
@Before
public void setUp() throws Exception {
// If @Before throws an exception, the error isn't logged. This will make sure any failures
// in the set up are clear. This can be removed when b/37850063 is fixed.
try {
- if (!sOneTimeSetupDone) {
- sOneTimeSetupDone = true;
-
- // Allows to mock package local classes and methods
- System.setProperty("dexmaker.share_classloader", "true");
- MockitoAnnotations.initMocks(this);
- sMockSession = mock(Session.class);
- }
+ mMockSession = mock(Session.class);
+ mPowerManagerWrapper = mock(WindowState.PowerManagerWrapper.class);
final Context context = InstrumentationRegistry.getTargetContext();
AttributeCache.init(context);
- sWm = TestWindowManagerPolicy.getWindowManagerService(context);
+ sWm = mWmRule.getWindowManagerService();
beforeCreateDisplay();
mWallpaperController = new WallpaperController(sWm);
@@ -217,9 +216,7 @@
* Waits until the main handler for WM has processed all messages.
*/
void waitUntilHandlersIdle() {
- sWm.mH.runWithScissors(() -> { }, 0);
- sWm.mAnimationHandler.runWithScissors(() -> { }, 0);
- SurfaceAnimationThread.getHandler().runWithScissors(() -> { }, 0);
+ mWmRule.waitUntilWindowManagerHandlersIdle();
}
private WindowToken createWindowToken(
@@ -285,20 +282,27 @@
}
}
- static WindowState createWindow(WindowState parent, int type, WindowToken token, String name) {
+ WindowState createWindow(WindowState parent, int type, WindowToken token, String name) {
synchronized (sWm.mWindowMap) {
return createWindow(parent, type, token, name, 0 /* ownerId */,
false /* ownerCanAddInternalSystemWindow */);
}
}
- static WindowState createWindow(WindowState parent, int type, WindowToken token, String name,
+ WindowState createWindow(WindowState parent, int type, WindowToken token, String name,
int ownerId, boolean ownerCanAddInternalSystemWindow) {
- synchronized (sWm.mWindowMap) {
+ return createWindow(parent, type, token, name, ownerId, ownerCanAddInternalSystemWindow,
+ sWm, mMockSession, mIWindow);
+ }
+
+ static WindowState createWindow(WindowState parent, int type, WindowToken token,
+ String name, int ownerId, boolean ownerCanAddInternalSystemWindow,
+ WindowManagerService service, Session session, IWindow iWindow) {
+ synchronized (service.mWindowMap) {
final WindowManager.LayoutParams attrs = new WindowManager.LayoutParams(type);
attrs.setTitle(name);
- final WindowState w = new WindowState(sWm, sMockSession, sIWindow, token, parent,
+ final WindowState w = new WindowState(service, session, iWindow, token, parent,
OP_NONE,
0, attrs, VISIBLE, ownerId, ownerCanAddInternalSystemWindow,
mPowerManagerWrapper);
@@ -357,7 +361,7 @@
WindowTestUtils.TestWindowState createWindowState(WindowManager.LayoutParams attrs,
WindowToken token) {
synchronized (sWm.mWindowMap) {
- return new WindowTestUtils.TestWindowState(sWm, sMockSession, sIWindow, attrs, token);
+ return new WindowTestUtils.TestWindowState(sWm, mMockSession, mIWindow, attrs, token);
}
}
diff --git a/services/tests/servicestests/test-apps/SuspendTestApp/Android.mk b/services/tests/servicestests/test-apps/SuspendTestApp/Android.mk
index afdde72..ae0b0f9 100644
--- a/services/tests/servicestests/test-apps/SuspendTestApp/Android.mk
+++ b/services/tests/servicestests/test-apps/SuspendTestApp/Android.mk
@@ -20,7 +20,7 @@
LOCAL_COMPATIBILITY_SUITE := device-tests
-LOCAL_STATIC_JAVA_LIBRARIES := android-support-test
+LOCAL_STATIC_JAVA_LIBRARIES := android-support-test ub-uiautomator
LOCAL_SRC_FILES := $(call all-subdir-java-files)
LOCAL_SRC_FILES += ../../src/com/android/server/pm/SuspendPackagesTest.java
diff --git a/services/tests/servicestests/test-apps/SuspendTestApp/src/com/android/servicestests/apps/suspendtestapp/SuspendTestActivity.java b/services/tests/servicestests/test-apps/SuspendTestApp/src/com/android/servicestests/apps/suspendtestapp/SuspendTestActivity.java
index fa5fc58..ab7ddbb 100644
--- a/services/tests/servicestests/test-apps/SuspendTestApp/src/com/android/servicestests/apps/suspendtestapp/SuspendTestActivity.java
+++ b/services/tests/servicestests/test-apps/SuspendTestApp/src/com/android/servicestests/apps/suspendtestapp/SuspendTestActivity.java
@@ -16,9 +16,45 @@
package com.android.servicestests.apps.suspendtestapp;
+import static com.android.server.pm.SuspendPackagesTest.ACTION_FINISH_TEST_ACTIVITY;
+import static com.android.server.pm.SuspendPackagesTest.ACTION_REPORT_TEST_ACTIVITY_STARTED;
+import static com.android.server.pm.SuspendPackagesTest.ACTION_REPORT_TEST_ACTIVITY_STOPPED;
+import static com.android.server.pm.SuspendPackagesTest.INSTRUMENTATION_PACKAGE;
+
import android.app.Activity;
+import android.content.BroadcastReceiver;
+import android.content.Context;
+import android.content.Intent;
+import android.content.IntentFilter;
+import android.util.Log;
public class SuspendTestActivity extends Activity {
private static final String TAG = SuspendTestActivity.class.getSimpleName();
-}
\ No newline at end of file
+ private BroadcastReceiver mFinishReceiver = new BroadcastReceiver() {
+ @Override
+ public void onReceive(Context context, Intent intent) {
+ Log.d(TAG, "Finishing test activity from receiver");
+ SuspendTestActivity.this.finish();
+ }
+ };
+
+ @Override
+ public void onStart() {
+ Log.d(TAG, "onStart");
+ final Intent reportStart = new Intent(ACTION_REPORT_TEST_ACTIVITY_STARTED)
+ .setPackage(INSTRUMENTATION_PACKAGE);
+ sendBroadcast(reportStart);
+ registerReceiver(mFinishReceiver, new IntentFilter(ACTION_FINISH_TEST_ACTIVITY));
+ super.onStart();
+ }
+ @Override
+ public void onStop() {
+ Log.d(TAG, "onStop");
+ final Intent reportStop = new Intent(ACTION_REPORT_TEST_ACTIVITY_STOPPED)
+ .setPackage(INSTRUMENTATION_PACKAGE);
+ sendBroadcast(reportStop);
+ unregisterReceiver(mFinishReceiver);
+ super.onStop();
+ }
+}
diff --git a/telephony/java/android/telephony/CarrierConfigManager.java b/telephony/java/android/telephony/CarrierConfigManager.java
index 288411a..aa76eab 100644
--- a/telephony/java/android/telephony/CarrierConfigManager.java
+++ b/telephony/java/android/telephony/CarrierConfigManager.java
@@ -2187,7 +2187,7 @@
sDefaults.putStringArray(KEY_FILTERED_CNAP_NAMES_STRING_ARRAY, null);
sDefaults.putBoolean(KEY_EDITABLE_WFC_ROAMING_MODE_BOOL, false);
sDefaults.putBoolean(KEY_STK_DISABLE_LAUNCH_BROWSER_BOOL, false);
- sDefaults.putBoolean(KEY_PERSIST_LPP_MODE_BOOL, false);
+ sDefaults.putBoolean(KEY_PERSIST_LPP_MODE_BOOL, true);
sDefaults.putStringArray(KEY_CARRIER_WIFI_STRING_ARRAY, null);
sDefaults.putInt(KEY_PREF_NETWORK_NOTIFICATION_DELAY_INT, -1);
sDefaults.putInt(KEY_EMERGENCY_NOTIFICATION_DELAY_INT, -1);
diff --git a/telephony/java/android/telephony/NetworkService.java b/telephony/java/android/telephony/NetworkService.java
index 35682a7..f7e6840 100644
--- a/telephony/java/android/telephony/NetworkService.java
+++ b/telephony/java/android/telephony/NetworkService.java
@@ -206,8 +206,10 @@
}
}
- /** @hide */
- protected NetworkService() {
+ /**
+ * Default constructor.
+ */
+ public NetworkService() {
mHandlerThread = new HandlerThread(TAG);
mHandlerThread.start();
diff --git a/telephony/java/android/telephony/data/DataService.java b/telephony/java/android/telephony/data/DataService.java
index e8c1cb1..4ca5ce3 100644
--- a/telephony/java/android/telephony/data/DataService.java
+++ b/telephony/java/android/telephony/data/DataService.java
@@ -429,8 +429,10 @@
}
}
- /** @hide */
- protected DataService() {
+ /**
+ * Default constructor.
+ */
+ public DataService() {
mHandlerThread = new HandlerThread(TAG);
mHandlerThread.start();
diff --git a/tests/net/java/android/net/IpSecManagerTest.java b/tests/net/java/android/net/IpSecManagerTest.java
index a946e50..13210e8 100644
--- a/tests/net/java/android/net/IpSecManagerTest.java
+++ b/tests/net/java/android/net/IpSecManagerTest.java
@@ -260,12 +260,14 @@
IpSecManager.IpSecTunnelInterface tunnelIntf =
createAndValidateVti(DUMMY_RESOURCE_ID, VTI_INTF_NAME);
- tunnelIntf.addAddress(VTI_INNER_ADDRESS);
+ tunnelIntf.addAddress(VTI_INNER_ADDRESS.getAddress(),
+ VTI_INNER_ADDRESS.getPrefixLength());
verify(mMockIpSecService)
.addAddressToTunnelInterface(
eq(DUMMY_RESOURCE_ID), eq(VTI_INNER_ADDRESS), anyString());
- tunnelIntf.removeAddress(VTI_INNER_ADDRESS);
+ tunnelIntf.removeAddress(VTI_INNER_ADDRESS.getAddress(),
+ VTI_INNER_ADDRESS.getPrefixLength());
verify(mMockIpSecService)
.addAddressToTunnelInterface(
eq(DUMMY_RESOURCE_ID), eq(VTI_INNER_ADDRESS), anyString());
diff --git a/tests/net/java/com/android/server/ConnectivityServiceTest.java b/tests/net/java/com/android/server/ConnectivityServiceTest.java
index 163dd2a..b0e11c4 100644
--- a/tests/net/java/com/android/server/ConnectivityServiceTest.java
+++ b/tests/net/java/com/android/server/ConnectivityServiceTest.java
@@ -17,6 +17,9 @@
package com.android.server;
import static android.net.ConnectivityManager.CONNECTIVITY_ACTION;
+import static android.net.ConnectivityManager.PRIVATE_DNS_MODE_OFF;
+import static android.net.ConnectivityManager.PRIVATE_DNS_MODE_OPPORTUNISTIC;
+import static android.net.ConnectivityManager.PRIVATE_DNS_MODE_PROVIDER_HOSTNAME;
import static android.net.ConnectivityManager.TYPE_ETHERNET;
import static android.net.ConnectivityManager.TYPE_MOBILE;
import static android.net.ConnectivityManager.TYPE_MOBILE_FOTA;
@@ -70,6 +73,7 @@
import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.verifyNoMoreInteractions;
import static org.mockito.Mockito.when;
@@ -181,6 +185,9 @@
private static final int TIMEOUT_MS = 500;
private static final int TEST_LINGER_DELAY_MS = 120;
+ private static final String MOBILE_IFNAME = "test_rmnet_data0";
+ private static final String WIFI_IFNAME = "test_wlan0";
+
private MockContext mServiceContext;
private WrappedConnectivityService mService;
private WrappedConnectivityManager mCm;
@@ -751,7 +758,7 @@
// NetworkMonitor implementation allowing overriding of Internet connectivity probe result.
private class WrappedNetworkMonitor extends NetworkMonitor {
- public Handler connectivityHandler;
+ public final Handler connectivityHandler;
// HTTP response code fed back to NetworkMonitor for Internet connectivity probe.
public int gen204ProbeResult = 500;
public String gen204ProbeRedirectUrl = null;
@@ -928,6 +935,7 @@
// Ensure that the default setting for Captive Portals is used for most tests
setCaptivePortalMode(Settings.Global.CAPTIVE_PORTAL_MODE_PROMPT);
setMobileDataAlwaysOn(false);
+ setPrivateDnsSettings(PRIVATE_DNS_MODE_OFF, "ignored.example.com");
}
@After
@@ -2582,6 +2590,14 @@
waitForIdle();
}
+ private void setPrivateDnsSettings(String mode, String specifier) {
+ final ContentResolver cr = mServiceContext.getContentResolver();
+ Settings.Global.putString(cr, Settings.Global.PRIVATE_DNS_MODE, mode);
+ Settings.Global.putString(cr, Settings.Global.PRIVATE_DNS_SPECIFIER, specifier);
+ mService.updatePrivateDnsSettings();
+ waitForIdle();
+ }
+
private boolean isForegroundNetwork(MockNetworkAgent network) {
NetworkCapabilities nc = mCm.getNetworkCapabilities(network.getNetwork());
assertNotNull(nc);
@@ -3583,7 +3599,7 @@
mCm.registerNetworkCallback(networkRequest, networkCallback);
LinkProperties lp = new LinkProperties();
- lp.setInterfaceName("wlan0");
+ lp.setInterfaceName(WIFI_IFNAME);
LinkAddress myIpv4Address = new LinkAddress("192.168.12.3/24");
RouteInfo myIpv4DefaultRoute = new RouteInfo((IpPrefix) null,
NetworkUtils.numericToInetAddress("192.168.12.1"), lp.getInterfaceName());
@@ -3672,52 +3688,63 @@
@Test
public void testBasicDnsConfigurationPushed() throws Exception {
- final String IFNAME = "test_rmnet_data0";
- final String[] EMPTY_TLS_SERVERS = new String[0];
+ setPrivateDnsSettings(PRIVATE_DNS_MODE_OPPORTUNISTIC, "ignored.example.com");
+ ArgumentCaptor<String[]> tlsServers = ArgumentCaptor.forClass(String[].class);
+
+ // Clear any interactions that occur as a result of CS starting up.
+ reset(mNetworkManagementService);
+
+ final String[] EMPTY_STRING_ARRAY = new String[0];
mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
waitForIdle();
verify(mNetworkManagementService, never()).setDnsConfigurationForNetwork(
- anyInt(), any(), any(), any(), anyString(), eq(EMPTY_TLS_SERVERS));
+ anyInt(), eq(EMPTY_STRING_ARRAY), any(), any(), eq(""), eq(EMPTY_STRING_ARRAY));
+ verifyNoMoreInteractions(mNetworkManagementService);
final LinkProperties cellLp = new LinkProperties();
- cellLp.setInterfaceName(IFNAME);
+ cellLp.setInterfaceName(MOBILE_IFNAME);
// Add IPv4 and IPv6 default routes, because DNS-over-TLS code does
// "is-reachable" testing in order to not program netd with unreachable
// nameservers that it might try repeated to validate.
cellLp.addLinkAddress(new LinkAddress("192.0.2.4/24"));
- cellLp.addRoute(new RouteInfo((IpPrefix) null, InetAddress.getByName("192.0.2.4"), IFNAME));
+ cellLp.addRoute(new RouteInfo((IpPrefix) null, InetAddress.getByName("192.0.2.4"),
+ MOBILE_IFNAME));
cellLp.addLinkAddress(new LinkAddress("2001:db8:1::1/64"));
- cellLp.addRoute(
- new RouteInfo((IpPrefix) null, InetAddress.getByName("2001:db8:1::1"), IFNAME));
+ cellLp.addRoute(new RouteInfo((IpPrefix) null, InetAddress.getByName("2001:db8:1::1"),
+ MOBILE_IFNAME));
mCellNetworkAgent.sendLinkProperties(cellLp);
mCellNetworkAgent.connect(false);
waitForIdle();
- verify(mNetworkManagementService, times(1)).setDnsConfigurationForNetwork(
- anyInt(), mStringArrayCaptor.capture(), any(), any(),
- anyString(), eq(EMPTY_TLS_SERVERS));
// CS tells netd about the empty DNS config for this network.
- assertEmpty(mStringArrayCaptor.getValue());
+ verify(mNetworkManagementService, atLeastOnce()).setDnsConfigurationForNetwork(
+ anyInt(), eq(EMPTY_STRING_ARRAY), any(), any(), eq(""), eq(EMPTY_STRING_ARRAY));
reset(mNetworkManagementService);
cellLp.addDnsServer(InetAddress.getByName("2001:db8::1"));
mCellNetworkAgent.sendLinkProperties(cellLp);
waitForIdle();
- verify(mNetworkManagementService, times(1)).setDnsConfigurationForNetwork(
+ verify(mNetworkManagementService, atLeastOnce()).setDnsConfigurationForNetwork(
anyInt(), mStringArrayCaptor.capture(), any(), any(),
- anyString(), eq(EMPTY_TLS_SERVERS));
+ eq(""), tlsServers.capture());
assertEquals(1, mStringArrayCaptor.getValue().length);
assertTrue(ArrayUtils.contains(mStringArrayCaptor.getValue(), "2001:db8::1"));
+ // Opportunistic mode.
+ assertTrue(ArrayUtils.contains(tlsServers.getValue(), "2001:db8::1"));
reset(mNetworkManagementService);
cellLp.addDnsServer(InetAddress.getByName("192.0.2.1"));
mCellNetworkAgent.sendLinkProperties(cellLp);
waitForIdle();
- verify(mNetworkManagementService, times(1)).setDnsConfigurationForNetwork(
+ verify(mNetworkManagementService, atLeastOnce()).setDnsConfigurationForNetwork(
anyInt(), mStringArrayCaptor.capture(), any(), any(),
- anyString(), eq(EMPTY_TLS_SERVERS));
+ eq(""), tlsServers.capture());
assertEquals(2, mStringArrayCaptor.getValue().length);
assertTrue(ArrayUtils.containsAll(mStringArrayCaptor.getValue(),
new String[]{"2001:db8::1", "192.0.2.1"}));
+ // Opportunistic mode.
+ assertEquals(2, tlsServers.getValue().length);
+ assertTrue(ArrayUtils.containsAll(tlsServers.getValue(),
+ new String[]{"2001:db8::1", "192.0.2.1"}));
reset(mNetworkManagementService);
final String TLS_SPECIFIER = "tls.example.com";
@@ -3730,7 +3757,7 @@
mCellNetworkAgent.getNetwork().netId,
new DnsManager.PrivateDnsConfig(TLS_SPECIFIER, TLS_IPS)));
waitForIdle();
- verify(mNetworkManagementService, times(1)).setDnsConfigurationForNetwork(
+ verify(mNetworkManagementService, atLeastOnce()).setDnsConfigurationForNetwork(
anyInt(), mStringArrayCaptor.capture(), any(), any(),
eq(TLS_SPECIFIER), eq(TLS_SERVERS));
assertEquals(2, mStringArrayCaptor.getValue().length);
@@ -3739,6 +3766,77 @@
reset(mNetworkManagementService);
}
+ @Test
+ public void testPrivateDnsSettingsChange() throws Exception {
+ final String[] EMPTY_STRING_ARRAY = new String[0];
+ ArgumentCaptor<String[]> tlsServers = ArgumentCaptor.forClass(String[].class);
+
+ // Clear any interactions that occur as a result of CS starting up.
+ reset(mNetworkManagementService);
+
+ // The default on Android is opportunistic mode ("Automatic").
+ setPrivateDnsSettings(PRIVATE_DNS_MODE_OPPORTUNISTIC, "ignored.example.com");
+
+ mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
+ waitForIdle();
+ // CS tells netd about the empty DNS config for this network.
+ verify(mNetworkManagementService, never()).setDnsConfigurationForNetwork(
+ anyInt(), eq(EMPTY_STRING_ARRAY), any(), any(), eq(""), eq(EMPTY_STRING_ARRAY));
+ verifyNoMoreInteractions(mNetworkManagementService);
+
+ final LinkProperties cellLp = new LinkProperties();
+ cellLp.setInterfaceName(MOBILE_IFNAME);
+ // Add IPv4 and IPv6 default routes, because DNS-over-TLS code does
+ // "is-reachable" testing in order to not program netd with unreachable
+ // nameservers that it might try repeated to validate.
+ cellLp.addLinkAddress(new LinkAddress("192.0.2.4/24"));
+ cellLp.addRoute(new RouteInfo((IpPrefix) null, InetAddress.getByName("192.0.2.4"),
+ MOBILE_IFNAME));
+ cellLp.addLinkAddress(new LinkAddress("2001:db8:1::1/64"));
+ cellLp.addRoute(new RouteInfo((IpPrefix) null, InetAddress.getByName("2001:db8:1::1"),
+ MOBILE_IFNAME));
+ cellLp.addDnsServer(InetAddress.getByName("2001:db8::1"));
+ cellLp.addDnsServer(InetAddress.getByName("192.0.2.1"));
+
+ mCellNetworkAgent.sendLinkProperties(cellLp);
+ mCellNetworkAgent.connect(false);
+ waitForIdle();
+ verify(mNetworkManagementService, atLeastOnce()).setDnsConfigurationForNetwork(
+ anyInt(), mStringArrayCaptor.capture(), any(), any(),
+ eq(""), tlsServers.capture());
+ assertEquals(2, mStringArrayCaptor.getValue().length);
+ assertTrue(ArrayUtils.containsAll(mStringArrayCaptor.getValue(),
+ new String[]{"2001:db8::1", "192.0.2.1"}));
+ // Opportunistic mode.
+ assertEquals(2, tlsServers.getValue().length);
+ assertTrue(ArrayUtils.containsAll(tlsServers.getValue(),
+ new String[]{"2001:db8::1", "192.0.2.1"}));
+ reset(mNetworkManagementService);
+
+ setPrivateDnsSettings(PRIVATE_DNS_MODE_OFF, "ignored.example.com");
+ verify(mNetworkManagementService, times(1)).setDnsConfigurationForNetwork(
+ anyInt(), mStringArrayCaptor.capture(), any(), any(),
+ eq(""), eq(EMPTY_STRING_ARRAY));
+ assertEquals(2, mStringArrayCaptor.getValue().length);
+ assertTrue(ArrayUtils.containsAll(mStringArrayCaptor.getValue(),
+ new String[]{"2001:db8::1", "192.0.2.1"}));
+ reset(mNetworkManagementService);
+
+ setPrivateDnsSettings(PRIVATE_DNS_MODE_OPPORTUNISTIC, "ignored.example.com");
+ verify(mNetworkManagementService, atLeastOnce()).setDnsConfigurationForNetwork(
+ anyInt(), mStringArrayCaptor.capture(), any(), any(),
+ eq(""), tlsServers.capture());
+ assertEquals(2, mStringArrayCaptor.getValue().length);
+ assertTrue(ArrayUtils.containsAll(mStringArrayCaptor.getValue(),
+ new String[]{"2001:db8::1", "192.0.2.1"}));
+ assertEquals(2, tlsServers.getValue().length);
+ assertTrue(ArrayUtils.containsAll(tlsServers.getValue(),
+ new String[]{"2001:db8::1", "192.0.2.1"}));
+ reset(mNetworkManagementService);
+
+ // Can't test strict mode without properly mocking out the DNS lookups.
+ }
+
private void checkDirectlyConnectedRoutes(Object callbackObj,
Collection<LinkAddress> linkAddresses, Collection<RouteInfo> otherRoutes) {
assertTrue(callbackObj instanceof LinkProperties);
diff --git a/tests/testables/src/android/testing/DexmakerShareClassLoaderRule.java b/tests/testables/src/android/testing/DexmakerShareClassLoaderRule.java
new file mode 100644
index 0000000..1b8e58c
--- /dev/null
+++ b/tests/testables/src/android/testing/DexmakerShareClassLoaderRule.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 android.testing;
+
+import android.util.Log;
+
+import com.android.internal.annotations.VisibleForTesting;
+
+import org.junit.rules.TestRule;
+import org.junit.runner.Description;
+import org.junit.runners.model.Statement;
+
+import java.util.ConcurrentModificationException;
+
+
+/**
+ * Runs the test such that mocks created in it don't use a dedicated classloader.
+ *
+ * This allows mocking package-private methods.
+ *
+ * WARNING: This is absolutely incompatible with running tests in parallel!
+ */
+public class DexmakerShareClassLoaderRule implements TestRule {
+
+ private static final String TAG = "ShareClassloaderRule";
+ @VisibleForTesting
+ static final String DEXMAKER_SHARE_CLASSLOADER_PROPERTY = "dexmaker.share_classloader";
+
+ private static Thread sOwningThread = null;
+
+ @Override
+ public Statement apply(Statement base, Description description) {
+ return apply(base::evaluate).toStatement();
+ }
+
+ /**
+ * Runs the runnable such that mocks created in it don't use a dedicated classloader.
+ *
+ * This allows mocking package-private methods.
+ *
+ * WARNING: This is absolutely incompatible with running tests in parallel!
+ */
+ public static void runWithDexmakerShareClassLoader(Runnable r) {
+ apply(r::run).run();
+ }
+
+ /**
+ * Returns a statement that first makes sure that only one thread at the time is modifying
+ * the property. Then actually sets the property, and runs the statement.
+ */
+ private static <T extends Throwable> ThrowingRunnable<T> apply(ThrowingRunnable<T> r) {
+ return wrapInMutex(wrapInSetAndClearProperty(r));
+ }
+
+ private static <T extends Throwable> ThrowingRunnable<T> wrapInSetAndClearProperty(
+ ThrowingRunnable<T> r) {
+ return () -> {
+ final String previousValue = System.getProperty(DEXMAKER_SHARE_CLASSLOADER_PROPERTY);
+ try {
+ System.setProperty(DEXMAKER_SHARE_CLASSLOADER_PROPERTY, "true");
+ r.run();
+ } finally {
+ if (previousValue != null) {
+ System.setProperty(DEXMAKER_SHARE_CLASSLOADER_PROPERTY, previousValue);
+ } else {
+ System.clearProperty(DEXMAKER_SHARE_CLASSLOADER_PROPERTY);
+ }
+ }
+ };
+ }
+
+ /**
+ * Runs the given statement, and while doing so prevents other threads from running statements.
+ */
+ private static <T extends Throwable> ThrowingRunnable<T> wrapInMutex(ThrowingRunnable<T> r) {
+ return () -> {
+ final boolean isOwner;
+ synchronized (DexmakerShareClassLoaderRule.class) {
+ isOwner = (sOwningThread == null);
+ if (isOwner) {
+ sOwningThread = Thread.currentThread();
+ } else if (sOwningThread != Thread.currentThread()) {
+ final RuntimeException e = new ConcurrentModificationException(
+ "Tried to set dexmaker.share_classloader from " + Thread.currentThread()
+ + ", but was already set from " + sOwningThread);
+ // Also log in case exception gets swallowed.
+ Log.e(TAG, e.getMessage(), e);
+ throw e;
+ }
+ }
+ try {
+ r.run();
+ } finally {
+ synchronized (DexmakerShareClassLoaderRule.class) {
+ if (isOwner) {
+ sOwningThread = null;
+ }
+ }
+ }
+ };
+ }
+
+ private interface ThrowingRunnable<T extends Throwable> {
+ void run() throws T;
+
+ default Statement toStatement() {
+ return new Statement() {
+ @Override
+ public void evaluate() throws Throwable {
+ ThrowingRunnable.this.run();
+ }
+ };
+ }
+ }
+}
diff --git a/tests/testables/tests/src/android/testing/DexmakerShareClassLoaderRuleTest.java b/tests/testables/tests/src/android/testing/DexmakerShareClassLoaderRuleTest.java
new file mode 100644
index 0000000..2528d09
--- /dev/null
+++ b/tests/testables/tests/src/android/testing/DexmakerShareClassLoaderRuleTest.java
@@ -0,0 +1,118 @@
+/*
+ * 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.testing;
+
+import static android.testing.DexmakerShareClassLoaderRule.DEXMAKER_SHARE_CLASSLOADER_PROPERTY;
+
+import static org.hamcrest.Matchers.is;
+import static org.junit.Assert.assertThat;
+import static org.junit.Assert.fail;
+
+import android.support.test.filters.SmallTest;
+import android.support.test.runner.AndroidJUnit4;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.model.Statement;
+
+import java.util.ConcurrentModificationException;
+
+@SmallTest
+@RunWith(AndroidJUnit4.class)
+public class DexmakerShareClassLoaderRuleTest {
+
+ // Intentionally not @Rule, so we have more control.
+ private final DexmakerShareClassLoaderRule mRule = new DexmakerShareClassLoaderRule();
+
+ @Before
+ public void setUp() throws Exception {
+ System.clearProperty(DEXMAKER_SHARE_CLASSLOADER_PROPERTY);
+ }
+
+ @Test
+ public void rule_setsProperty() throws Throwable {
+ mRule.apply(ASSERT_STATEMENT, null).evaluate();
+ }
+
+ @Test
+ public void rule_resetsProperty() throws Throwable {
+ mRule.apply(ASSERT_STATEMENT, null).evaluate();
+ assertThat(readProperty(), is(false));
+ }
+
+ @Test
+ public void rule_resetsProperty_toExactValue() throws Throwable {
+ System.setProperty(DEXMAKER_SHARE_CLASSLOADER_PROPERTY, "asdf");
+ mRule.apply(ASSERT_STATEMENT, null).evaluate();
+ assertThat(System.getProperty(DEXMAKER_SHARE_CLASSLOADER_PROPERTY), is("asdf"));
+ }
+
+ @Test
+ public void rule_preventsOtherThreadFromInterfering() throws Throwable {
+ mRule.apply(new Statement() {
+ @Override
+ public void evaluate() throws Throwable {
+ assertThat(readProperty(), is(true));
+
+ final Throwable[] thrown = new Throwable[1];
+ final Thread t = new Thread(() -> {
+ try {
+ new DexmakerShareClassLoaderRule().apply(ASSERT_STATEMENT, null).evaluate();
+ fail("Expected a ConcurrentModificationException");
+ } catch (ConcurrentModificationException e) {
+ // Success.
+ } catch (Throwable tr) {
+ thrown[0] = tr;
+ }
+ });
+ t.start();
+ t.join();
+
+ if (thrown[0] != null) {
+ throw thrown[0];
+ }
+ }
+ }, null).evaluate();
+ assertThat(readProperty(), is(false));
+ }
+
+ @Test
+ public void rule_isReentrant() throws Throwable {
+ mRule.apply(new Statement() {
+ @Override
+ public void evaluate() throws Throwable {
+ assertThat(readProperty(), is(true));
+ new DexmakerShareClassLoaderRule().apply(ASSERT_STATEMENT, null).evaluate();
+ assertThat(readProperty(), is(true));
+ }
+ }, null).evaluate();
+ assertThat(readProperty(), is(false));
+ }
+
+ private static boolean readProperty() {
+ return Boolean.parseBoolean(System.getProperty(DEXMAKER_SHARE_CLASSLOADER_PROPERTY));
+ }
+
+ private static final Statement ASSERT_STATEMENT = new Statement() {
+ @Override
+ public void evaluate() throws Throwable {
+ assertThat(readProperty(), is(true));
+ }
+ };
+
+}
diff --git a/tools/aapt2/ResourceParser_test.cpp b/tools/aapt2/ResourceParser_test.cpp
index c98c0b9..fc1aeaa 100644
--- a/tools/aapt2/ResourceParser_test.cpp
+++ b/tools/aapt2/ResourceParser_test.cpp
@@ -164,6 +164,39 @@
EXPECT_THAT(*str, StrValueEq(" This is what I think "));
}
+TEST_F(ResourceParserTest, ParseStringTruncateASCII) {
+ // Tuncate leading and trailing whitespace
+ EXPECT_TRUE(TestParse(R"(<string name="foo"> Hello </string>)"));
+
+ String* str = test::GetValue<String>(&table_, "string/foo");
+ ASSERT_THAT(str, NotNull());
+ EXPECT_THAT(*str->value, StrEq("Hello"));
+ EXPECT_THAT(str->untranslatable_sections, IsEmpty());
+
+ // AAPT does not truncate unicode whitespace
+ EXPECT_TRUE(TestParse(R"(<string name="foo2">\u0020\Hello\u0020</string>)"));
+
+ str = test::GetValue<String>(&table_, "string/foo2");
+ ASSERT_THAT(str, NotNull());
+ EXPECT_THAT(*str->value, StrEq(" Hello "));
+ EXPECT_THAT(str->untranslatable_sections, IsEmpty());
+
+ // Preserve non-ASCII whitespace including extended ASCII characters
+ EXPECT_TRUE(TestParse(R"(<string name="foo3"> Hello </string>)"));
+
+ str = test::GetValue<String>(&table_, "string/foo3");
+ ASSERT_THAT(str, NotNull());
+ EXPECT_THAT(*str->value, StrEq("\xC2\xA0Hello\xC2\xA0"));
+ EXPECT_THAT(str->untranslatable_sections, IsEmpty());
+
+ EXPECT_TRUE(TestParse(R"(<string name="foo4">2005年6月1日</string>)"));
+
+ str = test::GetValue<String>(&table_, "string/foo4");
+ ASSERT_THAT(str, NotNull());
+ EXPECT_THAT(*str->value, StrEq("2005年6月1日"));
+ EXPECT_THAT(str->untranslatable_sections, IsEmpty());
+}
+
TEST_F(ResourceParserTest, ParseStyledStringWithWhitespace) {
std::string input = R"(<string name="foo"> <b> My <i> favorite</i> string </b> </string>)";
ASSERT_TRUE(TestParse(input));
diff --git a/tools/aapt2/ResourceUtils.cpp b/tools/aapt2/ResourceUtils.cpp
index 8fc3d65..560077c 100644
--- a/tools/aapt2/ResourceUtils.cpp
+++ b/tools/aapt2/ResourceUtils.cpp
@@ -30,7 +30,6 @@
#include "util/Files.h"
#include "util/Util.h"
-using ::aapt::text::IsWhitespace;
using ::aapt::text::Utf8Iterator;
using ::android::StringPiece;
using ::android::StringPiece16;
@@ -807,7 +806,7 @@
Utf8Iterator iter(text);
while (iter.HasNext()) {
char32_t codepoint = iter.Next();
- if (!quote_ && text::IsWhitespace(codepoint)) {
+ if (!quote_ && iswspace(codepoint)) {
if (!last_codepoint_was_space_) {
// Emit a space if it's the first.
xml_string_.text += ' ';
diff --git a/tools/aapt2/cmd/Link.cpp b/tools/aapt2/cmd/Link.cpp
index 818ad20..a3b7664 100644
--- a/tools/aapt2/cmd/Link.cpp
+++ b/tools/aapt2/cmd/Link.cpp
@@ -2159,7 +2159,11 @@
"Syntax: path/to/output.apk:<config>[,<config>[...]].\n"
"On Windows, use a semicolon ';' separator instead.",
&split_args)
- .OptionalSwitch("-v", "Enables verbose logging.", &verbose);
+ .OptionalSwitch("-v", "Enables verbose logging.", &verbose)
+ .OptionalSwitch("--debug-mode",
+ "Inserts android:debuggable=\"true\" in to the application node of the\n"
+ "manifest, making the application debuggable even on production devices.",
+ &options.manifest_fixer_options.debug_mode);
if (!flags.Parse("aapt2 link", args, &std::cerr)) {
return 1;
diff --git a/tools/aapt2/link/ManifestFixer.cpp b/tools/aapt2/link/ManifestFixer.cpp
index 713db5b..165702c 100644
--- a/tools/aapt2/link/ManifestFixer.cpp
+++ b/tools/aapt2/link/ManifestFixer.cpp
@@ -354,6 +354,14 @@
uses_static_library_action.Action(RequiredAndroidAttribute("version"));
uses_static_library_action.Action(RequiredAndroidAttribute("certDigest"));
+ if (options_.debug_mode) {
+ application_action.Action([&](xml::Element* el) -> bool {
+ xml::Attribute *attr = el->FindOrCreateAttribute(xml::kSchemaAndroid, "debuggable");
+ attr->value = "true";
+ return true;
+ });
+ }
+
application_action["meta-data"] = meta_data_action;
application_action["activity"] = component_action;
diff --git a/tools/aapt2/link/ManifestFixer.h b/tools/aapt2/link/ManifestFixer.h
index 0caa52e..7d6fad2 100644
--- a/tools/aapt2/link/ManifestFixer.h
+++ b/tools/aapt2/link/ManifestFixer.h
@@ -58,10 +58,13 @@
// 'android:compileSdkVersionCodename' in the <manifest> tag.
Maybe<std::string> compile_sdk_version_codename;
- // Wether validation errors should be treated only as warnings. If this is 'true', then an
+ // Whether validation errors should be treated only as warnings. If this is 'true', then an
// incorrect node will not result in an error, but only as a warning, and the parsing will
// continue.
bool warn_validation = false;
+
+ // Whether to inject the android:debuggable="true" flag into the manifest
+ bool debug_mode = false;
};
// Verifies that the manifest is correctly formed and inserts defaults where specified with
diff --git a/tools/aapt2/link/ManifestFixer_test.cpp b/tools/aapt2/link/ManifestFixer_test.cpp
index ed98d71..8db9374 100644
--- a/tools/aapt2/link/ManifestFixer_test.cpp
+++ b/tools/aapt2/link/ManifestFixer_test.cpp
@@ -416,6 +416,68 @@
EXPECT_THAT(Verify(input), IsNull());
}
+TEST_F(ManifestFixerTest, ApplicationInjectDebuggable) {
+ ManifestFixerOptions options;
+ options.debug_mode = true;
+
+ std::string no_d = R"(
+ <manifest xmlns:android="http://schemas.android.com/apk/res/android"
+ package="android">
+ <application>
+ </application>
+ </manifest>)";
+
+ std::string false_d = R"(
+ <manifest xmlns:android="http://schemas.android.com/apk/res/android"
+ package="android">
+ <application android:debuggable="false">
+ </application>
+ </manifest>)";
+
+ std::string true_d = R"(
+ <manifest xmlns:android="http://schemas.android.com/apk/res/android"
+ package="android">
+ <application android:debuggable="true">
+ </application>
+ </manifest>)";
+
+ // Inject the debuggable attribute when the attribute is not present and the
+ // flag is present
+ std::unique_ptr<xml::XmlResource> manifest = VerifyWithOptions(no_d, options);
+ EXPECT_THAT(manifest->root.get()->FindChildWithAttribute(
+ {}, "application", xml::kSchemaAndroid, "debuggable", "true"), NotNull());
+
+ // Set the debuggable flag to true if the attribute is false and the flag is
+ // present
+ manifest = VerifyWithOptions(false_d, options);
+ EXPECT_THAT(manifest->root.get()->FindChildWithAttribute(
+ {}, "application", xml::kSchemaAndroid, "debuggable", "true"), NotNull());
+
+ // Keep debuggable flag true if the attribute is true and the flag is present
+ manifest = VerifyWithOptions(true_d, options);
+ EXPECT_THAT(manifest->root.get()->FindChildWithAttribute(
+ {}, "application", xml::kSchemaAndroid, "debuggable", "true"), NotNull());
+
+ // Do not inject the debuggable attribute when the attribute is not present
+ // and the flag is not present
+ manifest = Verify(no_d);
+ EXPECT_THAT(manifest->root.get()->FindChildWithAttribute(
+ {}, "application", xml::kSchemaAndroid, "debuggable", "true"), IsNull());
+
+ // Do not set the debuggable flag to true if the attribute is false and the
+ // flag is not present
+ manifest = Verify(false_d);
+ EXPECT_THAT(manifest->root.get()->FindChildWithAttribute(
+ {}, "application", xml::kSchemaAndroid, "debuggable", "true"), IsNull());
+
+ // Keep debuggable flag true if the attribute is true and the flag is not
+ // present
+ manifest = Verify(true_d);
+ EXPECT_THAT(manifest->root.get()->FindChildWithAttribute(
+ {}, "application", xml::kSchemaAndroid, "debuggable", "true"), NotNull());
+}
+
+
TEST_F(ManifestFixerTest, IgnoreNamespacedElements) {
std::string input = R"EOF(
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
diff --git a/tools/stats_log_api_gen/Android.bp b/tools/stats_log_api_gen/Android.bp
index 948422c..17819db 100644
--- a/tools/stats_log_api_gen/Android.bp
+++ b/tools/stats_log_api_gen/Android.bp
@@ -101,7 +101,6 @@
cflags: [
"-Wall",
"-Werror",
- "-fexceptions",
],
export_generated_headers: ["statslog.h"],
shared_libs: [
diff --git a/tools/stats_log_api_gen/main.cpp b/tools/stats_log_api_gen/main.cpp
index 499f254..057772f 100644
--- a/tools/stats_log_api_gen/main.cpp
+++ b/tools/stats_log_api_gen/main.cpp
@@ -101,7 +101,8 @@
fprintf(out, "// This file is autogenerated\n");
fprintf(out, "\n");
- fprintf(out, "#include <exception>\n");
+ fprintf(out, "#include <chrono>\n");
+ fprintf(out, "#include <thread>\n");
fprintf(out, "#include <log/log_event_list.h>\n");
fprintf(out, "#include <log/log.h>\n");
fprintf(out, "#include <statslog.h>\n");
@@ -212,7 +213,7 @@
int argIndex;
fprintf(out, "int\n");
- fprintf(out, "stats_write(int32_t code");
+ fprintf(out, "try_stats_write(int32_t code");
argIndex = 1;
for (vector<java_type_t>::const_iterator arg = signature->begin();
arg != signature->end(); arg++) {
@@ -247,10 +248,6 @@
if (chainField.javaType == JAVA_TYPE_STRING) {
fprintf(out, " if (%s_length != %s.size()) {\n",
attributionDecl.fields.front().name.c_str(), chainField.name.c_str());
- fprintf(out, " throw std::invalid_argument(\"attribution fields with"
- " diff length: %s vs %s\");\n",
- attributionDecl.fields.front().name.c_str(),
- chainField.name.c_str());
fprintf(out, " return -EINVAL;\n");
fprintf(out, " }\n");
}
@@ -289,12 +286,74 @@
fprintf(out, "\n");
}
+ for (set<vector<java_type_t>>::const_iterator signature = atoms.signatures.begin();
+ signature != atoms.signatures.end(); signature++) {
+ int argIndex;
+
+ fprintf(out, "int \n");
+ fprintf(out, "stats_write(int32_t code");
+ argIndex = 1;
+ for (vector<java_type_t>::const_iterator arg = signature->begin();
+ arg != signature->end(); arg++) {
+ if (*arg == JAVA_TYPE_ATTRIBUTION_CHAIN) {
+ for (auto chainField : attributionDecl.fields) {
+ if (chainField.javaType == JAVA_TYPE_STRING) {
+ fprintf(out, ", const std::vector<%s>& %s",
+ cpp_type_name(chainField.javaType),
+ chainField.name.c_str());
+ } else {
+ fprintf(out, ", const %s* %s, size_t %s_length",
+ cpp_type_name(chainField.javaType),
+ chainField.name.c_str(), chainField.name.c_str());
+ }
+ }
+ } else {
+ fprintf(out, ", %s arg%d", cpp_type_name(*arg), argIndex);
+ }
+ argIndex++;
+ }
+ fprintf(out, ")\n");
+
+ fprintf(out, "{\n");
+ fprintf(out, " int ret = 0;\n");
+
+ fprintf(out, " for(int retry = 0; retry < 3; ++retry) {\n");
+ fprintf(out, " ret = try_stats_write(code");
+
+ argIndex = 1;
+ for (vector<java_type_t>::const_iterator arg = signature->begin();
+ arg != signature->end(); arg++) {
+ if (*arg == JAVA_TYPE_ATTRIBUTION_CHAIN) {
+ for (auto chainField : attributionDecl.fields) {
+ if (chainField.javaType == JAVA_TYPE_STRING) {
+ fprintf(out, ", %s",
+ chainField.name.c_str());
+ } else {
+ fprintf(out, ", %s, %s_length",
+ chainField.name.c_str(), chainField.name.c_str());
+ }
+ }
+ } else {
+ fprintf(out, ", arg%d", argIndex);
+ }
+ argIndex++;
+ }
+ fprintf(out, ");\n");
+ fprintf(out, " if (ret >= 0) { return retry; }\n");
+ fprintf(out,
+ " std::this_thread::sleep_for(std::chrono::milliseconds(10 + 10 * retry));\n");
+ fprintf(out, " }\n");
+ fprintf(out, " return ret;\n");
+ fprintf(out, "}\n");
+ fprintf(out, "\n");
+ }
+
for (set<vector<java_type_t>>::const_iterator signature = atoms.non_chained_signatures.begin();
signature != atoms.non_chained_signatures.end(); signature++) {
int argIndex;
fprintf(out, "int\n");
- fprintf(out, "stats_write_non_chained(int32_t code");
+ fprintf(out, "try_stats_write_non_chained(int32_t code");
argIndex = 1;
for (vector<java_type_t>::const_iterator arg = signature->begin();
arg != signature->end(); arg++) {
@@ -331,6 +390,45 @@
fprintf(out, "}\n");
fprintf(out, "\n");
}
+
+ for (set<vector<java_type_t>>::const_iterator signature = atoms.non_chained_signatures.begin();
+ signature != atoms.non_chained_signatures.end(); signature++) {
+ int argIndex;
+
+ fprintf(out, "int\n");
+ fprintf(out, "stats_write_non_chained(int32_t code");
+ argIndex = 1;
+ for (vector<java_type_t>::const_iterator arg = signature->begin();
+ arg != signature->end(); arg++) {
+ fprintf(out, ", %s arg%d", cpp_type_name(*arg), argIndex);
+ argIndex++;
+ }
+ fprintf(out, ")\n");
+
+ fprintf(out, "{\n");
+
+ fprintf(out, " int ret = 0;\n");
+ fprintf(out, " for(int retry = 0; retry < 3; ++retry) {\n");
+ fprintf(out, " ret = try_stats_write_non_chained(code");
+
+ argIndex = 1;
+ for (vector<java_type_t>::const_iterator arg = signature->begin();
+ arg != signature->end(); arg++) {
+ fprintf(out, ", arg%d", argIndex);
+ argIndex++;
+ }
+ fprintf(out, ");\n");
+ fprintf(out, " if (ret >= 0) { return retry; }\n");
+ fprintf(out,
+ " std::this_thread::sleep_for(std::chrono::milliseconds(10 + 10 * retry));\n");
+ fprintf(out, " }\n");
+ fprintf(out, " return ret;\n");
+ fprintf(out, "}\n");
+
+ fprintf(out, "\n");
+ }
+
+
// Print footer
fprintf(out, "\n");
fprintf(out, "} // namespace util\n");
@@ -775,10 +873,6 @@
fprintf(out, " if (%s_length != %s_length) {\n",
chainField.name.c_str(),
attributionDecl.fields.front().name.c_str());
- fprintf(out, " jniThrowException(env, "
- "\"java/lang/IllegalArgumentException\", "
- "\"invalid attribution field(%s) length.\");\n",
- chainField.name.c_str());
fprintf(out, " return -EINVAL;\n");
fprintf(out, " }\n");
}
diff --git a/wifi/java/android/net/wifi/IWifiManager.aidl b/wifi/java/android/net/wifi/IWifiManager.aidl
index 2f7b50d..b333126 100644
--- a/wifi/java/android/net/wifi/IWifiManager.aidl
+++ b/wifi/java/android/net/wifi/IWifiManager.aidl
@@ -143,7 +143,7 @@
WifiConfiguration getWifiApConfiguration();
- void setWifiApConfiguration(in WifiConfiguration wifiConfig, String packageName);
+ boolean setWifiApConfiguration(in WifiConfiguration wifiConfig, String packageName);
Messenger getWifiServiceMessenger(String packageName);
diff --git a/wifi/java/android/net/wifi/WifiManager.java b/wifi/java/android/net/wifi/WifiManager.java
index 433285b..9c6c8a9 100644
--- a/wifi/java/android/net/wifi/WifiManager.java
+++ b/wifi/java/android/net/wifi/WifiManager.java
@@ -2141,7 +2141,8 @@
}
/**
- * Sets the Wi-Fi AP Configuration.
+ * Sets the Wi-Fi AP Configuration. The AP configuration must either be open or
+ * WPA2 PSK networks.
* @return {@code true} if the operation succeeded, {@code false} otherwise
*
* @hide
@@ -2150,8 +2151,7 @@
@RequiresPermission(android.Manifest.permission.CHANGE_WIFI_STATE)
public boolean setWifiApConfiguration(WifiConfiguration wifiConfig) {
try {
- mService.setWifiApConfiguration(wifiConfig, mContext.getOpPackageName());
- return true;
+ return mService.setWifiApConfiguration(wifiConfig, mContext.getOpPackageName());
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
diff --git a/wifi/tests/src/android/net/wifi/WifiManagerTest.java b/wifi/tests/src/android/net/wifi/WifiManagerTest.java
index f3a78bd..f3ffcad 100644
--- a/wifi/tests/src/android/net/wifi/WifiManagerTest.java
+++ b/wifi/tests/src/android/net/wifi/WifiManagerTest.java
@@ -1034,4 +1034,40 @@
verifyNoMoreInteractions(mWifiService);
}
+ /**
+ * Verify that a successful call properly returns true.
+ */
+ @Test
+ public void testSetWifiApConfigurationSuccessReturnsTrue() throws Exception {
+ WifiConfiguration apConfig = new WifiConfiguration();
+
+ when(mWifiService.setWifiApConfiguration(eq(apConfig), eq(TEST_PACKAGE_NAME)))
+ .thenReturn(true);
+ assertTrue(mWifiManager.setWifiApConfiguration(apConfig));
+ }
+
+ /**
+ * Verify that a failed call properly returns false.
+ */
+ @Test
+ public void testSetWifiApConfigurationFailureReturnsFalse() throws Exception {
+ WifiConfiguration apConfig = new WifiConfiguration();
+
+ when(mWifiService.setWifiApConfiguration(eq(apConfig), eq(TEST_PACKAGE_NAME)))
+ .thenReturn(false);
+ assertFalse(mWifiManager.setWifiApConfiguration(apConfig));
+ }
+
+ /**
+ * Verify Exceptions are rethrown when underlying calls to WifiService throw exceptions.
+ */
+ @Test
+ public void testSetWifiApConfigurationRethrowsException() throws Exception {
+ doThrow(new SecurityException()).when(mWifiService).setWifiApConfiguration(any(), any());
+
+ try {
+ mWifiManager.setWifiApConfiguration(new WifiConfiguration());
+ fail("setWifiApConfiguration should rethrow Exceptions from WifiService");
+ } catch (SecurityException e) { }
+ }
}